"Fossies" - the Fresh Open Source Software Archive

Member "Celestia-1.6.2.2/src/celestia/gtk/actions.cpp" (12 Jan 2021, 44729 Bytes) of package /linux/misc/Celestia-1.6.2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "actions.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.6.2.1_vs_1.6.2.2.

    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 */
   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 */
   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... */
  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... */
  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... */
  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 
  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 
  297 void actionSelectSol(GtkAction*, AppData* app)
  298 {
  299     app->core->charEntered('H');
  300 }
  301 
  302 
  303 void actionTourGuide(GtkAction*, AppData* app)
  304 {
  305     dialogTourGuide(app);
  306 }
  307 
  308 
  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 
  346 void actionGotoObject(GtkAction*, AppData* app)
  347 {
  348     dialogGotoObject(app);
  349 }
  350 
  351 
  352 void actionCenterSelection(GtkAction*, AppData* app)
  353 {
  354     app->core->charEntered('c');
  355 }
  356 
  357 
  358 void actionGotoSelection(GtkAction*, AppData* app)
  359 {
  360     app->core->charEntered('G');
  361 }
  362 
  363 
  364 void actionFollowSelection(GtkAction*, AppData* app)
  365 {
  366     app->core->charEntered('F');
  367 }
  368 
  369 
  370 void actionSyncSelection(GtkAction*, AppData* app)
  371 {
  372     app->core->charEntered('Y');
  373 }
  374 
  375 
  376 void actionTrackSelection(GtkAction*, AppData* app)
  377 {
  378     app->core->charEntered('T');
  379 }
  380 
  381 
  382 void actionSystemBrowser(GtkAction*, AppData* app)
  383 {
  384     dialogSolarBrowser(app);
  385 }
  386 
  387 
  388 void actionStarBrowser(GtkAction*, AppData* app)
  389 {
  390     dialogStarBrowser(app);
  391 }
  392 
  393 
  394 void actionEclipseFinder(GtkAction*, AppData* app)
  395 {
  396     dialogEclipseFinder(app);
  397 }
  398 
  399 
  400 void actionTimeFaster(GtkAction*, AppData* app)
  401 {
  402     app->core->charEntered('L');
  403 }
  404 
  405 
  406 void actionTimeSlower(GtkAction*, AppData* app)
  407 {
  408     app->core->charEntered('K');
  409 }
  410 
  411 
  412 void actionTimeFreeze(GtkAction*, AppData* app)
  413 {
  414     app->core->charEntered(' ');
  415 }
  416 
  417 
  418 void actionTimeReal(GtkAction*, AppData* app)
  419 {
  420     app->core->charEntered('\\');
  421 }
  422 
  423 
  424 void actionTimeReverse(GtkAction*, AppData* app)
  425 {
  426     app->core->charEntered('J');
  427 }
  428 
  429 
  430 void actionTimeSet(GtkAction*, AppData* app)
  431 {
  432     dialogSetTime(app);
  433 }
  434 
  435 
  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 
  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 
  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 
  548 void actionViewOptions(GtkAction*, AppData* app)
  549 {
  550     dialogViewOptions(app);
  551 }
  552 
  553 
  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 
  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 
  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 
  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 
  590 void actionMultiSplitH(GtkAction*, AppData* app)
  591 {
  592     app->core->splitView(View::HorizontalSplit);
  593 }
  594 
  595 
  596 void actionMultiSplitV(GtkAction*, AppData* app)
  597 {
  598     app->core->splitView(View::VerticalSplit);
  599 }
  600 
  601 
  602 void actionMultiCycle(GtkAction*, AppData* app)
  603 {
  604     /* Pass a Tab character */
  605     app->core->charEntered('\011');
  606 }
  607 
  608 
  609 void actionMultiDelete(GtkAction*, AppData* app)
  610 {
  611     app->core->deleteView();
  612 }
  613 
  614 
  615 void actionMultiSingle(GtkAction*, AppData* app)
  616 {
  617     app->core->singleView();
  618 }
  619 
  620 
  621 void actionMultiShowFrames(GtkToggleAction* action, AppData* app)
  622 {
  623     app->core->setFramesVisible(gtk_toggle_action_get_active(action));
  624 }
  625 
  626 
  627 void actionMultiShowActive(GtkToggleAction* action, AppData* app)
  628 {
  629     app->core->setActiveFrameVisible(gtk_toggle_action_get_active(action));
  630 }
  631 
  632 
  633 void actionMultiSyncTime(GtkToggleAction* action, AppData* app)
  634 {
  635     app->simulation->setSyncTime(gtk_toggle_action_get_active(action));
  636 }
  637 
  638 
  639 void actionRunDemo(GtkAction*, AppData* app)
  640 {
  641     app->core->charEntered('D');
  642 }
  643 
  644 
  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 
  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 
  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-2021 Celestia Development Team"),
  729                          "comments", FRONTEND " Front-End",
  730                          "website", "https://celestia.space",
  731                          "authors", authors,
  732                          "license", readFromFile("COPYING"),
  733                          "logo", logo,
  734                          NULL);
  735     g_object_unref(logo);
  736 }
  737 
  738 
  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 
  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 
  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 */
  772 void actionRenderAA(GtkToggleAction* action, AppData* app)
  773 {
  774     setRenderFlag(app, Renderer::ShowSmoothLines, gtk_toggle_action_get_active(action));
  775 }
  776 
  777 
  778 void actionRenderAtmospheres(GtkToggleAction* action, AppData* app)
  779 {
  780     setRenderFlag(app, Renderer::ShowAtmospheres, gtk_toggle_action_get_active(action));
  781 }
  782 
  783 
  784 void actionRenderAutoMagnitude(GtkToggleAction* action, AppData* app)
  785 {
  786     setRenderFlag(app, Renderer::ShowAutoMag, gtk_toggle_action_get_active(action));
  787 }
  788 
  789 
  790 void actionRenderCelestialGrid(GtkToggleAction* action, AppData* app)
  791 {
  792     setRenderFlag(app, Renderer::ShowCelestialSphere, gtk_toggle_action_get_active(action));
  793 }
  794 
  795 
  796 void actionRenderClouds(GtkToggleAction* action, AppData* app)
  797 {
  798     setRenderFlag(app, Renderer::ShowCloudMaps, gtk_toggle_action_get_active(action));
  799 }
  800 
  801 
  802 void actionRenderCometTails(GtkToggleAction* action, AppData* app)
  803 {
  804     setRenderFlag(app, Renderer::ShowCometTails, gtk_toggle_action_get_active(action));
  805 }
  806 
  807 
  808 void actionRenderConstellationBoundaries(GtkToggleAction* action, AppData* app)
  809 {
  810     setRenderFlag(app, Renderer::ShowBoundaries, gtk_toggle_action_get_active(action));
  811 }
  812 
  813 
  814 void actionRenderConstellations(GtkToggleAction* action, AppData* app)
  815 {
  816     setRenderFlag(app, Renderer::ShowDiagrams, gtk_toggle_action_get_active(action));
  817 }
  818 
  819 
  820 void actionRenderEclipticGrid(GtkToggleAction* action, AppData* app)
  821 {
  822     setRenderFlag(app, Renderer::ShowEclipticGrid, gtk_toggle_action_get_active(action));
  823 }
  824 
  825 
  826 void actionRenderEclipseShadows(GtkToggleAction* action, AppData* app)
  827 {
  828     setRenderFlag(app, Renderer::ShowEclipseShadows, gtk_toggle_action_get_active(action));
  829 }
  830 
  831 
  832 void actionRenderGalacticGrid(GtkToggleAction* action, AppData* app)
  833 {
  834     setRenderFlag(app, Renderer::ShowGalacticGrid, gtk_toggle_action_get_active(action));
  835 }
  836 
  837 
  838 void actionRenderGalaxies(GtkToggleAction* action, AppData* app)
  839 {
  840     setRenderFlag(app, Renderer::ShowGalaxies, gtk_toggle_action_get_active(action));
  841 }
  842 
  843 
  844 void actionRenderGlobulars(GtkToggleAction* action, AppData* app)
  845 {
  846     setRenderFlag(app, Renderer::ShowGlobulars, gtk_toggle_action_get_active(action));
  847 }
  848 
  849 
  850 void actionRenderHorizontalGrid(GtkToggleAction* action, AppData* app)
  851 {
  852     setRenderFlag(app, Renderer::ShowHorizonGrid, gtk_toggle_action_get_active(action));
  853 }
  854 
  855 
  856 void actionRenderMarkers(GtkToggleAction* action, AppData* app)
  857 {
  858     setRenderFlag(app, Renderer::ShowMarkers, gtk_toggle_action_get_active(action));
  859 }
  860 
  861 
  862 void actionRenderNebulae(GtkToggleAction* action, AppData* app)
  863 {
  864     setRenderFlag(app, Renderer::ShowNebulae, gtk_toggle_action_get_active(action));
  865 }
  866 
  867 
  868 void actionRenderNightLights(GtkToggleAction* action, AppData* app)
  869 {
  870     setRenderFlag(app, Renderer::ShowNightMaps, gtk_toggle_action_get_active(action));
  871 }
  872 
  873 
  874 void actionRenderOpenClusters(GtkToggleAction* action, AppData* app)
  875 {
  876     setRenderFlag(app, Renderer::ShowOpenClusters, gtk_toggle_action_get_active(action));
  877 }
  878 
  879 
  880 void actionRenderOrbits(GtkToggleAction* action, AppData* app)
  881 {
  882     setRenderFlag(app, Renderer::ShowOrbits, gtk_toggle_action_get_active(action));
  883 }
  884 
  885 
  886 void actionRenderPlanets(GtkToggleAction* action, AppData* app)
  887 {
  888     setRenderFlag(app, Renderer::ShowPlanets, gtk_toggle_action_get_active(action));
  889 }
  890 
  891 
  892 void actionRenderRingShadows(GtkToggleAction* action, AppData* app)
  893 {
  894     setRenderFlag(app, Renderer::ShowRingShadows, gtk_toggle_action_get_active(action));
  895 }
  896 
  897 
  898 void actionRenderStars(GtkToggleAction* action, AppData* app)
  899 {
  900     setRenderFlag(app, Renderer::ShowStars, gtk_toggle_action_get_active(action));
  901 }
  902 
  903 
  904 void actionOrbitAsteroids(GtkToggleAction* action, AppData* app)
  905 {
  906     setOrbitMask(app, Body::Asteroid, gtk_toggle_action_get_active(action));
  907 }
  908 
  909 
  910 void actionOrbitComets(GtkToggleAction* action, AppData* app)
  911 {
  912     setOrbitMask(app, Body::Comet, gtk_toggle_action_get_active(action));
  913 }
  914 
  915 
  916 void actionOrbitMoons(GtkToggleAction* action, AppData* app)
  917 {
  918     setOrbitMask(app, Body::Moon, gtk_toggle_action_get_active(action));
  919 }
  920 
  921 
  922 void actionOrbitPlanets(GtkToggleAction* action, AppData* app)
  923 {
  924     setOrbitMask(app, Body::Planet, gtk_toggle_action_get_active(action));
  925 }
  926 
  927 
  928 void actionOrbitSpacecraft(GtkToggleAction* action, AppData* app)
  929 {
  930     setOrbitMask(app, Body::Spacecraft, gtk_toggle_action_get_active(action));
  931 }
  932 
  933 
  934 void actionLabelAsteroids(GtkToggleAction* action, AppData* app)
  935 {
  936     setLabelMode(app, Renderer::AsteroidLabels, gtk_toggle_action_get_active(action));
  937 }
  938 
  939 
  940 void actionLabelComets(GtkToggleAction* action, AppData* app)
  941 {
  942     setLabelMode(app, Renderer::CometLabels, gtk_toggle_action_get_active(action));
  943 }
  944 
  945 
  946 void actionLabelConstellations(GtkToggleAction* action, AppData* app)
  947 {
  948     setLabelMode(app, Renderer::ConstellationLabels, gtk_toggle_action_get_active(action));
  949 }
  950 
  951 
  952 void actionLabelGalaxies(GtkToggleAction* action, AppData* app)
  953 {
  954     setLabelMode(app, Renderer::GalaxyLabels, gtk_toggle_action_get_active(action));
  955 }
  956 
  957 
  958 void actionLabelGlobulars(GtkToggleAction* action, AppData* app)
  959 {
  960     setLabelMode(app, Renderer::GlobularLabels, gtk_toggle_action_get_active(action));
  961 }
  962 
  963 
  964 void actionLabelLocations(GtkToggleAction* action, AppData* app)
  965 {
  966     setLabelMode(app, Renderer::LocationLabels, gtk_toggle_action_get_active(action));
  967 }
  968 
  969 
  970 void actionLabelMoons(GtkToggleAction* action, AppData* app)
  971 {
  972     setLabelMode(app, Renderer::MoonLabels, gtk_toggle_action_get_active(action));
  973 }
  974 
  975 
  976 void actionLabelNebulae(GtkToggleAction* action, AppData* app)
  977 {
  978     setLabelMode(app, Renderer::NebulaLabels, gtk_toggle_action_get_active(action));
  979 }
  980 
  981 
  982 void actionLabelOpenClusters(GtkToggleAction* action, AppData* app)
  983 {
  984     setLabelMode(app, Renderer::OpenClusterLabels, gtk_toggle_action_get_active(action));
  985 }
  986 
  987 
  988 void actionLabelPlanets(GtkToggleAction* action, AppData* app)
  989 {
  990     setLabelMode(app, Renderer::PlanetLabels, gtk_toggle_action_get_active(action));
  991 }
  992 
  993 
  994 void actionLabelSpacecraft(GtkToggleAction* action, AppData* app)
  995 {
  996     setLabelMode(app, Renderer::SpacecraftLabels, gtk_toggle_action_get_active(action));
  997 }
  998 
  999 
 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() */
 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() */
 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
 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. */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 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 */
 1454 #ifdef GNOME
 1455 void resyncGalaxyGainActions(AppData* app)
 1456 {
 1457     float gain = Galaxy::getLightGain();
 1458     gconf_client_set_float(app->client, "/apps/celestia/galaxyLightGain", gain, NULL);
 1459 }
 1460 #else
 1461 void resyncGalaxyGainActions(AppData*)
 1462 {
 1463 }
 1464 #endif
 1465 
 1466 
 1467 /* Synchronizes the Texture Resolution with the state of the core */
 1468 #ifdef GNOME
 1469 void resyncTextureResolutionActions(AppData* app)
 1470 {
 1471     int resolution = app->renderer->getResolution();
 1472     gconf_client_set_int(app->client, "/apps/celestia/textureResolution", resolution, NULL);
 1473 }
 1474 #else
 1475 void resyncTextureResolutionActions(AppData*)
 1476 {
 1477 }
 1478 #endif