1 // StarPlot - A program for interactively viewing 3D maps of stellar positions.
2 // Copyright (C) 2000 Kevin B. McCarty
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 /*
20 hrdiagram.cc
21 This file contains code for viewing a Hertzsprung-Russell diagram of the
22 stars being shown in the main program window.
23 */
24
25 #include <gtk/gtk.h>
26 #include "starplot.h"
27 #include <cstdlib>
28
29 /* Functions to make sure the HR Diagram window stays updated */
30
31 namespace globals {
32 static GtkWidget *program_hr_window = NULL;
33 static GdkPixmap *program_hr_pixmap = NULL;
34 }
35
36
hr_redraw_display(GtkWidget * widget)37 void hr_redraw_display(GtkWidget *widget)
38 {
39 if (globals::program_hr_viewer && globals::chart_stararray) {
40 globals::chart_stararray->Diagram(globals::program_hr_viewer,
41 globals::hr_mag_bright,
42 globals::hr_mag_dim);
43 gdk_draw_pixmap(widget->window,
44 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
45 globals::program_hr_pixmap,
46 0, 0, 0, 0,
47 widget->allocation.width, widget->allocation.height);
48 }
49 }
50
51
52 /* Create a new backing pixmap of the appropriate size */
configure_event(GtkWidget * widget,GdkEventConfigure * event)53 static gint configure_event( GtkWidget *widget,
54 GdkEventConfigure *event )
55 {
56 if (globals::program_hr_pixmap) {
57 delete globals::program_hr_viewer;
58 gdk_pixmap_unref (globals::program_hr_pixmap);
59 }
60 globals::program_hr_pixmap = gdk_pixmap_new(widget->window,
61 widget->allocation.width,
62 widget->allocation.height,
63 -1);
64 globals::program_hr_viewer =
65 new GTKViewer(globals::program_hr_pixmap, globals::program_hr_canvas);
66 hr_redraw_display(widget);
67 return true;
68 }
69
70
71 /* Redraw the screen from the backing pixmap */
expose_event(GtkWidget * widget,GdkEventExpose * event)72 static gint expose_event( GtkWidget *widget,
73 GdkEventExpose *event )
74 {
75 gdk_draw_pixmap(widget->window,
76 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
77 globals::program_hr_pixmap,
78 event->area.x, event->area.y,
79 event->area.x, event->area.y,
80 event->area.width, event->area.height);
81 return false;
82 }
83
84
85 /* function to exit the HR Diagram window */
hr_quit()86 void hr_quit()
87 {
88 delete globals::program_hr_viewer;
89 globals::program_hr_viewer = NULL;
90 gtk_widget_destroy(globals::program_hr_window);
91 return;
92 }
93
94
95 /* functions allowing to set the magnitude bounds of the HR Diagram */
96
97 /* callback functions: */
hr_mag_callback(GtkWidget * widget,gpointer magnitude_data)98 void hr_mag_callback(GtkWidget *widget, gpointer magnitude_data)
99 {
100 GtkWidget **data = (GtkWidget **)magnitude_data;
101 globals::hr_mag_bright =
102 starmath::atof(gtk_entry_get_text (GTK_ENTRY (data[0])));
103 globals::hr_mag_dim =
104 starmath::atof(gtk_entry_get_text (GTK_ENTRY (data[1])));
105 hr_redraw_display(globals::program_hr_canvas);
106 }
107
hr_mag_defaults(GtkWidget * widget,gpointer data)108 void hr_mag_defaults(GtkWidget *widget,
109 gpointer data /*just here so the type checker is happy*/)
110 {
111 RESET_GLOBAL(hr_mag_bright);
112 RESET_GLOBAL(hr_mag_dim);
113 hr_redraw_display(globals::program_hr_canvas);
114 }
115
116 /* the function displaying the dialog box */
hr_settings()117 void hr_settings()
118 {
119 GtkWidget *hr_set_dialog, *vbox, *table, *labels[2];
120 GtkWidget *OK, *defaults, *cancel;
121 static GtkWidget *entrybox[2];
122 std::string entryboxtext[2];
123
124 // The window
125 hr_set_dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
126 gtk_window_set_resizable (GTK_WINDOW (hr_set_dialog), false);
127 gtk_window_set_title (GTK_WINDOW (hr_set_dialog),
128 /* TRANSLATORS: "HR" stands for "Hertzsprung-Russell", a proper name. */
129 _("StarPlot: HR Diagram Scale"));
130 gtk_window_set_modal (GTK_WINDOW (hr_set_dialog), true);
131 g_signal_connect (G_OBJECT (hr_set_dialog), "destroy",
132 G_CALLBACK (gtk_widget_destroy), NULL);
133
134 // Pack it vertically
135 vbox = gtk_vbox_new (false, 10);
136 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
137 gtk_container_add (GTK_CONTAINER (hr_set_dialog), vbox);
138 gtk_widget_show (vbox);
139
140 // will put in a table:
141 table = gtk_table_new (2, 2, false);
142 gtk_box_pack_start (GTK_BOX (vbox), table, true, false, 0);
143 gtk_widget_show (table);
144
145 labels[0] = gtk_label_new (_("Magnitude at top of y axis:"));
146 labels[1] = gtk_label_new (_("Magnitude at bottom of y axis:"));
147 entryboxtext[0] = starstrings::ftoa(globals::hr_mag_bright);
148 entryboxtext[1] = starstrings::ftoa(globals::hr_mag_dim);
149
150 for (unsigned int i = 0; i < 2; i++) {
151 gtk_misc_set_alignment (GTK_MISC (labels[i]), 0.0F, 0.0F);
152 gtk_widget_show (labels[i]);
153
154 entrybox[i] = gtk_entry_new_with_max_length (8);
155 gtk_widget_set_usize (entrybox[i], 50, 20);
156 gtk_entry_set_text (GTK_ENTRY (entrybox[i]), entryboxtext[i].c_str());
157 gtk_widget_show (entrybox[i]);
158
159 gtk_table_attach (GTK_TABLE (table), labels[i], 0, 1, i, i + 1,
160 (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)GTK_FILL,
161 5, 5);
162 gtk_table_attach (GTK_TABLE (table), entrybox[i], 1, 2, i, i + 1,
163 (GtkAttachOptions)0, (GtkAttachOptions)0, 5, 5);
164 }
165
166 // set up the buttons
167 my_gtk_button_bar (&OK, &defaults, &cancel, vbox);
168 g_signal_connect (G_OBJECT (OK), "clicked",
169 G_CALLBACK (hr_mag_callback),
170 entrybox);
171 g_signal_connect (G_OBJECT (defaults), "clicked",
172 G_CALLBACK (hr_mag_defaults), NULL);
173 my_gtk_buttons_connect_destroy(OK, defaults, cancel, hr_set_dialog);
174
175 gtk_window_set_focus (GTK_WINDOW (hr_set_dialog), OK);
176 gtk_widget_show (hr_set_dialog);
177 }
178
179
180 /* Here are all the items in the StarPlot HR Diagram window's menu.
181 * Unimplemented items have been commented out.
182 * Note: C++ compilers don't like having non-void callback functions in the
183 * GtkItemFactoryEntry struct. It interferes with strict type checking.
184 */
185
186 GtkItemFactoryEntry hr_menu_items[] = { /* fn. */
187 /* menu path acc. key callback fn. param type */
188 {
189 _("/_File"), 0, 0, 0, "<Branch>" },
190 //{ _("/File/_Save Window as PNG..."), 0, hr_save, 0, "" },
191 {
192 _("/File/_Close Window"), 0, hr_quit, 0, "" },
193
194 { _("/_Options"), 0, 0, 0, "<Branch>" },
195 { _("/Options/Scale _Y Axis..."),0, hr_settings, 0, "" },
196
197 // star label and star diameter submenus
198 OPTIONS_LABEL_MENU, OPTIONS_DIAMETER_MENU // #defined in menu.h
199 };
200
201 GtkWidget *hr_options_label_widgets[OPTIONS_LABEL_MENU_SIZE];
202 GtkWidget *hr_options_diameter_widgets[OPTIONS_DIAMETER_MENU_SIZE];
203
204
205 /* hr_main_menu(): This function prepares the StarPlot HR Diagram window
206 menu bar. */
207
hr_main_menu(GtkWidget * hr_window,GtkWidget ** menubar)208 void hr_main_menu (GtkWidget *hr_window, GtkWidget **menubar)
209 {
210 GtkItemFactory *item_factory;
211 GtkAccelGroup *accel_group;
212 int nmenu_items = sizeof (hr_menu_items) / sizeof (hr_menu_items[0]);
213 static bool inited = false;
214
215 if (! inited) {
216 /* Gettextize the menu item names */
217 for (int i = 0; i < nmenu_items; i++) {
218 hr_menu_items[i].path = strdup(gettext(hr_menu_items[i].path));
219 if (hr_menu_items[i].item_type[0] != 0 &&
220 hr_menu_items[i].item_type[0] != '<')
221 hr_menu_items[i].item_type = strdup(gettext(hr_menu_items[i].item_type));
222 }
223 inited = true;
224 }
225
226 accel_group = gtk_accel_group_new ();
227
228 /* This function initializes the item factory.
229 Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
230 or GTK_TYPE_OPTION_MENU.
231 Param 2: The path of the menu.
232 Param 3: A pointer to a gtk_accel_group. The item factory sets up
233 the accelerator table while generating menus.
234 */
235
236 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
237 accel_group);
238
239 /* This function generates the menu items. Pass the item factory,
240 the number of items in the array, the array itself, and any
241 callback data for the the menu items. */
242 gtk_item_factory_create_items (item_factory, nmenu_items,
243 hr_menu_items, NULL);
244
245 /* Attach the new accelerator group to the window. */
246 gtk_window_add_accel_group (GTK_WINDOW (hr_window), accel_group);
247
248 /* Make the options menu radio button widgets globally available and set
249 * them to have the same state as the main menu options menu */
250 for (unsigned int i = 0; i < OPTIONS_LABEL_MENU_SIZE; i++) {
251 GtkWidget *item;
252 item = gtk_item_factory_get_widget (item_factory,
253 options_label_names[i]);
254 hr_options_label_widgets[i] = item;
255
256 if ((GTK_CHECK_MENU_ITEM (options_label_widgets[i]))->active)
257 set_item(&globals::chart_rules.StarLabels,
258 globals::chart_rules.StarLabels, item, false);
259 }
260
261 for (unsigned int i = 0; i < OPTIONS_DIAMETER_MENU_SIZE; i++) {
262 GtkWidget *item;
263 item = gtk_item_factory_get_widget (item_factory,
264 options_diameter_names[i]);
265 hr_options_diameter_widgets[i] = item;
266
267 if ((GTK_CHECK_MENU_ITEM (options_diameter_widgets[i]))->active)
268 set_item(&globals::chart_rules.StarDiameters,
269 globals::chart_rules.StarDiameters, item, false);
270 }
271
272 if (menubar) {
273 /* Finally, return the actual menu bar created by the item factory. */
274 *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
275 }
276 }
277
278
279 /* The main function for the HR Diagram window */
280
hrdiagram()281 void hrdiagram()
282 {
283 GtkWidget *mainbox = NULL;
284 GtkWidget *menubar;
285
286 // If the HR window is already open, do nothing but put it in front
287 if (globals::program_hr_viewer) {
288 gdk_window_raise(globals::program_hr_window->window);
289 return;
290 }
291
292 /* This sets the window title and border width: */
293 globals::program_hr_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
294 gtk_window_set_title (GTK_WINDOW (globals::program_hr_window),
295 /* TRANSLATORS: "HR" stands for "Hertzsprung-Russell", a proper name. */
296 _("StarPlot: HR Diagram"));
297 gtk_container_set_border_width (GTK_CONTAINER (globals::program_hr_window),0);
298
299 /* Set a delete_event handler for closing the window */
300 g_signal_connect (G_OBJECT (globals::program_hr_window), "delete_event",
301 G_CALLBACK (hr_quit), NULL);
302
303 /* Set the menus for this window. */
304 hr_main_menu (globals::program_hr_window, &menubar);
305
306 /* Set up the drawing area */
307 globals::program_hr_canvas = gtk_drawing_area_new();
308 gtk_widget_modify_font (GTK_WIDGET (globals::program_hr_canvas),
309 pango_font_description_from_string (globals::display_fontname.c_str()));
310 gtk_drawing_area_size (GTK_DRAWING_AREA (globals::program_hr_canvas),
311 defaults::program_hr_width,
312 defaults::program_hr_height);
313
314 /* Signals used to handle backing pixmap */
315 g_signal_connect (G_OBJECT (globals::program_hr_canvas), "expose_event",
316 G_CALLBACK (expose_event), NULL);
317 g_signal_connect (G_OBJECT (globals::program_hr_canvas), "configure_event",
318 G_CALLBACK (configure_event), NULL);
319
320 /* Event signals */
321 // g_signal_connect (G_OBJECT (hr_drawing_area), "button_press_event",
322 // G_CALLBACK (button_press_event), NULL);
323 gtk_widget_set_events (globals::program_hr_canvas, GDK_EXPOSURE_MASK
324 | GDK_LEAVE_NOTIFY_MASK
325 | GDK_BUTTON_PRESS_MASK
326 | GDK_POINTER_MOTION_MASK
327 | GDK_POINTER_MOTION_HINT_MASK);
328
329 /* finish putting widgets together */
330 mainbox = gtk_vbox_new (false, 0);
331 gtk_container_border_width (GTK_CONTAINER (mainbox), 1);
332 gtk_container_add (GTK_CONTAINER (globals::program_hr_window), mainbox);
333 gtk_box_pack_start (GTK_BOX (mainbox), menubar, false, true, 0);
334 gtk_box_pack_start (GTK_BOX (mainbox), globals::program_hr_canvas,
335 true, true, 0);
336
337 gtk_widget_realize (globals::program_hr_canvas);
338 hr_redraw_display (globals::program_hr_canvas);
339 gtk_widget_show (globals::program_hr_canvas);
340 gtk_widget_show (menubar);
341 gtk_widget_show (mainbox);
342 gtk_widget_show (globals::program_hr_window);
343
344 return;
345 }
346