Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

dialog-options.cpp

Go to the documentation of this file.
00001 /*
00002  *  Celestia GTK+ Front-End
00003  *  Copyright (C) 2005 Pat Suwalski <pat@suwalski.net>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  $Id: dialog-options.cpp,v 1.3 2005/12/16 00:57:05 suwalski Exp $
00011  */
00012 
00013 #include <gtk/gtk.h>
00014 
00015 #include <celutil/debug.h>
00016 
00017 #include "dialog-options.h"
00018 #include "common.h"
00019 #include "ui.h"
00020 
00021 
00022 /* Definitions: Callbacks */
00023 static gint changeDistanceLimit(GtkRange *slider, AppData* app);
00024 
00025 /* Definitions: Helpers */
00026 static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box);
00027 static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box);
00028 static float makeDistanceLimit(float value);
00029 
00030 
00031 static const int DistanceSliderRange = 10000;
00032 static const float MaxDistanceLimit = 1.0e6f;
00033 
00034 
00035 /* ENTRY: Options -> View Options... */
00036 void dialogViewOptions(AppData* app)
00037 {
00038         /* This dialog is hidden and shown because it is likely to be used a lot
00039          * and the actions->widgets operations are fairly intensive. */
00040         if (app->optionDialog != NULL)
00041         {
00042                 gtk_window_present(GTK_WINDOW(app->optionDialog));
00043                 return;
00044         }
00045         
00046     app->optionDialog = gtk_dialog_new_with_buttons("View Options",
00047                                                     GTK_WINDOW(app->mainWindow),
00048                                                         GTK_DIALOG_DESTROY_WITH_PARENT,
00049                                                         GTK_STOCK_OK,
00050                                                         GTK_RESPONSE_OK,
00051                                                         NULL);
00052         
00053         /* Create the main layout boxes */
00054     GtkWidget* hbox = gtk_hbox_new(FALSE, CELSPACING);
00055     GtkWidget* midBox = gtk_vbox_new(FALSE, CELSPACING);
00056     GtkWidget* miscBox = gtk_vbox_new(FALSE, CELSPACING);
00057 
00058         /* Create all of the frames */
00059         GtkWidget* showFrame = gtk_frame_new("Show");
00060         GtkWidget* orbitFrame = gtk_frame_new("Orbits");
00061         GtkWidget* labelFrame = gtk_frame_new("Label");
00062     GtkWidget* limitFrame = gtk_frame_new("Filter Stars");
00063     GtkWidget* infoFrame = gtk_frame_new("Info Text");
00064     GtkWidget* ambientFrame = gtk_frame_new("Ambient Light");
00065 
00066         /* Create the boxes that go in the frames */
00067         GtkWidget* showBox = gtk_vbox_new(FALSE, 0);
00068         GtkWidget* labelBox = gtk_vbox_new(FALSE, 0);
00069         GtkWidget* orbitBox = gtk_vbox_new(FALSE, 0);
00070         GtkWidget* limitBox = gtk_vbox_new(FALSE, 0);
00071         GtkWidget* infoBox = gtk_vbox_new(FALSE, 0);
00072         GtkWidget* ambientBox = gtk_vbox_new(FALSE, 0);
00073     
00074         /* Set border padding on the boxes */
00075         gtk_container_border_width(GTK_CONTAINER(showBox), CELSPACING);
00076         gtk_container_border_width(GTK_CONTAINER(labelBox), CELSPACING);
00077         gtk_container_border_width(GTK_CONTAINER(orbitBox), CELSPACING);
00078     gtk_container_border_width(GTK_CONTAINER(limitBox), CELSPACING);
00079     gtk_container_border_width(GTK_CONTAINER(ambientBox), CELSPACING);
00080     gtk_container_border_width(GTK_CONTAINER(infoBox), CELSPACING);
00081         
00082         /* Set border padding on the frames */
00083         gtk_container_border_width(GTK_CONTAINER(showFrame), 0);
00084         gtk_container_border_width(GTK_CONTAINER(labelFrame), 0);
00085         gtk_container_border_width(GTK_CONTAINER(orbitFrame), 0);
00086     gtk_container_border_width(GTK_CONTAINER(limitFrame), 0);
00087     gtk_container_border_width(GTK_CONTAINER(ambientFrame), 0);
00088     gtk_container_border_width(GTK_CONTAINER(infoFrame), 0);
00089         
00090         /* Place the boxes in the frames */
00091         gtk_container_add(GTK_CONTAINER(showFrame), GTK_WIDGET(showBox));
00092         gtk_container_add(GTK_CONTAINER(labelFrame), GTK_WIDGET(labelBox));
00093         gtk_container_add(GTK_CONTAINER(orbitFrame), GTK_WIDGET(orbitBox));
00094     gtk_container_add(GTK_CONTAINER(limitFrame),GTK_WIDGET(limitBox));
00095         gtk_container_add(GTK_CONTAINER(ambientFrame),GTK_WIDGET(ambientBox));
00096         gtk_container_add(GTK_CONTAINER(infoFrame),GTK_WIDGET(infoBox));
00097 
00098         /* Pack the frames into the top-level boxes and into the window */
00099     gtk_box_pack_start(GTK_BOX(hbox), showFrame, TRUE, TRUE, 0);
00100     gtk_box_pack_start(GTK_BOX(midBox), labelFrame, TRUE, TRUE, 0);
00101     gtk_box_pack_start(GTK_BOX(midBox), limitFrame, TRUE, TRUE, 0);
00102         gtk_box_pack_start(GTK_BOX(miscBox), orbitFrame, TRUE, TRUE, 0);
00103     gtk_box_pack_start(GTK_BOX(miscBox), ambientFrame, TRUE, TRUE, 0);
00104     gtk_box_pack_start(GTK_BOX(miscBox), infoFrame, TRUE, TRUE, 0);
00105     gtk_box_pack_start(GTK_BOX(hbox), midBox, TRUE, TRUE, 0);
00106     gtk_box_pack_start(GTK_BOX(hbox), miscBox, TRUE, TRUE, 0);
00107     gtk_box_pack_start(GTK_BOX(GTK_DIALOG (app->optionDialog)->vbox), hbox, TRUE,
00108                        TRUE, 0);
00109 
00110         gtk_container_set_border_width(GTK_CONTAINER(hbox), CELSPACING);
00111 
00112         float logDistanceLimit = log(app->renderer->getDistanceLimit()) / log((float)MaxDistanceLimit);
00113     GtkAdjustment *adj= (GtkAdjustment *)
00114                                                         gtk_adjustment_new((gfloat)(logDistanceLimit * DistanceSliderRange),
00115                                                0.0, DistanceSliderRange, 1.0, 2.0, 0.0);
00116 
00117         GtkWidget* magLabel = gtk_label_new(NULL);
00118         GtkWidget* slider = gtk_hscale_new(adj);
00119         g_object_set_data(G_OBJECT(slider), "valueLabel", magLabel);
00120         gtk_scale_set_draw_value(GTK_SCALE(slider), 0);
00121         gtk_box_pack_start(GTK_BOX(limitBox), slider, TRUE, TRUE, 0);
00122         gtk_box_pack_start(GTK_BOX(limitBox), magLabel, TRUE, TRUE, 0);
00123         g_signal_connect(GTK_OBJECT(slider), "value-changed", G_CALLBACK(changeDistanceLimit), app);
00124         changeDistanceLimit(GTK_RANGE(GTK_HSCALE(slider)), app);
00125 
00126         checkButtonsFromAG(actionsRenderFlags, G_N_ELEMENTS(actionsRenderFlags), app->agRender, showBox);
00127         checkButtonsFromAG(actionsOrbitFlags, G_N_ELEMENTS(actionsOrbitFlags), app->agOrbit, orbitBox);
00128         checkButtonsFromAG(actionsLabelFlags, G_N_ELEMENTS(actionsLabelFlags), app->agLabel, labelBox);
00129         toggleButtonsFromAG(actionsVerbosity, G_N_ELEMENTS(actionsVerbosity), app->agVerbosity, infoBox);
00130         toggleButtonsFromAG(actionsAmbientLight, G_N_ELEMENTS(actionsAmbientLight), app->agAmbient, ambientBox);
00131 
00132         g_signal_connect(app->optionDialog, "response",
00133                          G_CALLBACK(gtk_widget_hide), GTK_WIDGET(app->optionDialog));
00134 
00135         gtk_widget_show_all(hbox);
00136 
00137         gtk_dialog_set_default_response(GTK_DIALOG(app->optionDialog), GTK_RESPONSE_OK);
00138         gtk_window_present(GTK_WINDOW(app->optionDialog));
00139 }
00140 
00141 
00142 /* CALLBACK: React to changes in the star distance limit slider */
00143 static gint changeDistanceLimit(GtkRange *slider, AppData* app)
00144 {
00145         GtkLabel* magLabel = (GtkLabel*)g_object_get_data(G_OBJECT(slider), "valueLabel");
00146         float limit = makeDistanceLimit(gtk_range_get_value(slider));
00147         app->renderer->setDistanceLimit(limit);
00148 
00149         char labeltext[16] = "100000 ly";
00150         sprintf(labeltext, "%ld ly", (long)limit);
00151         gtk_label_set_text(GTK_LABEL(magLabel), labeltext);
00152 
00153         return TRUE;
00154 }
00155 
00156 
00157 /* HELPER: Creates check buttons from a GtkActionGroup */
00158 static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box)
00159 {
00160         for (int i = 0; i < size; i++) {
00161                 GtkAction* action = gtk_action_group_get_action(ag, actions[i].name);
00162                 
00163                 /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label
00164                  * is not set with action proxy. */
00165                 GtkWidget* w = gtk_check_button_new_with_mnemonic(actions[i].label);
00166 
00167                 gtk_action_connect_proxy(action, w);
00168                 gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0);
00169         }
00170 }
00171 
00172 
00173 /* HELPER: Creates toggle (instead of radio) buttons from a GtkActionGroup.
00174  *         Cannot be GtkRadioButtons because of GTK limitations/bugs. */
00175 static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box)
00176 {
00177         for (int i = 0; i < size; i++) {
00178                 GtkAction* action = gtk_action_group_get_action(ag, actions[i].name);
00179 
00180                 /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label
00181                  * is not set with action proxy. */
00182                 GtkWidget* w = gtk_toggle_button_new_with_mnemonic(actions[i].label);
00183 
00184                 gtk_action_connect_proxy(action, w);
00185                 gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0);
00186         }
00187 }
00188 
00189 
00190 /* HELPER: gives a logarithmic value based on linear value */
00191 static float makeDistanceLimit(float value)
00192 {
00193         float logDistanceLimit = value / DistanceSliderRange;
00194         return (float) pow(MaxDistanceLimit, logDistanceLimit);
00195 }

Generated on Sat Jan 14 22:30:30 2006 for Celestia by  doxygen 1.4.1