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

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: dialog-options.cpp,v 1.7 2008-01-21 04:55:19 suwalski Exp $
  11.  */
  12. #include <gtk/gtk.h>
  13. #include <celutil/debug.h>
  14. #include "dialog-options.h"
  15. #include "common.h"
  16. #include "ui.h"
  17. /* Definitions: Callbacks */
  18. static gint changeDistanceLimit(GtkRange *slider, AppData* app);
  19. static gint changeTextureResolution(GtkRange *slider, AppData* app);
  20. static gchar* formatTextureSlider(GtkRange*, gdouble value);
  21. /* Definitions: Helpers */
  22. static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box);
  23. static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box);
  24. static float makeDistanceLimit(float value);
  25. static const int DistanceSliderRange = 10000;
  26. static const float MaxDistanceLimit = 1.0e6f;
  27. /* ENTRY: Options -> View Options... */
  28. void dialogViewOptions(AppData* app)
  29. {
  30. /* This dialog is hidden and shown because it is likely to be used a lot
  31.  * and the actions->widgets operations are fairly intensive. */
  32. if (app->optionDialog != NULL)
  33. {
  34. gtk_window_present(GTK_WINDOW(app->optionDialog));
  35. return;
  36. }
  37. app->optionDialog = gtk_dialog_new_with_buttons("View Options",
  38.                                                 GTK_WINDOW(app->mainWindow),
  39.                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
  40.                                                 GTK_STOCK_OK,
  41.                                                 GTK_RESPONSE_OK,
  42.                                                 NULL);
  43. /* Create the main layout boxes */
  44. GtkWidget* hbox = gtk_hbox_new(FALSE, CELSPACING);
  45. GtkWidget* midBox = gtk_vbox_new(FALSE, CELSPACING);
  46. GtkWidget* miscBox = gtk_vbox_new(FALSE, CELSPACING);
  47. /* Create all of the frames */
  48. GtkWidget* showFrame = gtk_frame_new("Show");
  49. GtkWidget* orbitFrame = gtk_frame_new("Orbits");
  50. GtkWidget* labelFrame = gtk_frame_new("Label");
  51. GtkWidget* limitFrame = gtk_frame_new("Filter Stars");
  52. GtkWidget* textureFrame = gtk_frame_new("Texture Detail");
  53. GtkWidget* infoFrame = gtk_frame_new("Info Text");
  54. GtkWidget* ambientFrame = gtk_frame_new("Ambient Light");
  55. /* Create the boxes that go in the frames */
  56. GtkWidget* showBox = gtk_vbox_new(FALSE, 0);
  57. GtkWidget* labelBox = gtk_vbox_new(FALSE, 0);
  58. GtkWidget* orbitBox = gtk_vbox_new(FALSE, 0);
  59. GtkWidget* limitBox = gtk_vbox_new(FALSE, 0);
  60. GtkWidget* textureBox = gtk_vbox_new(FALSE, 0);
  61. GtkWidget* infoBox = gtk_vbox_new(FALSE, 0);
  62. GtkWidget* ambientBox = gtk_vbox_new(FALSE, 0);
  63.     
  64. /* Set border padding on the boxes */
  65. gtk_container_border_width(GTK_CONTAINER(showBox), CELSPACING);
  66. gtk_container_border_width(GTK_CONTAINER(labelBox), CELSPACING);
  67. gtk_container_border_width(GTK_CONTAINER(orbitBox), CELSPACING);
  68. gtk_container_border_width(GTK_CONTAINER(limitBox), CELSPACING);
  69. gtk_container_border_width(GTK_CONTAINER(textureBox), CELSPACING);
  70. gtk_container_border_width(GTK_CONTAINER(ambientBox), CELSPACING);
  71. gtk_container_border_width(GTK_CONTAINER(infoBox), CELSPACING);
  72. /* Set border padding on the frames */
  73. gtk_container_border_width(GTK_CONTAINER(showFrame), 0);
  74. gtk_container_border_width(GTK_CONTAINER(labelFrame), 0);
  75. gtk_container_border_width(GTK_CONTAINER(orbitFrame), 0);
  76. gtk_container_border_width(GTK_CONTAINER(limitFrame), 0);
  77. gtk_container_border_width(GTK_CONTAINER(textureFrame), 0);
  78. gtk_container_border_width(GTK_CONTAINER(ambientFrame), 0);
  79. gtk_container_border_width(GTK_CONTAINER(infoFrame), 0);
  80. /* Place the boxes in the frames */
  81. gtk_container_add(GTK_CONTAINER(showFrame), GTK_WIDGET(showBox));
  82. gtk_container_add(GTK_CONTAINER(labelFrame), GTK_WIDGET(labelBox));
  83. gtk_container_add(GTK_CONTAINER(orbitFrame), GTK_WIDGET(orbitBox));
  84. gtk_container_add(GTK_CONTAINER(limitFrame),GTK_WIDGET(limitBox));
  85. gtk_container_add(GTK_CONTAINER(textureFrame),GTK_WIDGET(textureBox));
  86. gtk_container_add(GTK_CONTAINER(ambientFrame),GTK_WIDGET(ambientBox));
  87. gtk_container_add(GTK_CONTAINER(infoFrame),GTK_WIDGET(infoBox));
  88. /* Pack the frames into the top-level boxes and into the window */
  89. gtk_box_pack_start(GTK_BOX(hbox), showFrame, TRUE, TRUE, 0);
  90. gtk_box_pack_start(GTK_BOX(midBox), labelFrame, TRUE, TRUE, 0);
  91. gtk_box_pack_start(GTK_BOX(midBox), limitFrame, TRUE, TRUE, 0);
  92. gtk_box_pack_start(GTK_BOX(midBox), textureFrame, TRUE, TRUE, 0);
  93. gtk_box_pack_start(GTK_BOX(miscBox), orbitFrame, TRUE, TRUE, 0);
  94. gtk_box_pack_start(GTK_BOX(miscBox), ambientFrame, TRUE, TRUE, 0);
  95. gtk_box_pack_start(GTK_BOX(miscBox), infoFrame, TRUE, TRUE, 0);
  96. gtk_box_pack_start(GTK_BOX(hbox), midBox, TRUE, TRUE, 0);
  97. gtk_box_pack_start(GTK_BOX(hbox), miscBox, TRUE, TRUE, 0);
  98. gtk_box_pack_start(GTK_BOX(GTK_DIALOG (app->optionDialog)->vbox), hbox, TRUE,
  99.                    TRUE, 0);
  100. gtk_container_set_border_width(GTK_CONTAINER(hbox), CELSPACING);
  101. float logDistanceLimit = log(app->renderer->getDistanceLimit()) / log((float)MaxDistanceLimit);
  102. GtkAdjustment *adj = (GtkAdjustment *)
  103.                         gtk_adjustment_new((gfloat)(logDistanceLimit * DistanceSliderRange),
  104.                         0.0, DistanceSliderRange, 1.0, 2.0, 0.0);
  105. /* Distance limit slider */
  106. GtkWidget* magLabel = gtk_label_new(NULL);
  107. GtkWidget* slider = gtk_hscale_new(adj);
  108. g_object_set_data(G_OBJECT(slider), "valueLabel", magLabel);
  109. gtk_scale_set_draw_value(GTK_SCALE(slider), 0);
  110. gtk_box_pack_start(GTK_BOX(limitBox), slider, TRUE, TRUE, 0);
  111. gtk_box_pack_start(GTK_BOX(limitBox), magLabel, TRUE, TRUE, 0);
  112. g_signal_connect(GTK_OBJECT(slider), "value-changed", G_CALLBACK(changeDistanceLimit), app);
  113. changeDistanceLimit(GTK_RANGE(GTK_HSCALE(slider)), app);
  114. /* Texture resolution slider */
  115. GtkWidget* textureSlider = gtk_hscale_new_with_range(0, 2, 1);
  116. gtk_scale_set_value_pos(GTK_SCALE(textureSlider), GTK_POS_BOTTOM);
  117. gtk_range_set_increments(GTK_RANGE(textureSlider), 1, 1);
  118. gtk_range_set_value(GTK_RANGE(textureSlider), app->renderer->getResolution());
  119. gtk_range_set_update_policy(GTK_RANGE(textureSlider), GTK_UPDATE_DISCONTINUOUS);
  120. gtk_box_pack_start(GTK_BOX(textureBox), textureSlider, TRUE, TRUE, 0);
  121. g_signal_connect(GTK_OBJECT(textureSlider), "value-changed", G_CALLBACK(changeTextureResolution), app);
  122. g_signal_connect(GTK_OBJECT(textureSlider), "format-value", G_CALLBACK(formatTextureSlider), NULL);
  123. checkButtonsFromAG(actionsRenderFlags, G_N_ELEMENTS(actionsRenderFlags), app->agRender, showBox);
  124. checkButtonsFromAG(actionsOrbitFlags, G_N_ELEMENTS(actionsOrbitFlags), app->agOrbit, orbitBox);
  125. checkButtonsFromAG(actionsLabelFlags, G_N_ELEMENTS(actionsLabelFlags), app->agLabel, labelBox);
  126. toggleButtonsFromAG(actionsVerbosity, G_N_ELEMENTS(actionsVerbosity), app->agVerbosity, infoBox);
  127. toggleButtonsFromAG(actionsAmbientLight, G_N_ELEMENTS(actionsAmbientLight), app->agAmbient, ambientBox);
  128. g_signal_connect(app->optionDialog, "response",
  129.                  G_CALLBACK(gtk_widget_hide), GTK_WIDGET(app->optionDialog));
  130. gtk_widget_show_all(hbox);
  131. gtk_dialog_set_default_response(GTK_DIALOG(app->optionDialog), GTK_RESPONSE_OK);
  132. gtk_window_present(GTK_WINDOW(app->optionDialog));
  133. }
  134. /* CALLBACK: React to changes in the star distance limit slider */
  135. static gint changeDistanceLimit(GtkRange *slider, AppData* app)
  136. {
  137. GtkLabel* magLabel = (GtkLabel*)g_object_get_data(G_OBJECT(slider), "valueLabel");
  138. float limit = makeDistanceLimit(gtk_range_get_value(slider));
  139. app->renderer->setDistanceLimit(limit);
  140. char labeltext[16] = "100000 ly";
  141. sprintf(labeltext, "%ld ly", (long)(limit + 0.5));
  142. gtk_label_set_text(GTK_LABEL(magLabel), labeltext);
  143. #ifdef GNOME
  144. /* Distance limit changes do not trigger an event like the other
  145.  * render settings. Save setting here. */
  146. gconf_client_set_int(app->client, "/apps/celestia/distanceLimit", (int)(limit + 0.5), NULL);
  147. #endif /* GNOME */
  148. return TRUE;
  149. }
  150. /* CALLBACK: React to changes in the texture resolution slider */
  151. static gint changeTextureResolution(GtkRange *slider, AppData* app)
  152. {
  153. app->renderer->setResolution((int)gtk_range_get_value(slider));
  154. /* Seeing as this is not a GtkAction, kick off the update function */
  155. resyncTextureResolutionActions(app);
  156. return TRUE;
  157. }
  158. /* CALLBACK: Format the label under the texture detail slider */
  159. static gchar* formatTextureSlider(GtkRange*, gdouble value)
  160. {
  161. switch ((int)value) {
  162. case 0: return g_strdup("Low");
  163. case 1: return g_strdup("Medium");
  164. case 2: return g_strdup("High");
  165. default: return g_strdup("Error");
  166. }
  167. }
  168. /* HELPER: Creates check buttons from a GtkActionGroup */
  169. static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box)
  170. {
  171. for (int i = 0; i < size; i++) {
  172. GtkAction* action = gtk_action_group_get_action(ag, actions[i].name);
  173. /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label
  174.  * is not set with action proxy. */
  175. GtkWidget* w = gtk_check_button_new_with_mnemonic(actions[i].label);
  176. gtk_action_connect_proxy(action, w);
  177. gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0);
  178. }
  179. }
  180. /* HELPER: Creates toggle (instead of radio) buttons from a GtkActionGroup.
  181.  *         Cannot be GtkRadioButtons because of GTK limitations/bugs. */
  182. static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box)
  183. {
  184. for (int i = 0; i < size; i++) {
  185. GtkAction* action = gtk_action_group_get_action(ag, actions[i].name);
  186. /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label
  187.  * is not set with action proxy. */
  188. GtkWidget* w = gtk_toggle_button_new_with_mnemonic(actions[i].label);
  189. gtk_action_connect_proxy(action, w);
  190. gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0);
  191. }
  192. }
  193. /* HELPER: gives a logarithmic value based on linear value */
  194. static float makeDistanceLimit(float value)
  195. {
  196. float logDistanceLimit = value / DistanceSliderRange;
  197. return (float) pow(MaxDistanceLimit, logDistanceLimit);
  198. }