actions.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:43k
源码类别:

OpenGL

开发平台:

Visual C++

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