00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <gtk/gtk.h>
00014
00015 #include <celengine/astro.h>
00016 #include <celengine/simulation.h>
00017 #include <celestia/eclipsefinder.h>
00018
00019 #include "dialog-eclipse.h"
00020 #include "common.h"
00021
00022
00023
00024 static void calDateSelect(GtkCalendar *calendar, GtkToggleButton *button);
00025 static void showCalPopup(GtkToggleButton *button, EclipseData *ed);
00026 static gint eclipseGoto(GtkButton*, EclipseData* ed);
00027 static gint eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed);
00028 static void eclipseCompute(GtkButton* button, EclipseData* ed);
00029 static void eclipseBodySelect(GtkMenuShell* menu, EclipseData* ed);
00030 static void eclipseTypeSelect(GtkMenuShell* menu, EclipseData* ed);
00031 static void listEclipseSelect(GtkTreeSelection* sel, EclipseData* ed);
00032 static void eclipseDestroy(GtkWidget* w, gint, EclipseData* ed);
00033
00034
00035 static void setButtonDateString(GtkToggleButton *button, int year, int month, int day);
00036
00037
00038
00039 void dialogEclipseFinder(AppData* app)
00040 {
00041 EclipseData* ed = g_new0(EclipseData, 1);
00042 selDate* d1 = g_new0(selDate, 1);
00043 selDate* d2 = g_new0(selDate, 1);
00044 ed->d1 = d1;
00045 ed->d2 = d2;
00046 ed->app = app;
00047 ed->eclipseList = NULL;
00048 ed->eclipseListStore = NULL;
00049 ed->bSolar = TRUE;
00050 sprintf(ed->body, "%s", eclipsePlanetTitles[0]);
00051 ed->sel = NULL;
00052
00053 ed->window = GTK_DIALOG(gtk_dialog_new_with_buttons("Eclipse Finder",
00054 GTK_WINDOW(app->mainWindow),
00055 GTK_DIALOG_DESTROY_WITH_PARENT,
00056 GTK_STOCK_OK,
00057 GTK_RESPONSE_OK,
00058 NULL));
00059 gtk_window_set_modal(GTK_WINDOW(ed->window), FALSE);
00060
00061 GtkWidget *mainbox = gtk_vbox_new(FALSE, CELSPACING);
00062 gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING);
00063 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ed->window)->vbox), mainbox, TRUE, TRUE, 0);
00064
00065 GtkWidget *scrolled_win = gtk_scrolled_window_new (NULL, NULL);
00066
00067 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_win),
00068 GTK_POLICY_AUTOMATIC,
00069 GTK_POLICY_ALWAYS);
00070 gtk_box_pack_start(GTK_BOX(mainbox), scrolled_win, TRUE, TRUE, 0);
00071
00072
00073
00074
00075
00076 ed->eclipseListStore = gtk_list_store_new(12,
00077 G_TYPE_STRING,
00078 G_TYPE_STRING,
00079 G_TYPE_STRING,
00080 G_TYPE_STRING,
00081 G_TYPE_STRING,
00082 G_TYPE_INT,
00083 G_TYPE_INT,
00084 G_TYPE_INT,
00085 G_TYPE_INT,
00086 G_TYPE_INT,
00087 G_TYPE_INT,
00088 G_TYPE_POINTER);
00089 ed->eclipseList = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ed->eclipseListStore));
00090
00091 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ed->eclipseList), TRUE);
00092 gtk_container_add(GTK_CONTAINER(scrolled_win), ed->eclipseList);
00093
00094 GtkCellRenderer *renderer;
00095 GtkTreeViewColumn *column;
00096
00097
00098 for (int i=0; i<5; i++) {
00099 renderer = gtk_cell_renderer_text_new();
00100 column = gtk_tree_view_column_new_with_attributes (eclipseTitles[i], renderer, "text", i, NULL);
00101 gtk_tree_view_append_column(GTK_TREE_VIEW(ed->eclipseList), column);
00102 }
00103
00104
00105 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ed->eclipseList));
00106 g_signal_connect(selection, "changed", G_CALLBACK(listEclipseSelect), ed);
00107
00108
00109 GtkWidget *label;
00110 GtkWidget *hbox;
00111
00112
00113 hbox = gtk_hbox_new(FALSE, CELSPACING);
00114
00115 label = gtk_label_new("Find");
00116 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
00117
00118 GtkWidget* menuTypeBox = gtk_option_menu_new();
00119 gtk_box_pack_start(GTK_BOX(hbox), menuTypeBox, FALSE, FALSE, 0);
00120
00121 label = gtk_label_new("eclipse on");
00122 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
00123
00124 GtkWidget* menuBodyBox = gtk_option_menu_new();
00125 gtk_box_pack_start(GTK_BOX(hbox), menuBodyBox, FALSE, FALSE, 0);
00126
00127 gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0);
00128
00129 hbox = gtk_hbox_new(FALSE, CELSPACING);
00130
00131 label = gtk_label_new("From");
00132 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
00133
00134
00135 astro::Date datenow(app->simulation->getTime());
00136
00137
00138 ed->d1->year = datenow.year - 1;
00139 ed->d1->month = datenow.month;
00140 ed->d1->day = datenow.day;
00141
00142
00143 ed->d2->year = ed->d1->year + 2;
00144 ed->d2->month = ed->d1->month;
00145 ed->d2->day = ed->d1->day;
00146
00147 GtkWidget* date1Button = gtk_toggle_button_new();
00148 setButtonDateString(GTK_TOGGLE_BUTTON(date1Button), ed->d1->year, ed->d1->month, ed->d1->day);
00149 g_object_set_data(G_OBJECT(date1Button), "eclipsedata", ed->d1);
00150 gtk_box_pack_start(GTK_BOX(hbox), date1Button, FALSE, FALSE, 0);
00151
00152 label = gtk_label_new("to");
00153 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
00154
00155 GtkWidget* date2Button = gtk_toggle_button_new();
00156 setButtonDateString(GTK_TOGGLE_BUTTON(date2Button), ed->d2->year, ed->d2->month, ed->d2->day);
00157 g_object_set_data(G_OBJECT(date2Button), "eclipsedata", ed->d2);
00158 gtk_box_pack_start(GTK_BOX(hbox), date2Button, FALSE, FALSE, 0);
00159
00160 gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0);
00161
00162
00163
00164 hbox = gtk_hbox_new(TRUE, CELSPACING);
00165 if (buttonMake(hbox, "Compute", (GtkSignalFunc)eclipseCompute, ed))
00166 return;
00167 if (buttonMake(hbox, "Set Date and Go to Planet", (GtkSignalFunc)eclipseGoto, ed))
00168 return;
00169 gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0);
00170
00171
00172 GtkWidget *item;
00173
00174 GtkWidget* menuType = gtk_menu_new();
00175 for (int i = 0; eclipseTypeTitles[i] != NULL; i++)
00176 {
00177 item = gtk_menu_item_new_with_label(eclipseTypeTitles[i]);
00178 gtk_menu_append(GTK_MENU(menuType), item);
00179 gtk_widget_show(item);
00180 }
00181 gtk_option_menu_set_menu(GTK_OPTION_MENU(menuTypeBox), menuType);
00182
00183 GtkWidget* menuBody = gtk_menu_new();
00184 for (int i = 0; eclipsePlanetTitles[i] != NULL; i++)
00185 {
00186 item = gtk_menu_item_new_with_label(eclipsePlanetTitles[i]);
00187 gtk_menu_append(GTK_MENU(menuBody), item);
00188 gtk_widget_show(item);
00189 }
00190 gtk_option_menu_set_menu(GTK_OPTION_MENU(menuBodyBox), menuBody);
00191
00192
00193 g_signal_connect(GTK_OBJECT(menuType), "selection-done", G_CALLBACK(eclipseTypeSelect), ed);
00194 g_signal_connect(GTK_OBJECT(menuBody), "selection-done", G_CALLBACK(eclipseBodySelect), ed);
00195
00196
00197 g_signal_connect(GTK_OBJECT(ed->eclipseList), "button-press-event", G_CALLBACK(eclipse2Click), ed);
00198
00199 g_signal_connect(GTK_OBJECT(date1Button), "toggled", G_CALLBACK(showCalPopup), ed);
00200 g_signal_connect(GTK_OBJECT(date2Button), "toggled", G_CALLBACK(showCalPopup), ed);
00201 g_signal_connect(ed->window, "response", G_CALLBACK(eclipseDestroy), ed);
00202
00203 gtk_widget_set_usize(GTK_WIDGET(ed->window), 400, 400);
00204 gtk_widget_show_all(GTK_WIDGET(ed->window));
00205 }
00206
00207
00208
00209 static void calDateSelect(GtkCalendar *calendar, GtkToggleButton *button)
00210 {
00211
00212 guint year, month, day;
00213 gtk_calendar_get_date(calendar, &year, &month, &day);
00214
00215
00216 selDate* date = (selDate *)g_object_get_data(G_OBJECT(button), "eclipsedata");
00217 date->year = year;
00218 date->month = month + 1;
00219 date->day = day;
00220
00221
00222 setButtonDateString(button, year, month + 1, day);
00223
00224
00225 gtk_toggle_button_set_active(button, !gtk_toggle_button_get_active(button));
00226 }
00227
00228
00229
00230 static void showCalPopup(GtkToggleButton *button, EclipseData *ed)
00231 {
00232 GtkWidget* calwindow = GTK_WIDGET(g_object_get_data(G_OBJECT(button), "calendar"));
00233
00234 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
00235 {
00236
00237 if (!calwindow)
00238 {
00239 calwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00240
00241
00242 gtk_window_set_modal(GTK_WINDOW(calwindow), TRUE);
00243 gtk_window_set_type_hint(GTK_WINDOW(calwindow), GDK_WINDOW_TYPE_HINT_DOCK);
00244 gtk_window_set_decorated(GTK_WINDOW(calwindow), FALSE);
00245 gtk_window_set_resizable(GTK_WINDOW(calwindow), FALSE);
00246 gtk_window_stick(GTK_WINDOW(calwindow));
00247
00248 GtkWidget* calendar = gtk_calendar_new();
00249
00250
00251 selDate* date = (selDate *)g_object_get_data(G_OBJECT(button), "eclipsedata");
00252
00253 gtk_calendar_select_month(GTK_CALENDAR(calendar), date->month - 1, date->year);
00254 gtk_calendar_select_day(GTK_CALENDAR(calendar), date->day);
00255
00256 gtk_container_add(GTK_CONTAINER(calwindow), calendar);
00257 gtk_widget_show(calendar);
00258
00259 int x, y, i, j;
00260 gdk_window_get_origin(GDK_WINDOW(GTK_WIDGET(button)->window), &x, &y);
00261 gtk_widget_translate_coordinates(GTK_WIDGET(button), GTK_WIDGET(ed->window), 10, 10, &i, &j);
00262
00263 gtk_window_move(GTK_WINDOW(calwindow), x + i, y + j);
00264
00265 g_signal_connect(calendar, "day-selected-double-click", G_CALLBACK(calDateSelect), button);
00266
00267 gtk_window_present(GTK_WINDOW(calwindow));
00268
00269 g_object_set_data_full(G_OBJECT (button), "calendar",
00270 calwindow, (GDestroyNotify)gtk_widget_destroy);
00271 }
00272 }
00273 else
00274 {
00275
00276 if (calwindow)
00277 {
00278
00279 g_object_set_data(G_OBJECT (button), "calendar", NULL);
00280 calwindow = NULL;
00281 }
00282 }
00283 }
00284
00285
00286
00287 static gint eclipseGoto(GtkButton*, EclipseData* ed)
00288 {
00289 GValue value = { 0, 0 };
00290 GtkTreeIter iter;
00291 GtkTreeModel* model;
00292 int time[6];
00293 Simulation* sim = ed->app->simulation;
00294
00295
00296 if (ed->sel == NULL)
00297 return FALSE;
00298
00299
00300 if (!gtk_tree_selection_get_selected(ed->sel, &model, &iter))
00301 return FALSE;
00302
00303
00304
00305 for (int i = 0; i < 6; i++)
00306 {
00307 gtk_tree_model_get_value(model, &iter, i+5, &value);
00308 time[i] = g_value_get_int(&value);
00309 g_value_unset(&value);
00310 }
00311
00312
00313 gtk_tree_model_get_value(model, &iter, 11, &value);
00314 Body* body = (Body *)g_value_get_pointer(&value);
00315 g_value_unset(&value);
00316
00317
00318 astro::Date d(time[0], time[1], time[2]);
00319 d.hour = time[3];
00320 d.minute = time[4];
00321 d.seconds = (double)time[5];
00322 sim->setTime((double)d);
00323
00324
00325 Selection target(body);
00326 Selection ref(body->getSystem()->getStar());
00327
00328
00329
00330
00331 sim->setFrame(FrameOfReference(astro::PhaseLock, target, ref));
00332 sim->update(0.0);
00333
00334 double distance = astro::kilometersToMicroLightYears(target.radius() * 4.0);
00335 RigidTransform to;
00336 to.rotation = Quatd::yrotation(PI);
00337 to.translation = Point3d(0, 0, -distance);
00338 sim->gotoLocation(to, 2.5);
00339
00340 return TRUE;
00341 }
00342
00343
00344
00345 static gint eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed)
00346 {
00347 if (event->type == GDK_2BUTTON_PRESS) {
00348
00349 return eclipseGoto(NULL, ed);
00350 }
00351
00352 return FALSE;
00353 }
00354
00355
00356
00357 static void eclipseCompute(GtkButton* button, EclipseData* ed)
00358 {
00359 GtkTreeIter iter;
00360
00361
00362 gdk_window_set_cursor(GTK_WIDGET(button)->window, gdk_cursor_new(GDK_WATCH));
00363 gtk_main_iteration();
00364
00365
00366 gtk_list_store_clear(ed->eclipseListStore);
00367
00368
00369 astro::Date from(ed->d1->year, ed->d1->month, ed->d1->day);
00370 astro::Date to(ed->d2->year, ed->d2->month, ed->d2->day);
00371
00372
00373 EclipseFinder ef(ed->app->core, ed->body, ed->bSolar ? Eclipse::Solar : Eclipse::Moon, (double)from, (double)to);
00374 vector<Eclipse> eclipseListRaw = ef.getEclipses();
00375
00376 for (std::vector<Eclipse>::iterator i = eclipseListRaw.begin();
00377 i != eclipseListRaw.end();
00378 i++)
00379 {
00380
00381
00382 if ((*i).planete == "None") {
00383 gtk_list_store_append(ed->eclipseListStore, &iter);
00384 gtk_list_store_set(ed->eclipseListStore, &iter, 0, (*i).planete.c_str(), -1);
00385 continue;
00386 }
00387
00388 char d[12], strStart[10], strEnd[10];
00389 astro::Date start((*i).startTime);
00390 astro::Date end((*i).endTime);
00391
00392 sprintf(d, "%d-%02d-%02d", (*i).date->year, (*i).date->month, (*i).date->day);
00393 sprintf(strStart, "%02d:%02d:%02d", start.hour, start.minute, (int)start.seconds);
00394 sprintf(strEnd, "%02d:%02d:%02d", end.hour, end.minute, (int)end.seconds);
00395
00396
00397 astro::Date timeToSet = (start + end) / 2.0f;
00398
00399
00400
00401 gtk_list_store_append(ed->eclipseListStore, &iter);
00402 gtk_list_store_set(ed->eclipseListStore, &iter,
00403 0, (*i).planete.c_str(),
00404 1, (*i).sattelite.c_str(),
00405 2, d,
00406 3, strStart,
00407 4, strEnd,
00408 5, timeToSet.year,
00409 6, timeToSet.month,
00410 7, timeToSet.day,
00411 8, timeToSet.hour,
00412 9, timeToSet.minute,
00413 10, (int)timeToSet.seconds,
00414 11, (*i).body,
00415 -1);
00416 }
00417
00418
00419 gdk_window_set_cursor(GTK_WIDGET(button)->window, gdk_cursor_new(GDK_LEFT_PTR));
00420 }
00421
00422
00423
00424 static void eclipseBodySelect(GtkMenuShell* menu, EclipseData* ed)
00425 {
00426 GtkWidget* item = gtk_menu_get_active(GTK_MENU(menu));
00427
00428 GList* list = gtk_container_children(GTK_CONTAINER(menu));
00429 int itemIndex = g_list_index(list, item);
00430
00431
00432 sprintf(ed->body, "%s", eclipsePlanetTitles[itemIndex]);
00433 }
00434
00435
00436
00437 static void eclipseTypeSelect(GtkMenuShell* menu, EclipseData* ed)
00438 {
00439 GtkWidget* item = gtk_menu_get_active(GTK_MENU(menu));
00440
00441 GList* list = gtk_container_children(GTK_CONTAINER(menu));
00442 int itemIndex = g_list_index(list, item);
00443
00444
00445 if (itemIndex == 0)
00446 ed->bSolar = 1;
00447
00448 else
00449 ed->bSolar = 0;
00450 }
00451
00452
00453
00454 static void listEclipseSelect(GtkTreeSelection* sel, EclipseData* ed)
00455 {
00456
00457 ed->sel = sel;
00458 }
00459
00460
00461
00462 static void eclipseDestroy(GtkWidget* w, gint, EclipseData* ed)
00463 {
00464 gtk_widget_destroy(GTK_WIDGET(w));
00465 g_free(ed->d1);
00466 g_free(ed->d2);
00467 g_free(ed);
00468 }
00469
00470
00471
00472 static void setButtonDateString(GtkToggleButton *button, int year, int month, int day)
00473 {
00474 char date[50];
00475 sprintf(date, "%d %s %d", day, monthOptions[month - 1], year);
00476
00477 gtk_button_set_label(GTK_BUTTON(button), date);
00478 }