1 /*
2 * Celestia GTK+ Front-End
3 * Copyright (C) 2005 Pat Suwalski <pat@suwalski.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * $Id: actions.cpp,v 1.17 2008-01-25 01:05:14 suwalski Exp $
11 */
12
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif /* HAVE_CONFIG_H */
16
17 #include <cstring>
18 #include <fstream>
19 #include <gtk/gtk.h>
20
21 #ifdef GNOME
22 #include <gconf/gconf-client.h>
23 #endif /* GNOME */
24
25 #include <celengine/body.h>
26 #include <celengine/gl.h>
27 #include <celengine/glext.h>
28 #include <celengine/simulation.h>
29 #include <celengine/cmdparser.h>
30 #include <celengine/render.h>
31 #include <celestia/celestiacore.h>
32 #include <celestia/imagecapture.h>
33 #include <celestia/url.h>
34 #include <celutil/filetype.h>
35 #ifdef THEORA
36 #include <celestia/oggtheoracapture.h>
37 #endif
38
39 #include "actions.h"
40 #include "common.h"
41 #include "dialog-eclipse.h"
42 #include "dialog-goto.h"
43 #include "dialog-options.h"
44 #include "dialog-solar.h"
45 #include "dialog-star.h"
46 #include "dialog-time.h"
47 #include "dialog-tour.h"
48
49 #ifdef GNOME
50 #include "settings-gconf.h"
51 #else
52 #include "settings-file.h"
53 #endif /* GNOME */
54
55
56 /* Declarations: Action Helpers */
57 static void openScript(const char* filename, AppData* app);
58 static void captureImage(const char* filename, AppData* app);
59 #ifdef THEORA
60 static void captureMovie(const char* filename, int aspect, float fps, float quality, AppData* app);
61 #endif
62 static void textInfoDialog(const char *txt, const char *title, AppData* app);
63 static void setRenderFlag(AppData* a, int flag, gboolean state);
64 static void setOrbitMask(AppData* a, int mask, gboolean state);
65 static void setLabelMode(AppData* a, int mode, gboolean state);
66
67
68 /* File -> Copy URL */
actionCopyURL(GtkAction *,AppData * app)69 void actionCopyURL(GtkAction*, AppData* app)
70 {
71 GtkClipboard* cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
72 CelestiaState appState;
73 appState.captureState(app->core);
74 Url url(appState, Url::CurrentVersion);
75 gtk_clipboard_set_text(cb, url.getAsString().c_str(), -1);
76 }
77
78
79 /* File -> Open URL */
actionOpenURL(GtkAction *,AppData * app)80 void actionOpenURL(GtkAction*, AppData* app)
81 {
82 GtkWidget* dialog = gtk_dialog_new_with_buttons("Enter cel:// URL",
83 GTK_WINDOW(app->mainWindow),
84 GTK_DIALOG_MODAL,
85 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
86 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
87 NULL);
88
89 /* Create a new entry box with default text, all selected */
90 GtkWidget* entry = gtk_entry_new();
91 gtk_entry_set_width_chars(GTK_ENTRY(entry), 80);
92 gtk_entry_set_text(GTK_ENTRY(entry), "cel://");
93 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
94
95 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, TRUE, TRUE, CELSPACING);
96 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
97 gtk_widget_show_all(dialog);
98
99 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
100 app->core->goToUrl(gtk_entry_get_text(GTK_ENTRY(entry)));
101
102 gtk_widget_destroy(dialog);
103 }
104
105
106 /* File -> Open Script... */
actionOpenScript(GtkAction *,AppData * app)107 void actionOpenScript(GtkAction*, AppData* app)
108 {
109 GtkWidget* fs = gtk_file_chooser_dialog_new("Open Script.",
110 GTK_WINDOW(app->mainWindow),
111 GTK_FILE_CHOOSER_ACTION_OPEN,
112 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
113 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
114 NULL);
115
116 #if GTK_CHECK_VERSION(2, 7, 0)
117 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fs), TRUE);
118 #endif /* GTK_CHECK_VERSION */
119
120 gtk_dialog_set_default_response(GTK_DIALOG(fs), GTK_RESPONSE_ACCEPT);
121 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), g_get_home_dir());
122
123 GtkFileFilter* filter = gtk_file_filter_new();
124 gtk_file_filter_set_name(filter, "Celestia Scripts");
125
126 gtk_file_filter_add_pattern(filter, "*.cel");
127
128 #ifdef CELX
129 gtk_file_filter_add_pattern(filter, "*.celx");
130 gtk_file_filter_add_pattern(filter, "*.clx");
131 #endif /* CELX */
132
133 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter);
134
135 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
136 {
137 char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
138 openScript(filename, app);
139 g_free(filename);
140 }
141
142 gtk_widget_destroy(fs);
143 }
144
145
146 /* File -> Capture Image... */
actionCaptureImage(GtkAction *,AppData * app)147 void actionCaptureImage(GtkAction*, AppData* app)
148 {
149 GtkWidget* fs = gtk_file_chooser_dialog_new("Save Image to File",
150 GTK_WINDOW(app->mainWindow),
151 GTK_FILE_CHOOSER_ACTION_SAVE,
152 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
153 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
154 NULL);
155
156 GtkFileFilter* filter = gtk_file_filter_new();
157 gtk_file_filter_set_name(filter, "PNG and JPEG Images");
158 gtk_file_filter_add_pattern(filter, "*.jpeg");
159 gtk_file_filter_add_pattern(filter, "*.jpg");
160 gtk_file_filter_add_pattern(filter, "*.png");
161 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter);
162
163 #if GTK_CHECK_VERSION(2, 7, 0)
164 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fs), TRUE);
165 #endif /* GTK_CHECK_VERSION */
166
167 gtk_dialog_set_default_response(GTK_DIALOG(fs), GTK_RESPONSE_ACCEPT);
168 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), g_get_home_dir());
169
170 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
171 {
172 char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
173 gtk_widget_destroy(fs);
174 for (int i=0; i < 10 && gtk_events_pending ();i++)
175 gtk_main_iteration ();
176 captureImage(filename, app);
177 g_free(filename);
178 }
179 else
180 {
181 gtk_widget_destroy(fs);
182 }
183 }
184
185 /* File -> Capture Movie... */
actionCaptureMovie(GtkAction *,AppData * app)186 void actionCaptureMovie(GtkAction*, AppData* app)
187 {
188 #ifdef THEORA
189 // TODO: The menu item should be disable so that the user doesn't even
190 // have the opportunity to record two movies simultaneously; the only
191 // thing missing to make this happen is notification when recording
192 // is complete.
193 if (app->core->isCaptureActive())
194 {
195 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
196 GTK_DIALOG_DESTROY_WITH_PARENT,
197 GTK_MESSAGE_ERROR,
198 GTK_BUTTONS_OK,
199 "Stop current movie capture before starting another one.");
200 gtk_dialog_run(GTK_DIALOG(errBox));
201 gtk_widget_destroy(errBox);
202 return;
203 }
204
205 GtkWidget* fs = gtk_file_chooser_dialog_new("Save Ogg Theora Movie to File",
206 GTK_WINDOW(app->mainWindow),
207 GTK_FILE_CHOOSER_ACTION_SAVE,
208 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
209 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
210 NULL);
211
212 GtkFileFilter* filter = gtk_file_filter_new();
213 gtk_file_filter_set_name(filter, "Ogg Files");
214 gtk_file_filter_add_pattern(filter, "*.ogg");
215 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter);
216
217 #if GTK_CHECK_VERSION(2, 7, 0)
218 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fs), TRUE);
219 #endif /* GTK_CHECK_VERSION */
220
221 gtk_dialog_set_default_response(GTK_DIALOG(fs), GTK_RESPONSE_ACCEPT);
222 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), g_get_home_dir());
223
224 GtkWidget* hbox = gtk_hbox_new(FALSE, CELSPACING);
225 gtk_container_set_border_width(GTK_CONTAINER(hbox), CELSPACING);
226
227 GtkWidget* rlabel = gtk_label_new("Aspect Ratio:");
228 gtk_box_pack_start(GTK_BOX(hbox), rlabel, TRUE, TRUE, 0);
229
230 GtkWidget* aspectmenubox = gtk_combo_box_new_text();
231 gtk_combo_box_append_text(GTK_COMBO_BOX(aspectmenubox), "1:1");
232 gtk_combo_box_append_text(GTK_COMBO_BOX(aspectmenubox), "4:3");
233 gtk_combo_box_append_text(GTK_COMBO_BOX(aspectmenubox), "16:9");
234 gtk_combo_box_append_text(GTK_COMBO_BOX(aspectmenubox), "Display");
235 gtk_combo_box_set_active(GTK_COMBO_BOX(aspectmenubox), 0);
236 gtk_box_pack_start(GTK_BOX(hbox), aspectmenubox, FALSE, FALSE, 0);
237
238 GtkWidget* flabel = gtk_label_new("Frame Rate:");
239 gtk_box_pack_start(GTK_BOX(hbox), flabel, TRUE, TRUE, 0);
240
241 GtkWidget* fpsspin = gtk_spin_button_new_with_range(5.0, 30.0, 0.01);
242 gtk_box_pack_start(GTK_BOX(hbox), fpsspin, TRUE, TRUE, 0);
243 gtk_spin_button_set_value(GTK_SPIN_BUTTON(fpsspin), 12.0);
244 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(fpsspin), 0.01, 1.0);
245
246 GtkWidget* qlabel = gtk_label_new("Video Quality:");
247 gtk_box_pack_start(GTK_BOX(hbox), qlabel, TRUE, TRUE, 0);
248
249 GtkWidget* qspin = gtk_spin_button_new_with_range(0.0, 10.0, 1.0);
250 gtk_box_pack_start(GTK_BOX(hbox), qspin, TRUE, TRUE, 0);
251 gtk_spin_button_set_value(GTK_SPIN_BUTTON(qspin), 10.0);
252
253 gtk_widget_show_all(hbox);
254 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(fs), hbox);
255
256 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
257 {
258 char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
259 int aspect = gtk_combo_box_get_active(GTK_COMBO_BOX(aspectmenubox));
260 double fps = gtk_spin_button_get_value(GTK_SPIN_BUTTON(fpsspin));
261 double quality = gtk_spin_button_get_value(GTK_SPIN_BUTTON(qspin));
262
263 gtk_widget_destroy(fs);
264 for (int i=0; i < 10 && gtk_events_pending ();i++)
265 gtk_main_iteration ();
266 captureMovie(filename, aspect, fps, quality, app);
267 g_free(filename);
268 }
269 else
270 {
271 gtk_widget_destroy(fs);
272 }
273 #else
274 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
275 GTK_DIALOG_DESTROY_WITH_PARENT,
276 GTK_MESSAGE_ERROR,
277 GTK_BUTTONS_OK,
278 "Movie support was not included. To use re-build with --enable-theora.");
279 gtk_dialog_run(GTK_DIALOG(errBox));
280 gtk_widget_destroy(errBox);
281 #endif
282 }
283
284
actionQuit(GtkAction *,AppData * app)285 void actionQuit(GtkAction*, AppData* app)
286 {
287 #ifdef GNOME
288 saveSettingsGConf(app);
289 #else
290 saveSettingsFile(app);
291 #endif /* GNOME */
292
293 gtk_main_quit();
294 }
295
296
actionSelectSol(GtkAction *,AppData * app)297 void actionSelectSol(GtkAction*, AppData* app)
298 {
299 app->core->charEntered('H');
300 }
301
302
actionTourGuide(GtkAction *,AppData * app)303 void actionTourGuide(GtkAction*, AppData* app)
304 {
305 dialogTourGuide(app);
306 }
307
308
actionSearchObject(GtkAction *,AppData * app)309 void actionSearchObject(GtkAction*, AppData* app)
310 {
311 GtkWidget* dialog = gtk_dialog_new_with_buttons("Select Object",
312 GTK_WINDOW(app->mainWindow),
313 GTK_DIALOG_DESTROY_WITH_PARENT,
314 GTK_STOCK_OK, GTK_RESPONSE_OK,
315 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
316 NULL);
317
318 GtkWidget* box = gtk_hbox_new(FALSE, CELSPACING);
319 gtk_container_set_border_width(GTK_CONTAINER(box), CELSPACING);
320 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), box, TRUE, TRUE, 0);
321
322 GtkWidget* label = gtk_label_new("Object name");
323 gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
324
325 GtkWidget* entry = gtk_entry_new();
326 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
327
328 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
329 gtk_widget_show_all(GTK_WIDGET(dialog));
330
331 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
332 {
333 const gchar* name = gtk_entry_get_text(GTK_ENTRY(entry));
334 if (name != NULL)
335 {
336 Selection sel = app->simulation->findObject(name);
337 if (!sel.empty())
338 app->simulation->setSelection(sel);
339 }
340 }
341
342 gtk_widget_destroy(GTK_WIDGET(dialog));
343 }
344
345
actionGotoObject(GtkAction *,AppData * app)346 void actionGotoObject(GtkAction*, AppData* app)
347 {
348 dialogGotoObject(app);
349 }
350
351
actionCenterSelection(GtkAction *,AppData * app)352 void actionCenterSelection(GtkAction*, AppData* app)
353 {
354 app->core->charEntered('c');
355 }
356
357
actionGotoSelection(GtkAction *,AppData * app)358 void actionGotoSelection(GtkAction*, AppData* app)
359 {
360 app->core->charEntered('G');
361 }
362
363
actionFollowSelection(GtkAction *,AppData * app)364 void actionFollowSelection(GtkAction*, AppData* app)
365 {
366 app->core->charEntered('F');
367 }
368
369
actionSyncSelection(GtkAction *,AppData * app)370 void actionSyncSelection(GtkAction*, AppData* app)
371 {
372 app->core->charEntered('Y');
373 }
374
375
actionTrackSelection(GtkAction *,AppData * app)376 void actionTrackSelection(GtkAction*, AppData* app)
377 {
378 app->core->charEntered('T');
379 }
380
381
actionSystemBrowser(GtkAction *,AppData * app)382 void actionSystemBrowser(GtkAction*, AppData* app)
383 {
384 dialogSolarBrowser(app);
385 }
386
387
actionStarBrowser(GtkAction *,AppData * app)388 void actionStarBrowser(GtkAction*, AppData* app)
389 {
390 dialogStarBrowser(app);
391 }
392
393
actionEclipseFinder(GtkAction *,AppData * app)394 void actionEclipseFinder(GtkAction*, AppData* app)
395 {
396 dialogEclipseFinder(app);
397 }
398
399
actionTimeFaster(GtkAction *,AppData * app)400 void actionTimeFaster(GtkAction*, AppData* app)
401 {
402 app->core->charEntered('L');
403 }
404
405
actionTimeSlower(GtkAction *,AppData * app)406 void actionTimeSlower(GtkAction*, AppData* app)
407 {
408 app->core->charEntered('K');
409 }
410
411
actionTimeFreeze(GtkAction *,AppData * app)412 void actionTimeFreeze(GtkAction*, AppData* app)
413 {
414 app->core->charEntered(' ');
415 }
416
417
actionTimeReal(GtkAction *,AppData * app)418 void actionTimeReal(GtkAction*, AppData* app)
419 {
420 app->core->charEntered('\\');
421 }
422
423
actionTimeReverse(GtkAction *,AppData * app)424 void actionTimeReverse(GtkAction*, AppData* app)
425 {
426 app->core->charEntered('J');
427 }
428
429
actionTimeSet(GtkAction *,AppData * app)430 void actionTimeSet(GtkAction*, AppData* app)
431 {
432 dialogSetTime(app);
433 }
434
435
actionTimeLocal(GtkAction * action,AppData * app)436 void actionTimeLocal(GtkAction* action, AppData* app)
437 {
438 app->showLocalTime = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
439 updateTimeZone(app, app->showLocalTime);
440
441 #ifdef GNOME
442 gconf_client_set_bool(app->client, "/apps/celestia/showLocalTime", app->showLocalTime, NULL);
443 #endif /* GNOME */
444 }
445
446
actionViewerSize(GtkAction *,AppData * app)447 void actionViewerSize(GtkAction*, AppData* app)
448 {
449 GtkWidget* dialog;
450 int newX, currentX, currentY, winX, winY, screenX, i = 1, position = -1;
451 char res[32];
452
453 screenX = gdk_screen_get_width(gdk_screen_get_default());
454 currentX = app->glArea->allocation.width;
455 currentY = app->glArea->allocation.height;
456
457 dialog = gtk_dialog_new_with_buttons("Set Viewer Size...",
458 GTK_WINDOW(app->mainWindow),
459 GTK_DIALOG_DESTROY_WITH_PARENT,
460 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
461 GTK_STOCK_OK, GTK_RESPONSE_OK,
462 NULL);
463
464 GtkWidget* vbox = gtk_vbox_new(FALSE, CELSPACING);
465 gtk_container_set_border_width(GTK_CONTAINER(vbox), CELSPACING);
466
467 GtkWidget* label = gtk_label_new("Dimensions for Main Window:");
468 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
469
470 GtkWidget* menubox = gtk_combo_box_new_text();
471 gtk_box_pack_start(GTK_BOX(vbox), menubox, FALSE, FALSE, 0);
472
473 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
474
475 while (resolutions[i] != -1)
476 {
477 if (position == -1 && resolutions[i-1] < currentX && resolutions[i] >= currentX)
478 {
479 sprintf(res, "%d x %d (current)", currentX, currentY);
480 position = i - 1;
481 }
482 else if (resolutions[i] < screenX)
483 {
484 sprintf(res, "%d x %d", resolutions[i], int(0.75 * resolutions[i]));
485 i++;
486 }
487 else
488 break;
489
490 gtk_combo_box_append_text(GTK_COMBO_BOX(menubox), res);
491 }
492
493 gtk_combo_box_set_active(GTK_COMBO_BOX(menubox), position);
494
495 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
496 gtk_widget_show_all(dialog);
497
498 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
499 {
500 int active = gtk_combo_box_get_active(GTK_COMBO_BOX(menubox));
501
502 if (active > -1 && active != position)
503 {
504 /* Adjust for default entry */
505 if (active > position) active--;
506
507 newX = resolutions[active + 1];
508 gtk_window_get_size(GTK_WINDOW(app->mainWindow), &winX, &winY);
509
510 /* Resizing takes into account border, titlebar, and menubar
511 sizes. Without them only an allocation can be requested */
512 gtk_window_resize(GTK_WINDOW(app->mainWindow), newX + winX - currentX, int(0.75 * newX) + winY - currentY);
513 }
514 }
515
516 gtk_widget_destroy(GTK_WIDGET(dialog));
517 }
518
519
actionFullScreen(GtkAction * action,AppData * app)520 void actionFullScreen(GtkAction* action, AppData* app)
521 {
522 int positionX, positionY;
523 app->fullScreen = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
524
525 if (app->fullScreen)
526 {
527 /* Save size/position, so original numbers are available for prefs */
528 g_object_set_data(G_OBJECT(app->mainWindow), "sizeX", GINT_TO_POINTER(app->glArea->allocation.width));
529 g_object_set_data(G_OBJECT(app->mainWindow), "sizeY", GINT_TO_POINTER(app->glArea->allocation.height));
530 gtk_window_get_position(GTK_WINDOW(app->mainWindow), &positionX, &positionY);
531 g_object_set_data(G_OBJECT(app->mainWindow), "positionX", GINT_TO_POINTER(positionX));
532 g_object_set_data(G_OBJECT(app->mainWindow), "positionY", GINT_TO_POINTER(positionY));
533
534 gtk_window_fullscreen(GTK_WINDOW(app->mainWindow));
535 }
536 else
537 gtk_window_unfullscreen(GTK_WINDOW(app->mainWindow));
538
539 /* Enable/Disable the Viewer Size action */
540 gtk_action_set_sensitive(gtk_action_group_get_action(app->agMain, "ViewerSize"), !app->fullScreen);
541
542 #ifdef GNOME
543 gconf_client_set_bool(app->client, "/apps/celestia/fullScreen", app->fullScreen, NULL);
544 #endif
545 }
546
547
actionViewOptions(GtkAction *,AppData * app)548 void actionViewOptions(GtkAction*, AppData* app)
549 {
550 dialogViewOptions(app);
551 }
552
553
actionStarsMore(GtkAction *,AppData * app)554 void actionStarsMore(GtkAction*, AppData* app)
555 {
556 app->core->charEntered(']');
557
558 #ifdef GNOME
559 gconf_client_set_float(app->client, "/apps/celestia/visualMagnitude", app->simulation->getFaintestVisible(), NULL);
560 #endif
561 }
562
563
actionStarsFewer(GtkAction *,AppData * app)564 void actionStarsFewer(GtkAction*, AppData* app)
565 {
566 app->core->charEntered('[');
567
568 #ifdef GNOME
569 gconf_client_set_float(app->client, "/apps/celestia/visualMagnitude", app->simulation->getFaintestVisible(), NULL);
570 #endif
571 }
572
573
actionVideoSync(GtkToggleAction * action,AppData * app)574 void actionVideoSync(GtkToggleAction* action, AppData* app)
575 {
576 app->renderer->setVideoSync(gtk_toggle_action_get_active(action));
577
578 #ifdef GNOME
579 gconf_client_set_bool(app->client, "/apps/celestia/videoSync", app->renderer->getVideoSync(), NULL);
580 #endif
581 }
582
583
actionMenuBarVisible(GtkToggleAction * action,AppData * app)584 void actionMenuBarVisible(GtkToggleAction* action, AppData* app)
585 {
586 g_object_set(G_OBJECT(app->mainMenu), "visible", gtk_toggle_action_get_active(action), NULL);
587 }
588
589
actionMultiSplitH(GtkAction *,AppData * app)590 void actionMultiSplitH(GtkAction*, AppData* app)
591 {
592 app->core->splitView(View::HorizontalSplit);
593 }
594
595
actionMultiSplitV(GtkAction *,AppData * app)596 void actionMultiSplitV(GtkAction*, AppData* app)
597 {
598 app->core->splitView(View::VerticalSplit);
599 }
600
601
actionMultiCycle(GtkAction *,AppData * app)602 void actionMultiCycle(GtkAction*, AppData* app)
603 {
604 /* Pass a Tab character */
605 app->core->charEntered('\011');
606 }
607
608
actionMultiDelete(GtkAction *,AppData * app)609 void actionMultiDelete(GtkAction*, AppData* app)
610 {
611 app->core->deleteView();
612 }
613
614
actionMultiSingle(GtkAction *,AppData * app)615 void actionMultiSingle(GtkAction*, AppData* app)
616 {
617 app->core->singleView();
618 }
619
620
actionMultiShowFrames(GtkToggleAction * action,AppData * app)621 void actionMultiShowFrames(GtkToggleAction* action, AppData* app)
622 {
623 app->core->setFramesVisible(gtk_toggle_action_get_active(action));
624 }
625
626
actionMultiShowActive(GtkToggleAction * action,AppData * app)627 void actionMultiShowActive(GtkToggleAction* action, AppData* app)
628 {
629 app->core->setActiveFrameVisible(gtk_toggle_action_get_active(action));
630 }
631
632
actionMultiSyncTime(GtkToggleAction * action,AppData * app)633 void actionMultiSyncTime(GtkToggleAction* action, AppData* app)
634 {
635 app->simulation->setSyncTime(gtk_toggle_action_get_active(action));
636 }
637
638
actionRunDemo(GtkAction *,AppData * app)639 void actionRunDemo(GtkAction*, AppData* app)
640 {
641 app->core->charEntered('D');
642 }
643
644
actionHelpControls(GtkAction *,AppData * app)645 void actionHelpControls(GtkAction*, AppData* app)
646 {
647 char *txt = readFromFile("controls.txt");
648 textInfoDialog(txt, "Mouse and Keyboard Controls", app);
649 g_free(txt);
650 }
651
652
actionHelpOpenGL(GtkAction *,AppData * app)653 void actionHelpOpenGL(GtkAction*, AppData* app)
654 {
655 /* Code grabbed from winmain.cpp */
656 char* vendor = (char*) glGetString(GL_VENDOR);
657 char* render = (char*) glGetString(GL_RENDERER);
658 char* version = (char*) glGetString(GL_VERSION);
659 char* ext = (char*) glGetString(GL_EXTENSIONS);
660
661 string s;
662 s = "Vendor: ";
663 if (vendor != NULL)
664 s += vendor;
665 s += "\n";
666
667 s += "Renderer: ";
668 if (render != NULL)
669 s += render;
670 s += "\n";
671
672 s += "Version: ";
673 if (version != NULL)
674 s += version;
675 s += "\n";
676
677 char buf[100];
678 GLint simTextures = 1;
679 if (ExtensionSupported("GL_ARB_multitexture"))
680 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &simTextures);
681 sprintf(buf, "Max simultaneous textures: %d\n", simTextures);
682 s += buf;
683
684 GLint maxTextureSize = 0;
685 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
686 sprintf(buf, "Max texture size: %d\n\n", maxTextureSize);
687 s += buf;
688
689 s += "Supported Extensions:\n ";
690 if (ext != NULL)
691 {
692 string extString(ext);
693 unsigned int pos = extString.find(' ', 0);
694 while (pos != (unsigned int)string::npos)
695 {
696 extString.replace(pos, 1, "\n ");
697 pos = extString.find(' ', pos + 5);
698 }
699 s += extString;
700 }
701
702 textInfoDialog(s.c_str(), "Open GL Info", app);
703 }
704
705
actionHelpAbout(GtkAction *,AppData * app)706 void actionHelpAbout(GtkAction*, AppData* app)
707 {
708 const gchar* authors[] = {
709 "Chris Laurel <claurel@shatters.net>",
710 "Clint Weisbrod <cweisbrod@cogeco.ca>",
711 "Fridger Schrempp <fridger.schrempp@desy.de>",
712 "Bob Ippolito <bob@redivi.com>",
713 "Christophe Teyssier <chris@teyssier.org>",
714 "Hank Ramsey <hramsey@users.sourceforce.net>",
715 "Grant Hutchison <grantcelestia@xemaps.com>",
716 "Pat Suwalski <pat@suwalski.net>",
717 "Toti <>",
718 "Da-Woon Jung <dirkpitt2050@users.sf.net>",
719 "Vincent Giangiulio <vince.gian@free.fr>",
720 NULL
721 };
722
723 GdkPixbuf *logo = gdk_pixbuf_new_from_file ("celestia-logo.png", NULL);
724
725 gtk_show_about_dialog(GTK_WINDOW(app->mainWindow),
726 "name", "Celestia",
727 "version", VERSION,
728 "copyright", "Copyright \xc2\xa9 2001-2011 Celestia Development Team",
729 "comments", FRONTEND " Front-End",
730 "website", "http://celestia.sf.net",
731 "authors", authors,
732 "license", readFromFile("COPYING"),
733 "logo", logo,
734 NULL);
735 gdk_pixbuf_unref(logo);
736 }
737
738
actionVerbosity(GtkRadioAction * action,GtkRadioAction *,AppData * app)739 void actionVerbosity(GtkRadioAction* action, GtkRadioAction*, AppData* app)
740 {
741 int value = gtk_radio_action_get_current_value(action);
742 app->core->setHudDetail(value);
743
744 #ifdef GNOME
745 gconf_client_set_int(app->client, "/apps/celestia/verbosity", value, NULL);
746 #endif
747 }
748
749
actionStarStyle(GtkRadioAction * action,GtkRadioAction *,AppData * app)750 void actionStarStyle(GtkRadioAction* action, GtkRadioAction*, AppData* app)
751 {
752 int value = gtk_radio_action_get_current_value(action);
753 app->renderer->setStarStyle((Renderer::StarStyle)value);
754
755 #ifdef GNOME
756 gconf_client_set_int(app->client, "/apps/celestia/starStyle", value, NULL);
757 #endif
758 }
759
760
actionAmbientLight(GtkRadioAction * action,GtkRadioAction *,AppData * app)761 void actionAmbientLight(GtkRadioAction* action, GtkRadioAction*, AppData* app)
762 {
763 float value = amLevels[gtk_radio_action_get_current_value(action)];
764 app->renderer->setAmbientLightLevel(value);
765
766 #ifdef GNOME
767 gconf_client_set_float(app->client, "/apps/celestia/ambientLight", value, NULL);
768 #endif
769 }
770
771 /* Render-Flag Actions */
actionRenderAA(GtkToggleAction * action,AppData * app)772 void actionRenderAA(GtkToggleAction* action, AppData* app)
773 {
774 setRenderFlag(app, Renderer::ShowSmoothLines, gtk_toggle_action_get_active(action));
775 }
776
777
actionRenderAtmospheres(GtkToggleAction * action,AppData * app)778 void actionRenderAtmospheres(GtkToggleAction* action, AppData* app)
779 {
780 setRenderFlag(app, Renderer::ShowAtmospheres, gtk_toggle_action_get_active(action));
781 }
782
783
actionRenderAutoMagnitude(GtkToggleAction * action,AppData * app)784 void actionRenderAutoMagnitude(GtkToggleAction* action, AppData* app)
785 {
786 setRenderFlag(app, Renderer::ShowAutoMag, gtk_toggle_action_get_active(action));
787 }
788
789
actionRenderCelestialGrid(GtkToggleAction * action,AppData * app)790 void actionRenderCelestialGrid(GtkToggleAction* action, AppData* app)
791 {
792 setRenderFlag(app, Renderer::ShowCelestialSphere, gtk_toggle_action_get_active(action));
793 }
794
795
actionRenderClouds(GtkToggleAction * action,AppData * app)796 void actionRenderClouds(GtkToggleAction* action, AppData* app)
797 {
798 setRenderFlag(app, Renderer::ShowCloudMaps, gtk_toggle_action_get_active(action));
799 }
800
801
actionRenderCometTails(GtkToggleAction * action,AppData * app)802 void actionRenderCometTails(GtkToggleAction* action, AppData* app)
803 {
804 setRenderFlag(app, Renderer::ShowCometTails, gtk_toggle_action_get_active(action));
805 }
806
807
actionRenderConstellationBoundaries(GtkToggleAction * action,AppData * app)808 void actionRenderConstellationBoundaries(GtkToggleAction* action, AppData* app)
809 {
810 setRenderFlag(app, Renderer::ShowBoundaries, gtk_toggle_action_get_active(action));
811 }
812
813
actionRenderConstellations(GtkToggleAction * action,AppData * app)814 void actionRenderConstellations(GtkToggleAction* action, AppData* app)
815 {
816 setRenderFlag(app, Renderer::ShowDiagrams, gtk_toggle_action_get_active(action));
817 }
818
819
actionRenderEclipticGrid(GtkToggleAction * action,AppData * app)820 void actionRenderEclipticGrid(GtkToggleAction* action, AppData* app)
821 {
822 setRenderFlag(app, Renderer::ShowEclipticGrid, gtk_toggle_action_get_active(action));
823 }
824
825
actionRenderEclipseShadows(GtkToggleAction * action,AppData * app)826 void actionRenderEclipseShadows(GtkToggleAction* action, AppData* app)
827 {
828 setRenderFlag(app, Renderer::ShowEclipseShadows, gtk_toggle_action_get_active(action));
829 }
830
831
actionRenderGalacticGrid(GtkToggleAction * action,AppData * app)832 void actionRenderGalacticGrid(GtkToggleAction* action, AppData* app)
833 {
834 setRenderFlag(app, Renderer::ShowGalacticGrid, gtk_toggle_action_get_active(action));
835 }
836
837
actionRenderGalaxies(GtkToggleAction * action,AppData * app)838 void actionRenderGalaxies(GtkToggleAction* action, AppData* app)
839 {
840 setRenderFlag(app, Renderer::ShowGalaxies, gtk_toggle_action_get_active(action));
841 }
842
843
actionRenderGlobulars(GtkToggleAction * action,AppData * app)844 void actionRenderGlobulars(GtkToggleAction* action, AppData* app)
845 {
846 setRenderFlag(app, Renderer::ShowGlobulars, gtk_toggle_action_get_active(action));
847 }
848
849
actionRenderHorizontalGrid(GtkToggleAction * action,AppData * app)850 void actionRenderHorizontalGrid(GtkToggleAction* action, AppData* app)
851 {
852 setRenderFlag(app, Renderer::ShowHorizonGrid, gtk_toggle_action_get_active(action));
853 }
854
855
actionRenderMarkers(GtkToggleAction * action,AppData * app)856 void actionRenderMarkers(GtkToggleAction* action, AppData* app)
857 {
858 setRenderFlag(app, Renderer::ShowMarkers, gtk_toggle_action_get_active(action));
859 }
860
861
actionRenderNebulae(GtkToggleAction * action,AppData * app)862 void actionRenderNebulae(GtkToggleAction* action, AppData* app)
863 {
864 setRenderFlag(app, Renderer::ShowNebulae, gtk_toggle_action_get_active(action));
865 }
866
867
actionRenderNightLights(GtkToggleAction * action,AppData * app)868 void actionRenderNightLights(GtkToggleAction* action, AppData* app)
869 {
870 setRenderFlag(app, Renderer::ShowNightMaps, gtk_toggle_action_get_active(action));
871 }
872
873
actionRenderOpenClusters(GtkToggleAction * action,AppData * app)874 void actionRenderOpenClusters(GtkToggleAction* action, AppData* app)
875 {
876 setRenderFlag(app, Renderer::ShowOpenClusters, gtk_toggle_action_get_active(action));
877 }
878
879
actionRenderOrbits(GtkToggleAction * action,AppData * app)880 void actionRenderOrbits(GtkToggleAction* action, AppData* app)
881 {
882 setRenderFlag(app, Renderer::ShowOrbits, gtk_toggle_action_get_active(action));
883 }
884
885
actionRenderPlanets(GtkToggleAction * action,AppData * app)886 void actionRenderPlanets(GtkToggleAction* action, AppData* app)
887 {
888 setRenderFlag(app, Renderer::ShowPlanets, gtk_toggle_action_get_active(action));
889 }
890
891
actionRenderRingShadows(GtkToggleAction * action,AppData * app)892 void actionRenderRingShadows(GtkToggleAction* action, AppData* app)
893 {
894 setRenderFlag(app, Renderer::ShowRingShadows, gtk_toggle_action_get_active(action));
895 }
896
897
actionRenderStars(GtkToggleAction * action,AppData * app)898 void actionRenderStars(GtkToggleAction* action, AppData* app)
899 {
900 setRenderFlag(app, Renderer::ShowStars, gtk_toggle_action_get_active(action));
901 }
902
903
actionOrbitAsteroids(GtkToggleAction * action,AppData * app)904 void actionOrbitAsteroids(GtkToggleAction* action, AppData* app)
905 {
906 setOrbitMask(app, Body::Asteroid, gtk_toggle_action_get_active(action));
907 }
908
909
actionOrbitComets(GtkToggleAction * action,AppData * app)910 void actionOrbitComets(GtkToggleAction* action, AppData* app)
911 {
912 setOrbitMask(app, Body::Comet, gtk_toggle_action_get_active(action));
913 }
914
915
actionOrbitMoons(GtkToggleAction * action,AppData * app)916 void actionOrbitMoons(GtkToggleAction* action, AppData* app)
917 {
918 setOrbitMask(app, Body::Moon, gtk_toggle_action_get_active(action));
919 }
920
921
actionOrbitPlanets(GtkToggleAction * action,AppData * app)922 void actionOrbitPlanets(GtkToggleAction* action, AppData* app)
923 {
924 setOrbitMask(app, Body::Planet, gtk_toggle_action_get_active(action));
925 }
926
927
actionOrbitSpacecraft(GtkToggleAction * action,AppData * app)928 void actionOrbitSpacecraft(GtkToggleAction* action, AppData* app)
929 {
930 setOrbitMask(app, Body::Spacecraft, gtk_toggle_action_get_active(action));
931 }
932
933
actionLabelAsteroids(GtkToggleAction * action,AppData * app)934 void actionLabelAsteroids(GtkToggleAction* action, AppData* app)
935 {
936 setLabelMode(app, Renderer::AsteroidLabels, gtk_toggle_action_get_active(action));
937 }
938
939
actionLabelComets(GtkToggleAction * action,AppData * app)940 void actionLabelComets(GtkToggleAction* action, AppData* app)
941 {
942 setLabelMode(app, Renderer::CometLabels, gtk_toggle_action_get_active(action));
943 }
944
945
actionLabelConstellations(GtkToggleAction * action,AppData * app)946 void actionLabelConstellations(GtkToggleAction* action, AppData* app)
947 {
948 setLabelMode(app, Renderer::ConstellationLabels, gtk_toggle_action_get_active(action));
949 }
950
951
actionLabelGalaxies(GtkToggleAction * action,AppData * app)952 void actionLabelGalaxies(GtkToggleAction* action, AppData* app)
953 {
954 setLabelMode(app, Renderer::GalaxyLabels, gtk_toggle_action_get_active(action));
955 }
956
957
actionLabelGlobulars(GtkToggleAction * action,AppData * app)958 void actionLabelGlobulars(GtkToggleAction* action, AppData* app)
959 {
960 setLabelMode(app, Renderer::GlobularLabels, gtk_toggle_action_get_active(action));
961 }
962
963
actionLabelLocations(GtkToggleAction * action,AppData * app)964 void actionLabelLocations(GtkToggleAction* action, AppData* app)
965 {
966 setLabelMode(app, Renderer::LocationLabels, gtk_toggle_action_get_active(action));
967 }
968
969
actionLabelMoons(GtkToggleAction * action,AppData * app)970 void actionLabelMoons(GtkToggleAction* action, AppData* app)
971 {
972 setLabelMode(app, Renderer::MoonLabels, gtk_toggle_action_get_active(action));
973 }
974
975
actionLabelNebulae(GtkToggleAction * action,AppData * app)976 void actionLabelNebulae(GtkToggleAction* action, AppData* app)
977 {
978 setLabelMode(app, Renderer::NebulaLabels, gtk_toggle_action_get_active(action));
979 }
980
981
actionLabelOpenClusters(GtkToggleAction * action,AppData * app)982 void actionLabelOpenClusters(GtkToggleAction* action, AppData* app)
983 {
984 setLabelMode(app, Renderer::OpenClusterLabels, gtk_toggle_action_get_active(action));
985 }
986
987
actionLabelPlanets(GtkToggleAction * action,AppData * app)988 void actionLabelPlanets(GtkToggleAction* action, AppData* app)
989 {
990 setLabelMode(app, Renderer::PlanetLabels, gtk_toggle_action_get_active(action));
991 }
992
993
actionLabelSpacecraft(GtkToggleAction * action,AppData * app)994 void actionLabelSpacecraft(GtkToggleAction* action, AppData* app)
995 {
996 setLabelMode(app, Renderer::SpacecraftLabels, gtk_toggle_action_get_active(action));
997 }
998
999
actionLabelStars(GtkToggleAction * action,AppData * app)1000 void actionLabelStars(GtkToggleAction* action, AppData* app)
1001 {
1002 setLabelMode(app, Renderer::StarLabels, gtk_toggle_action_get_active(action));
1003 }
1004
1005
1006 /* Script opening helper called by actionOpenScript() */
openScript(const char * filename,AppData * app)1007 static void openScript(const char* filename, AppData* app)
1008 {
1009 /* Modified From Win32 HandleOpenScript */
1010 if (filename)
1011 {
1012 /* If you got here, a path and file has been specified.
1013 * filename contains full path to specified file. */
1014 ContentType type = DetermineFileType(filename);
1015
1016 if (type == Content_CelestiaScript)
1017 {
1018 app->core->runScript(filename);
1019 }
1020 else if (type == Content_CelestiaLegacyScript)
1021 {
1022 ifstream scriptfile(filename);
1023 if (!scriptfile.good())
1024 {
1025 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1026 GTK_DIALOG_DESTROY_WITH_PARENT,
1027 GTK_MESSAGE_ERROR,
1028 GTK_BUTTONS_OK,
1029 "Error opening script file.");
1030 gtk_dialog_run(GTK_DIALOG(errBox));
1031 gtk_widget_destroy(errBox);
1032 }
1033 else
1034 {
1035 CommandParser parser(scriptfile);
1036 CommandSequence* script = parser.parse();
1037 if (script == NULL)
1038 {
1039 const vector<string>* errors = parser.getErrors();
1040 const char* errorMsg = "";
1041 if (errors->size() > 0)
1042 errorMsg = (*errors)[0].c_str();
1043 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1044 GTK_DIALOG_DESTROY_WITH_PARENT,
1045 GTK_MESSAGE_ERROR,
1046 GTK_BUTTONS_OK, "%s",
1047 errorMsg);
1048 gtk_dialog_run(GTK_DIALOG(errBox));
1049 gtk_widget_destroy(errBox);
1050 }
1051 else
1052 {
1053 /* Cancel any running script */
1054 app->core->cancelScript();
1055 app->core->runScript(script);
1056 }
1057 }
1058 }
1059 else
1060 {
1061 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1062 GTK_DIALOG_DESTROY_WITH_PARENT,
1063 GTK_MESSAGE_ERROR,
1064 GTK_BUTTONS_OK,
1065 "Bad File Type. Use *.(cel|celx|clx).");
1066 gtk_dialog_run(GTK_DIALOG(errBox));
1067 gtk_widget_destroy(errBox);
1068 }
1069 }
1070 }
1071
1072
1073 /* Image capturing helper called by actionCaptureImage() */
captureImage(const char * filename,AppData * app)1074 static void captureImage(const char* filename, AppData* app)
1075 {
1076 /* Get the dimensions of the current viewport */
1077 int viewport[4];
1078 glGetIntegerv(GL_VIEWPORT, viewport);
1079
1080 bool success = false;
1081 ContentType type = DetermineFileType(filename);
1082 if (type == Content_Unknown)
1083 {
1084 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1085 GTK_DIALOG_DESTROY_WITH_PARENT,
1086 GTK_MESSAGE_ERROR,
1087 GTK_BUTTONS_OK,
1088 "Unable to determine image file type from name, please use a name ending in '.jpg' or '.png'.");
1089 gtk_dialog_run(GTK_DIALOG(errBox));
1090 gtk_widget_destroy(errBox);
1091 return;
1092 }
1093 else if (type == Content_JPEG)
1094 {
1095 success = CaptureGLBufferToJPEG(filename,
1096 viewport[0], viewport[1],
1097 viewport[2], viewport[3]);
1098 }
1099 else if (type == Content_PNG)
1100 {
1101 success = CaptureGLBufferToPNG(filename,
1102 viewport[0], viewport[1],
1103 viewport[2], viewport[3]);
1104 }
1105 else
1106 {
1107 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1108 GTK_DIALOG_DESTROY_WITH_PARENT,
1109 GTK_MESSAGE_ERROR,
1110 GTK_BUTTONS_OK,
1111 "Currently screen capturing to only JPEG or PNG files is supported.");
1112 gtk_dialog_run(GTK_DIALOG(errBox));
1113 gtk_widget_destroy(errBox);
1114 return;
1115 }
1116
1117 if (!success)
1118 {
1119 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1120 GTK_DIALOG_DESTROY_WITH_PARENT,
1121 GTK_MESSAGE_ERROR,
1122 GTK_BUTTONS_OK,
1123 "Error writing captured image.");
1124 gtk_dialog_run(GTK_DIALOG(errBox));
1125 gtk_widget_destroy(errBox);
1126 }
1127 }
1128
1129 /* Image capturing helper called by actionCaptureImage() */
1130 #ifdef THEORA
captureMovie(const char * filename,int aspect,float fps,float quality,AppData * app)1131 static void captureMovie(const char* filename, int aspect, float fps, float quality, AppData* app)
1132 {
1133 /* Get the dimensions of the current viewport */
1134 int viewport[4];
1135 glGetIntegerv(GL_VIEWPORT, viewport);
1136
1137 MovieCapture* movieCapture = new OggTheoraCapture();
1138 switch (aspect)
1139 {
1140 case 0:
1141 movieCapture->setAspectRatio(1, 1);
1142 break;
1143 case 1:
1144 movieCapture->setAspectRatio(4, 3);
1145 break;
1146 case 2:
1147 movieCapture->setAspectRatio(16, 9);
1148 break;
1149 default:
1150 movieCapture->setAspectRatio(viewport[2], viewport[3]);
1151 break;
1152 }
1153 movieCapture->setQuality(quality);
1154
1155 bool success = movieCapture->start(filename, viewport[2], viewport[3], fps);
1156 if (success)
1157 app->core->initMovieCapture(movieCapture);
1158 else
1159 {
1160 delete movieCapture;
1161
1162 GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
1163 GTK_DIALOG_DESTROY_WITH_PARENT,
1164 GTK_MESSAGE_ERROR,
1165 GTK_BUTTONS_OK,
1166 "Error initializing movie capture.");
1167 gtk_dialog_run(GTK_DIALOG(errBox));
1168 gtk_widget_destroy(errBox);
1169 }
1170 }
1171 #endif
1172
1173 /* Runs a dialog that displays text; should be replaced at some point with
1174 a more elegant solution. */
textInfoDialog(const char * txt,const char * title,AppData * app)1175 static void textInfoDialog(const char *txt, const char *title, AppData* app)
1176 {
1177 /* I would use a gnome_message_box dialog for this, except they don't seem
1178 * to notice that the texts are so big that they create huge windows, and
1179 * would work better with a scrolled window. Deon */
1180 GtkWidget* dialog = gtk_dialog_new_with_buttons(title,
1181 GTK_WINDOW(app->mainWindow),
1182 GTK_DIALOG_DESTROY_WITH_PARENT,
1183 GTK_STOCK_OK, GTK_RESPONSE_OK,
1184 NULL);
1185
1186 GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1187 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolled_window, TRUE, TRUE, 0);
1188 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window),
1189 GTK_POLICY_AUTOMATIC,
1190 GTK_POLICY_AUTOMATIC);
1191 gtk_widget_show(scrolled_window);
1192
1193 GtkWidget *text = gtk_label_new(txt);
1194 gtk_widget_modify_font(text, pango_font_description_from_string("mono"));
1195 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), GTK_WIDGET(text));
1196 gtk_widget_show(text);
1197
1198 gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 400); /* Absolute Size, urghhh */
1199 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
1200
1201 gtk_dialog_run(GTK_DIALOG(dialog));
1202 gtk_widget_destroy(dialog);
1203 }
1204
1205
1206 /* Calculates and sets the render-flag int */
setRenderFlag(AppData * a,int flag,gboolean state)1207 static void setRenderFlag(AppData* a, int flag, gboolean state)
1208 {
1209 int rf = (a->renderer->getRenderFlags() & ~flag) | (state ? flag : 0);
1210 a->renderer->setRenderFlags(rf);
1211
1212 #ifdef GNOME
1213 /* Update GConf */
1214 gcSetRenderFlag(flag, state, a->client);
1215 #endif /* GNOME */
1216 }
1217
1218
1219 /* Calculates and sets the orbit-mask int */
setOrbitMask(AppData * a,int mask,gboolean state)1220 static void setOrbitMask(AppData* a, int mask, gboolean state)
1221 {
1222 int om = (a->renderer->getOrbitMask() & ~mask) | (state ? mask : 0);
1223 a->renderer->setOrbitMask(om);
1224
1225 #ifdef GNOME
1226 /* Update GConf */
1227 gcSetOrbitMask(mask, state, a->client);
1228 #endif /* GNOME */
1229 }
1230
1231
1232 /* Calculates and sets the label-mode int */
setLabelMode(AppData * a,int mode,gboolean state)1233 static void setLabelMode(AppData* a, int mode, gboolean state)
1234 {
1235 int lm = (a->renderer->getLabelMode() & ~mode) | (state ? mode : 0);
1236 a->renderer->setLabelMode(lm);
1237
1238 #ifdef GNOME
1239 /* Update GConf */
1240 gcSetLabelMode(mode, state, a->client);
1241 #endif /* GNOME */
1242 }
1243
1244
1245 /* Synchronizes the Label Actions with the state of the core */
resyncLabelActions(AppData * app)1246 void resyncLabelActions(AppData* app)
1247 {
1248 GtkAction* action;
1249 const char* actionName;
1250
1251 /* Simply for readability */
1252 int f = app->renderer->getLabelMode();
1253
1254 for (int i = Renderer::StarLabels; i <= Renderer::GlobularLabels; i *= 2)
1255 {
1256 switch (i)
1257 {
1258 case Renderer::StarLabels: actionName = "LabelStars"; break;
1259 case Renderer::PlanetLabels: actionName = "LabelPlanets"; break;
1260 case Renderer::MoonLabels: actionName = "LabelMoons"; break;
1261 case Renderer::ConstellationLabels: actionName = "LabelConstellations"; break;
1262 case Renderer::GalaxyLabels: actionName = "LabelGalaxies"; break;
1263 case Renderer::AsteroidLabels: actionName = "LabelAsteroids"; break;
1264 case Renderer::SpacecraftLabels: actionName = "LabelSpacecraft"; break;
1265 case Renderer::LocationLabels: actionName = "LabelLocations"; break;
1266 case Renderer::CometLabels: actionName = "LabelComets"; break;
1267 case Renderer::NebulaLabels: actionName = "LabelNebulae"; break;
1268 case Renderer::OpenClusterLabels: actionName = "LabelOpenClusters"; break;
1269 case Renderer::GlobularLabels: actionName = "LabelGlobulars"; break;
1270 case Renderer::I18nConstellationLabels: /* Not used yet */
1271 default: actionName = NULL;
1272 }
1273
1274 if (actionName != NULL)
1275 {
1276 /* Get the action */
1277 action = gtk_action_group_get_action(app->agLabel, actionName);
1278
1279 /* The current i anded with the labelMode gives state of flag */
1280 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & f));
1281 }
1282 }
1283 }
1284
1285
1286 /* Synchronizes the Render Actions with the state of the core */
resyncRenderActions(AppData * app)1287 void resyncRenderActions(AppData* app)
1288 {
1289 GtkAction* action;
1290 const char* actionName;
1291
1292 /* Simply for readability */
1293 int rf = app->renderer->getRenderFlags();
1294
1295 /* Unlike the other interfaces, which go through each menu item and set
1296 * the corresponding renderFlag, we go the other way and set the menu
1297 * based on the renderFlag. Last one is ShowEcliptic. */
1298
1299 for (int i = Renderer::ShowStars; i <= Renderer::ShowEcliptic; i *= 2)
1300 {
1301 switch (i)
1302 {
1303 case Renderer::ShowStars: actionName = "RenderStars"; break;
1304 case Renderer::ShowPlanets: actionName = "RenderPlanets"; break;
1305 case Renderer::ShowGalaxies: actionName = "RenderGalaxies"; break;
1306 case Renderer::ShowDiagrams: actionName = "RenderConstellations"; break;
1307 case Renderer::ShowCloudMaps: actionName = "RenderClouds"; break;
1308 case Renderer::ShowOrbits: actionName = "RenderOrbits"; break;
1309 case Renderer::ShowCelestialSphere: actionName = "RenderCelestialGrid"; break;
1310 case Renderer::ShowNightMaps: actionName = "RenderNightLights"; break;
1311 case Renderer::ShowAtmospheres: actionName = "RenderAtmospheres"; break;
1312 case Renderer::ShowSmoothLines: actionName = "RenderAA"; break;
1313 case Renderer::ShowEclipseShadows: actionName = "RenderEclipseShadows"; break;
1314 case Renderer::ShowStarsAsPoints: actionName = NULL; break; /* Deprecated */
1315 case Renderer::ShowRingShadows: actionName = "RenderRingShadows"; break;
1316 case Renderer::ShowBoundaries: actionName = "RenderConstellationBoundaries"; break;
1317 case Renderer::ShowAutoMag: actionName = "RenderAutoMagnitude"; break;
1318 case Renderer::ShowCometTails: actionName = "RenderCometTails"; break;
1319 case Renderer::ShowMarkers: actionName = "RenderMarkers"; break;
1320 case Renderer::ShowPartialTrajectories: actionName = NULL; break; /* Not useful yet */
1321 case Renderer::ShowNebulae: actionName = "RenderNebulae"; break;
1322 case Renderer::ShowOpenClusters: actionName = "RenderOpenClusters"; break;
1323 case Renderer::ShowGlobulars: actionName = "RenderGlobulars"; break;
1324 case Renderer::ShowCloudShadows: actionName = NULL; break; /* Not implemented yet */
1325 case Renderer::ShowGalacticGrid: actionName = "RenderGalacticGrid"; break;
1326 case Renderer::ShowEclipticGrid: actionName = "RenderEclipticGrid"; break;
1327 case Renderer::ShowHorizonGrid: actionName = "RenderHorizontalGrid"; break;
1328 case Renderer::ShowEcliptic: actionName = NULL; break; /* Not implemented yet */
1329 default: actionName = NULL;
1330 }
1331
1332 if (actionName != NULL)
1333 {
1334 /* Get the action */
1335 action = gtk_action_group_get_action(app->agRender, actionName);
1336
1337 /* The current i anded with the renderFlags gives state of flag */
1338 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & rf));
1339 }
1340 }
1341 }
1342
1343
1344 /* Synchronizes the Orbit Actions with the state of the core */
resyncOrbitActions(AppData * app)1345 void resyncOrbitActions(AppData* app)
1346 {
1347 GtkAction* action;
1348 const char* actionName;
1349
1350 /* Simply for readability */
1351 int om = app->renderer->getOrbitMask();
1352
1353 for (int i = Body::Planet; i <= Body::Spacecraft; i *= 2)
1354 {
1355 switch (i)
1356 {
1357 case Body::Planet: actionName = "OrbitPlanets"; break;
1358 case Body::Moon: actionName = "OrbitMoons"; break;
1359 case Body::Asteroid: actionName = "OrbitAsteroids"; break;
1360 case Body::Comet: actionName = "OrbitComets"; break;
1361 case Body::Spacecraft: actionName = "OrbitSpacecraft"; break;
1362 default: actionName = NULL;
1363 }
1364
1365 if (actionName != NULL)
1366 {
1367 /* Get the action */
1368 action = gtk_action_group_get_action(app->agOrbit, actionName);
1369
1370 /* The current i anded with the orbitMask gives state of flag */
1371 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & om));
1372 }
1373 }
1374 }
1375
1376
1377 /* Synchronizes the Verbosity Actions with the state of the core */
resyncVerbosityActions(AppData * app)1378 void resyncVerbosityActions(AppData* app)
1379 {
1380 GtkAction* action;
1381 const char* actionName;
1382
1383 switch (app->core->getHudDetail())
1384 {
1385 case 0: actionName = "HudNone"; break;
1386 case 1: actionName = "HudTerse"; break;
1387 case 2: actionName = "HudVerbose"; break;
1388 default: return;
1389 }
1390
1391 /* Get the action, set the widget */
1392 action = gtk_action_group_get_action(app->agVerbosity, actionName);
1393 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
1394 }
1395
1396
1397 /* Synchronizes the TimeZone Action with the state of the core */
resyncTimeZoneAction(AppData * app)1398 void resyncTimeZoneAction(AppData* app)
1399 {
1400 /* Get the action, set the widget */
1401 GtkAction* action = gtk_action_group_get_action(app->agMain, "TimeLocal");
1402 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), app->showLocalTime);
1403 }
1404
1405
1406 /* Synchronizes the Ambient Light Actions with the state of the core */
resyncAmbientActions(AppData * app)1407 void resyncAmbientActions(AppData* app)
1408 {
1409 GtkAction* action;
1410
1411 float ambient = app->renderer->getAmbientLightLevel();
1412
1413 /* Try to be smart about being close to the value of a float */
1414 if (ambient > amLevels[0] && ambient < (amLevels[1] / 2.0))
1415 action = gtk_action_group_get_action(app->agAmbient, "AmbientNone");
1416
1417 else if (ambient < amLevels[1] + ((amLevels[2] - amLevels[1]) / 2.0))
1418 action = gtk_action_group_get_action(app->agAmbient, "AmbientLow");
1419
1420 else
1421 action = gtk_action_group_get_action(app->agAmbient, "AmbientMedium");
1422
1423 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
1424
1425 #ifdef GNOME
1426 /* The action callback only occurs when one of the None/Low/Medium barriers
1427 * is surpassed, so an update is forced. */
1428 gconf_client_set_float(app->client, "/apps/celestia/ambientLight", ambient, NULL);
1429 #endif
1430 }
1431
1432
1433 /* Synchronizes the Verbosity Actions with the state of the core */
resyncStarStyleActions(AppData * app)1434 void resyncStarStyleActions(AppData* app)
1435 {
1436 GtkAction* action;
1437 const char* actionName;
1438
1439 switch (app->renderer->getStarStyle())
1440 {
1441 case Renderer::FuzzyPointStars: actionName = "StarsFuzzy"; break;
1442 case Renderer::PointStars: actionName = "StarsPoints"; break;
1443 case Renderer::ScaledDiscStars: actionName = "StarsDiscs"; break;
1444 default: return;
1445 }
1446
1447 /* Get the action, set the widget */
1448 action = gtk_action_group_get_action(app->agStarStyle, actionName);
1449 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
1450 }
1451
1452
1453 /* Placeholder for when galaxy brightness is added as an action */
resyncGalaxyGainActions(AppData * app)1454 void resyncGalaxyGainActions(AppData* app)
1455 {
1456 float gain = Galaxy::getLightGain();
1457
1458 #ifdef GNOME
1459 gconf_client_set_float(app->client, "/apps/celestia/galaxyLightGain", gain, NULL);
1460 #endif
1461 }
1462
1463
1464 /* Synchronizes the Texture Resolution with the state of the core */
resyncTextureResolutionActions(AppData * app)1465 void resyncTextureResolutionActions(AppData* app)
1466 {
1467 int resolution = app->renderer->getResolution();
1468
1469 #ifdef GNOME
1470 gconf_client_set_int(app->client, "/apps/celestia/textureResolution", resolution, NULL);
1471 #endif /* GNOME */
1472 }
1473