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 infodialogs.cc
21 This file contains code for the dialog boxes in the StarPlot Stars menu,
22 and for the informational popup window.
23 */
24
25 #include <gtk/gtk.h>
26 #include "starplot.h"
27 #include <cstring>
28 using std::string;
29
30 // ---------------------------------------------------------------------------
31 // This function displays an error message popup.
my_gtk_error(GtkWindow * parent_win,const char * error_msg)32 void my_gtk_error (GtkWindow *parent_win, const char * error_msg)
33 {
34 GtkWidget * dialog = gtk_message_dialog_new (parent_win,
35 GTK_DIALOG_DESTROY_WITH_PARENT,
36 GTK_MESSAGE_ERROR,
37 GTK_BUTTONS_CLOSE,
38 error_msg);
39 gtk_dialog_run (GTK_DIALOG (dialog));
40 gtk_widget_destroy (dialog);
41 }
42
43 // ---------------------------------------------------------------------------
44 /* This function displays a popup window of information about the star: */
45
my_gtk_star_popup(Star & s)46 void my_gtk_star_popup(Star &s)
47 {
48 GtkWidget *popup, *OK, *topbox, *expander, *separator,
49 *namebox, *altname, *label[5];
50 StringList starinfo = s.GetInfo(globals::chart_rules);
51 string Name, RA, Dec, Distance, Class, Mag;
52
53 Name = starinfo[1];
54 starstrings::addgreek(Name);
55 if (globals::chart_rules.StarLabels == NUMBER_LABEL)
56 Name = starinfo[0] + ". " + Name;
57 if (globals::chart_rules.CelestialCoords) {
58 RA = string(_("R.A.")) + ": " + starinfo[2];
59 Dec = string(_("Dec.")) + ": " + starinfo[3];
60 }
61 else {
62 RA = string(_("Long.")) + ": " + starinfo[2];
63 Dec = string(_("Lat.")) + ": " + starinfo[3];
64 }
65 Distance = string(_("Distance")) + ": " + starstrings::distance_to_str(
66 s.GetStarDistance(), globals::chart_rules.ChartUnits[1]);
67 Class = string(_("Spectral Class")) + ": " + starinfo[5];
68 Mag = string(_("Magnitude")) + ": " + starstrings::ftoa(s.GetStarMagnitude());
69
70 popup = gtk_dialog_new ();
71 gtk_window_set_resizable (GTK_WINDOW (popup), false);
72 gtk_window_set_title (GTK_WINDOW (popup), _("StarPlot: Star Info"));
73 gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_MOUSE);
74
75 topbox = gtk_vbox_new (false, 0);
76 gtk_container_set_border_width (GTK_CONTAINER (topbox), 10);
77 gtk_widget_show (topbox);
78 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (popup)->vbox), topbox,
79 true, true, 0);
80
81 #if HAVE_GTK_EXPANDER_NEW
82 // name
83 expander = gtk_expander_new ((string("<big><b>") + Name.c_str()
84 + "</b></big>").c_str());
85 gtk_expander_set_use_markup (GTK_EXPANDER (expander), true);
86 gtk_expander_set_expanded (GTK_EXPANDER (expander), false);
87
88 // alternate names
89 namebox = gtk_vbox_new (true, 0);
90 gtk_widget_show (namebox);
91 gtk_container_add (GTK_CONTAINER (expander), namebox);
92
93 for (unsigned int i = 10; i < starinfo.size(); i++) {
94 starstrings::addgreek(starinfo[i]);
95 altname = gtk_label_new (starinfo[i].c_str());
96 gtk_label_set_markup (GTK_LABEL (altname),
97 (string("<b>") + starinfo[i] + string("</b>")).c_str());
98 gtk_misc_set_alignment(GTK_MISC (altname), 0.0F, 0.0F);
99 gtk_widget_show (altname);
100 gtk_box_pack_start (GTK_BOX (namebox), altname, true, true, 0);
101 }
102 #else // no GtkExpander widget, just show best-known name
103 expander = gtk_label_new (Name.c_str());
104 #endif
105 gtk_widget_show (expander);
106 gtk_box_pack_start (GTK_BOX (topbox), expander, false, false, 0);
107
108 separator = gtk_hseparator_new ();
109 gtk_widget_show (separator);
110 gtk_box_pack_start (GTK_BOX (topbox), separator, false, false, 5);
111
112 // other info
113 label[0] = gtk_label_new (RA.c_str());
114 label[1] = gtk_label_new (Dec.c_str());
115 label[2] = gtk_label_new (Distance.c_str());
116 label[3] = gtk_label_new (Class.c_str());
117 label[4] = gtk_label_new (Mag.c_str());
118
119 for (unsigned int i = 0; i < 5; i++) {
120 gtk_box_pack_start (GTK_BOX (topbox), label[i], false, false, 0);
121 gtk_misc_set_alignment(GTK_MISC (label[i]), 0.0F, 0.0F);
122 gtk_widget_show (label[i]);
123 }
124
125 my_gtk_popup_button (&OK, GTK_DIALOG (popup)->action_area, popup);
126 gtk_window_set_focus (GTK_WINDOW (popup), OK);
127 gtk_widget_show (popup);
128 }
129
130 // ---------------------------------------------------------------------------
131 /* Begin auxiliary types and functions for my_gtk_list_setup () */
132
133 enum elisttype { CHARTLIST, NUMBERED_CHARTLIST, SEARCHLIST };
134 enum ecolumntype { COL_INDEX, COL_NAME, COL_ALTNAME, COL_RA, COL_DEC,
135 COL_DISTANCE, COL_SPCLASS, COL_MAGNITUDE, NUM_COLS };
136
137 // Print doubles with at most 4 significant figures. Modified from here:
138 // http://mail.gnome.org/archives/gtk-list/2003-April/msg00326.html
139 void
print_double_to_text(GtkTreeViewColumn * column,GtkCellRenderer * cell,GtkTreeModel * treemodel,GtkTreeIter * iter,void * data)140 print_double_to_text(GtkTreeViewColumn *column,
141 GtkCellRenderer *cell,
142 GtkTreeModel *treemodel,
143 GtkTreeIter *iter,
144 void * data)
145 {
146 GtkCellRendererText *cell_text = (GtkCellRendererText *)cell;
147 double d;
148
149 /* Free the previous (default) text of the column's renderer. */
150 g_free (cell_text->text);
151 /* Get the double value from the model. */
152 gtk_tree_model_get (treemodel, iter, (long)data, &d, -1);
153 /* Now we can format the value ourselves. */
154 cell_text->text = g_strdup (starstrings::ftoa(d, 4).c_str());
155 }
156
157 // Sort function for latitude coordinate
158 // (in order to get strings starting with '-' before those starting
159 // with '+')
160 int
signed_coord_sort_func(GtkTreeModel * model,GtkTreeIter * item1,GtkTreeIter * item2,void * data)161 signed_coord_sort_func(GtkTreeModel * model,
162 GtkTreeIter * item1, GtkTreeIter * item2,
163 void * data)
164 {
165 char * s1, * s2;
166 int result;
167 gtk_tree_model_get (model, item1, COL_DEC, &s1, -1);
168 gtk_tree_model_get (model, item2, COL_DEC, &s2, -1);
169
170 // N.B. we expect strings that look like "[+ -]NNh NNm NN.NNs"
171 char c1 = s1[0], c2 = s2[0];
172 result = std::strcmp(s1, s2);
173
174 if (c1 == '-' && c2 == '-')
175 result *= -1;
176 else if (c1 == '-')
177 result = -1;
178 else if (c2 == '-')
179 result = +1;
180
181 std::free (s1);
182 std::free (s2);
183 return result;
184 }
185
186 // Sort function for spectral class
187 int
spec_class_sort_func(GtkTreeModel * model,GtkTreeIter * item1,GtkTreeIter * item2,void * data)188 spec_class_sort_func(GtkTreeModel * model,
189 GtkTreeIter * item1, GtkTreeIter * item2,
190 void * data)
191 {
192 char * s1, * s2;
193 int M1, M2;
194 double m1, m2, MK1, MK2;
195 int result;
196
197 gtk_tree_model_get (model, item1, COL_SPCLASS, &s1, -1);
198 gtk_tree_model_get (model, item2, COL_SPCLASS, &s2, -1);
199
200 SpecClass *c1 = new SpecClass(string(s1));
201 SpecClass *c2 = new SpecClass(string(s2));
202 std::free (s1);
203 std::free (s2);
204
205 c1->initialize();
206 c2->initialize();
207 M1 = SpecClass::class_to_int(c1->classmajor());
208 M2 = SpecClass::class_to_int(c2->classmajor());
209 if (M1 < 0) M1 = 999;
210 if (M2 < 0) M2 = 999;
211 result = M1 - M2;
212 if (result) goto done;
213
214 m1 = c1->classminor();
215 m2 = c2->classminor();
216 result = static_cast<int>(100 * (m1 - m2));
217 if (result) goto done;
218
219 MK1 = c1->MKtype();
220 MK2 = c2->MKtype();
221 result = static_cast<int>(100 * (MK1 - MK2));
222
223 done:
224 delete c1;
225 delete c2;
226 return result;
227 }
228
229 /* Here is a function which sets up the treeview for starinfo() and
230 * starsearch(). "box" is the box into which the treeview should
231 * be packed. */
232
my_gtk_list_setup(GtkWidget * box,GtkTreeView ** treeviewptr,enum elisttype listtype)233 void my_gtk_list_setup (GtkWidget *box, GtkTreeView **treeviewptr,
234 enum elisttype listtype)
235 {
236 GtkWidget *scrolled_window;
237 GtkTreeView *treeview;
238 GtkListStore *store;
239
240 // set up a scroll window to hold the chart
241 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
242 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
243 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
244 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
245 GTK_SHADOW_IN);
246 gtk_box_pack_start (GTK_BOX (box), scrolled_window, true, true, 0);
247 gtk_widget_show (scrolled_window);
248
249 // set up the data model
250 store = gtk_list_store_new (NUM_COLS, // number of possible columns
251 G_TYPE_UINT, // star index number
252 G_TYPE_STRING, // star name
253 G_TYPE_STRING, // alternate name
254 G_TYPE_STRING, // right ascension
255 G_TYPE_STRING, // declination
256 G_TYPE_DOUBLE, // distance
257 G_TYPE_STRING, // spectral class
258 G_TYPE_DOUBLE); // absolute magnitude
259
260 // set up the data viewer
261 *treeviewptr = (GtkTreeView *)gtk_tree_view_new_with_model (
262 GTK_TREE_MODEL (store));
263 treeview = *treeviewptr;
264 gtk_tree_view_set_rules_hint (treeview, true);
265 gtk_widget_set_usize (GTK_WIDGET (treeview), 600, 300);
266 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (treeview));
267
268 // render the data viewer columns
269 GtkTreeViewColumn *column;
270 GtkCellRenderer *renderer;
271
272 #define COL_SETUP(Text, Index) do { \
273 renderer = gtk_cell_renderer_text_new (); \
274 column = gtk_tree_view_column_new_with_attributes (Text, renderer, \
275 "text", Index, NULL); \
276 gtk_tree_view_column_set_sort_column_id (column, Index); \
277 gtk_tree_view_append_column (treeview, column); } while (0)
278
279 if (listtype == NUMBERED_CHARTLIST)
280 COL_SETUP (_("Label"), COL_INDEX);
281 COL_SETUP (_("Star"), COL_NAME);
282 if (listtype == SEARCHLIST)
283 COL_SETUP (_("Also known as"), COL_ALTNAME);
284 if (globals::chart_rules.CelestialCoords) {
285 COL_SETUP (_("Right Ascension"), COL_RA);
286 COL_SETUP (_("Declination"), COL_DEC);
287 }
288 else {
289 COL_SETUP (_("Gal. Longitude"), COL_RA);
290 COL_SETUP (_("Gal. Latitude"), COL_DEC);
291 }
292 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
293 COL_DEC, signed_coord_sort_func, NULL, NULL);
294 COL_SETUP ((string(_("Distance")) + " ("
295 + distance_name[globals::chart_rules.ChartUnits[1]]
296 + ")").c_str(),
297 COL_DISTANCE);
298 gtk_tree_view_column_set_cell_data_func (column, renderer,
299 print_double_to_text, (void *)COL_DISTANCE, 0);
300 COL_SETUP (_("Class"), COL_SPCLASS);
301 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
302 COL_SPCLASS, spec_class_sort_func, NULL, NULL);
303 COL_SETUP (_("Magnitude"), COL_MAGNITUDE);
304 gtk_tree_view_column_set_cell_data_func (column, renderer,
305 print_double_to_text, (void *)COL_MAGNITUDE, 0);
306 #undef COL_SETUP
307
308 g_object_unref (store);
309 return;
310 }
311
312
313 /* Callback to destroy info window dialog */
314
315 namespace globals {
316 GtkTreeView *program_treeview = NULL;
317 static GtkWidget *program_info_window = NULL;
318 }
319
info_quit()320 void info_quit()
321 {
322 gtk_widget_destroy(globals::program_info_window);
323 globals::program_info_window = NULL;
324 globals::program_treeview = NULL;
325 return;
326 }
327
328 /* Function to update the chart information when necessary */
329
update_info(GtkTreeView * treeview)330 void update_info(GtkTreeView *treeview)
331 {
332 int namecol = (globals::chart_rules.StarLabels == NUMBER_LABEL);
333 GtkTreeViewColumn *column = gtk_tree_view_get_column (treeview, 0);
334 const char *col_label = gtk_tree_view_column_get_title (column);
335
336 // add or remove the "Label" column as necessary
337 if ((!namecol) && strcmp(_("Label"), col_label) == 0) {
338 gtk_tree_view_remove_column (treeview, column);
339 }
340 else if (namecol && strcmp(_("Label"), col_label)) {
341 GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
342 column = gtk_tree_view_column_new_with_attributes (_("Label"), renderer,
343 "text", COL_INDEX, NULL);
344 gtk_tree_view_column_set_sort_column_id (column, COL_INDEX);
345 gtk_tree_view_insert_column (treeview, column, 0);
346 }
347
348 // re-label column headers as necessary
349 column = gtk_tree_view_get_column (treeview, namecol + 1);
350 gtk_tree_view_column_set_title (column,
351 globals::chart_rules.CelestialCoords ?
352 _("Right Ascension") : _("Gal. Longitude"));
353 column = gtk_tree_view_get_column (treeview, namecol + 2);
354 gtk_tree_view_column_set_title (column,
355 globals::chart_rules.CelestialCoords ?
356 _("Declination") : _("Gal. Latitude"));
357 column = gtk_tree_view_get_column (treeview, namecol + 3);
358 gtk_tree_view_column_set_title (column, (string(_("Distance")) + " ("
359 + distance_name[globals::chart_rules.ChartUnits[1]] + ")").c_str());
360
361 // update the data
362 GtkListStore *store = (GtkListStore *)gtk_tree_view_get_model (treeview);
363 GtkTreeIter iter;
364 gtk_list_store_clear (store);
365
366 citerate (StarArray, *globals::chart_stararray, star_ptr) {
367 StringList infolist = (*star_ptr).GetInfo(globals::chart_rules);
368 starstrings::addgreek(infolist[1]);
369 gtk_list_store_append (store, &iter);
370 gtk_list_store_set (store, &iter,
371 COL_INDEX, starmath::atoi(infolist[0]),
372 COL_NAME, infolist[1].c_str(),
373 COL_RA, infolist[2].c_str(),
374 COL_DEC, infolist[3].c_str(),
375 COL_DISTANCE, (*star_ptr).GetStarDistance()
376 * distance_conversion[globals::chart_rules.ChartUnits[1]],
377 COL_SPCLASS, infolist[5].c_str(),
378 COL_MAGNITUDE, (*star_ptr).GetStarMagnitude(),
379 -1 /* to mark end of args */);
380 }
381
382 return;
383 }
384
385 /* This function displays information about the stars shown on the chart. */
386
starinfo()387 void starinfo()
388 {
389 GtkWidget *vbox, *OK;
390 enum elisttype listtype = (globals::chart_rules.StarLabels == NUMBER_LABEL) ?
391 NUMBERED_CHARTLIST : CHARTLIST;
392
393 // If the info window is already open, do nothing but put it in front
394 if (globals::program_info_window) {
395 gdk_window_raise(globals::program_info_window->window);
396 return;
397 }
398
399 // make a window for it
400 globals::program_info_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
401 gtk_window_set_title (GTK_WINDOW (globals::program_info_window),
402 _("StarPlot: Chart Data"));
403 g_signal_connect (G_OBJECT (globals::program_info_window), "destroy",
404 G_CALLBACK (info_quit), NULL);
405
406 // make a vbox
407 vbox = gtk_vbox_new (false, 5);
408 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
409 gtk_container_add (GTK_CONTAINER (globals::program_info_window), vbox);
410 gtk_widget_show (vbox);
411
412 // set up the column list and put star information into it
413 my_gtk_list_setup (vbox, &globals::program_treeview, listtype);
414 update_info(globals::program_treeview);
415
416 // the button to make the window go away
417 my_gtk_popup_button(&OK, vbox, globals::program_info_window);
418 gtk_window_set_focus (GTK_WINDOW (globals::program_info_window), OK);
419 gtk_widget_show_all (globals::program_info_window);
420 return;
421 }
422
423
424 /* These functions allow the user to look up star names containing a string.
425 * (admittedly, doing a `grep' of the star data files would work just as
426 * well, but it wouldn't be all nice and GUI...) */
427
428 GtkWidget *searchwindow = NULL;
429
430 struct sSearchData {
431 GtkWidget *casesensitive;
432 GtkWidget *entrybox;
433 GtkTreeView *sview;
434 };
435
search_callback(GtkWidget * widget,gpointer search_data)436 void search_callback(GtkWidget *widget, gpointer search_data)
437 {
438 sSearchData data = * (sSearchData *)search_data;
439 GtkTreeView *sview = data.sview;
440 GtkListStore *store = (GtkListStore *)gtk_tree_view_get_model (sview);
441 GtkTreeIter iter;
442
443 string searchstring = gtk_entry_get_text(GTK_ENTRY (data.entrybox));
444 bool casesensitive =
445 (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data.casesensitive))
446 == true);
447 StarArray searchresults;
448 StringList information;
449
450 if (starstrings::isempty(searchstring)) return;
451
452 gtk_list_store_clear (store);
453 searchresults.Search(searchstring, globals::chart_rules.ChartFileNames,
454 globals::chart_rules, casesensitive);
455
456 // error checking
457 if (searchresults.size() >= MAX_STARS) {
458 string errormsg = starstrings::ssprintf(
459 _("Showing only the first %d results."), MAX_STARS);
460 my_gtk_error (GTK_WINDOW (searchwindow), errormsg.c_str());
461 }
462 else if (!searchresults.size()) {
463 my_gtk_error (GTK_WINDOW (searchwindow), starstrings::ssprintf(
464 _("Sorry, no stars matching\npattern \"%s\" were found."),
465 searchstring.c_str()).c_str());
466 return;
467 }
468
469 citerate (StarArray, searchresults, result_ptr) {
470 StringList infolist = (*result_ptr).GetInfo(globals::chart_rules);
471
472 // where is the star name which matches the search string in the
473 // list of star characteristics?
474 unsigned int nameplace = starmath::atoi(infolist[0]);
475 unsigned int infolistplace = nameplace ? nameplace + 9 : 1;
476 information.clear();
477 information.push_back(infolist[infolistplace]);
478
479 // if this is not the best-known star name, put that in the "aka" column;
480 // else put the second-best-known star name in that column
481 information.push_back(nameplace ? infolist[1] : infolist[10]);
482 starstrings::addgreek(information[0]);
483 starstrings::addgreek(information[1]);
484
485 iterate_between (StringList, infolist, j, 2, 7)
486 information.push_back(*j);
487
488 gtk_list_store_append (store, &iter);
489 gtk_list_store_set (store, &iter,
490 COL_NAME, information[0].c_str(),
491 COL_ALTNAME, information[1].c_str(),
492 COL_RA, information[2].c_str(),
493 COL_DEC, information[3].c_str(),
494 COL_DISTANCE, (*result_ptr).GetStarDistance()
495 * distance_conversion[globals::chart_rules.ChartUnits[1]],
496 COL_SPCLASS, information[5].c_str(),
497 COL_MAGNITUDE,(*result_ptr).GetStarMagnitude(),
498 -1 /* to mark end of args */);
499 }
500 return;
501 }
502
503 /* Callback to destroy search window dialog */
504
search_quit()505 void search_quit()
506 {
507 gtk_widget_destroy(searchwindow);
508 searchwindow = NULL;
509 return;
510 }
511
512 /* create the search window dialog */
513
starsearch()514 void starsearch()
515 {
516 GtkWidget *vbox, *OK;
517 GtkWidget *hbox, *casesensitive, *entrybox, *searchbutton;
518 GtkTreeView *sview;
519 static sSearchData search_data;
520
521 // If the search window is already open, do nothing but put it in front
522 if (searchwindow) {
523 gdk_window_raise(searchwindow->window);
524 return;
525 }
526
527 // make a window for it
528 searchwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
529 gtk_window_set_title (GTK_WINDOW (searchwindow), _("StarPlot: Search"));
530 g_signal_connect (G_OBJECT (searchwindow), "destroy",
531 G_CALLBACK (search_quit), NULL);
532
533 // make a vbox
534 vbox = gtk_vbox_new (false, 5);
535 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
536 gtk_container_add (GTK_CONTAINER (searchwindow), vbox);
537 gtk_widget_show (vbox);
538
539 // set up the search input field in an hbox
540 casesensitive = gtk_check_button_new_with_label (_("Case sensitive"));
541 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (casesensitive), false);
542 gtk_widget_show (casesensitive);
543
544 entrybox = gtk_entry_new();
545 gtk_widget_show (entrybox);
546
547 searchbutton = gtk_button_new_with_mnemonic (_("_Search"));
548 gtk_widget_set_usize (searchbutton,
549 defaults::program_button_width,
550 defaults::program_button_height);
551 gtk_widget_show (searchbutton);
552
553 hbox = gtk_hbox_new (false, 5);
554 gtk_box_pack_start (GTK_BOX (hbox), casesensitive, false, false, 0);
555 gtk_box_pack_start (GTK_BOX (hbox), entrybox, true, true, 0);
556 gtk_box_pack_start (GTK_BOX (hbox), searchbutton, false, false, 0);
557 gtk_box_pack_start (GTK_BOX (vbox), hbox, false, false, 0);
558 gtk_widget_show (hbox);
559
560 // set up the column list
561 my_gtk_list_setup (vbox, &sview, SEARCHLIST);
562
563 // set up the search button
564 search_data.casesensitive = casesensitive;
565 search_data.entrybox = entrybox;
566 search_data.sview = sview;
567 g_signal_connect (G_OBJECT (searchbutton), "clicked",
568 G_CALLBACK (search_callback),
569 &search_data);
570 g_signal_connect (G_OBJECT (entrybox), "activate",
571 G_CALLBACK (search_callback),
572 &search_data);
573
574 // the button to make the window go away
575 my_gtk_popup_button (&OK, vbox, searchwindow);
576 gtk_window_set_focus (GTK_WINDOW (searchwindow), OK);
577 gtk_widget_show_all (searchwindow);
578 return;
579 }
580
581 // ---------------------------------------------------------------------------
582 /* This function displays a dialog allowing to calculate the distance
583 * between two stars (or arbitrary coordinates): */
584
585 /* Callback function that actually calculates the distance: */
calculate_star_distance(GtkWidget * widget,gpointer star_data)586 static void calculate_star_distance(GtkWidget *widget, gpointer star_data)
587 {
588 GtkWidget ** coords = (GtkWidget **)star_data;
589
590 int mult[2] = { 1, -1 };
591 Vector3 result;
592
593 for (unsigned i = 0; i < 2; i++) {
594 Vector3 v = SolidAngle( starstrings::strs_to_ra(
595 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 0])),
596 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 1])),
597 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 2])),
598 globals::chart_rules.CelestialCoords),
599 starstrings::strs_to_dec(
600 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 3])),
601 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 4])),
602 gtk_entry_get_text (GTK_ENTRY (coords[8*i + 5]))
603 )
604 ).toCartesian(starmath::atof(
605 gtk_entry_get_text(GTK_ENTRY (coords[8*i + 6])))
606 / distance_conversion[globals::chart_rules.ChartUnits[1]]);
607 result += mult[i] * v;
608 }
609
610 string dist = starstrings::distance_to_str(result.magnitude(),
611 globals::chart_rules.ChartUnits);
612 gtk_entry_set_text (GTK_ENTRY (coords[2*8]), dist.c_str());
613 }
614
stardistance(void)615 void stardistance(void)
616 {
617 GtkWidget *window, *main_hbox, *main_vbox, *title;
618 GtkWidget *star_frame[2], *star_vbox[2];
619 GtkWidget *OK, *calculate, *results_hbox, *results_label;
620 static GtkWidget * star_coords[2*8 + 1];
621
622 // The window
623 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
624 gtk_window_set_resizable (GTK_WINDOW (window), false);
625 gtk_window_set_title (GTK_WINDOW (window), _("StarPlot: Calculate Distance"));
626 gtk_window_set_modal (GTK_WINDOW (window), true);
627 g_signal_connect (G_OBJECT (window), "destroy",
628 G_CALLBACK (gtk_widget_destroy), NULL);
629
630 // Pack it vertically
631 main_vbox = gtk_vbox_new (false, 5);
632 gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
633 gtk_container_add (GTK_CONTAINER (window), main_vbox);
634 gtk_widget_show (main_vbox);
635
636 // Add explanatory title
637 title = gtk_label_new (_(
638 "Define the two positions between which to calculate the distance.\n\
639 (The default for the first position is the center of the current chart.)"));
640 gtk_box_pack_start (GTK_BOX (main_vbox), title, false, false, 0);
641 gtk_misc_set_alignment (GTK_MISC (title), 0.5F, 0.0F);
642 gtk_widget_show (title);
643
644 // Set up star frames horizontally
645 main_hbox = gtk_hbox_new (true, 20);
646 gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 10);
647 gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, false, false, 0);
648 gtk_widget_show (main_hbox);
649
650 // Set up star frames
651 for (unsigned i = 0; i < 2; i++) {
652 string s = starstrings::ssprintf(_("Coordinates of position %d:"), i+1);
653 star_frame[i] = gtk_frame_new (s.c_str());
654 gtk_box_pack_start (GTK_BOX (main_hbox), star_frame[i], false, false, 0);
655 gtk_frame_set_label_align (GTK_FRAME (star_frame[i]), 0.5F, 0.0F);
656 gtk_frame_set_shadow_type (GTK_FRAME (star_frame[i]), GTK_SHADOW_NONE);
657 gtk_widget_show (star_frame[i]);
658
659 star_vbox[i] = gtk_vbox_new (false, 5);
660 gtk_container_add (GTK_CONTAINER (star_frame[i]), star_vbox[i]);
661 gtk_container_set_border_width (GTK_CONTAINER (star_vbox[i]), 5);
662 gtk_widget_show (star_vbox[i]);
663
664 my_gtk_star_coordinates(&star_coords[8*i], star_vbox[i]);
665 }
666
667 // Set the default for the second position to be the origin.
668 for (unsigned i = 0; i < 6; i++)
669 gtk_entry_set_text (GTK_ENTRY (star_coords[8 + i]), "00");
670 gtk_entry_set_text (GTK_ENTRY (star_coords[8+6]), "0");
671
672 gtk_entry_set_text (GTK_ENTRY (star_coords[0+7]),
673 (string("[") + _("Chart Center") + string("]")).c_str());
674 gtk_entry_set_text (GTK_ENTRY (star_coords[8+7]), "Sun");
675
676 // Add calculate button and results field
677 results_hbox = gtk_hbox_new (false, 20);
678 gtk_container_set_border_width (GTK_CONTAINER (results_hbox), 10);
679 gtk_box_pack_start (GTK_BOX (main_vbox), results_hbox, false, false, 0);
680 gtk_widget_show (results_hbox);
681
682 GtkWidget * spacer = gtk_label_new ("");
683 gtk_box_pack_start (GTK_BOX (results_hbox), spacer, true, false, 0);
684 gtk_widget_show (spacer);
685
686 calculate = gtk_button_new_with_mnemonic (_("_Calculate distance"));
687 gtk_box_pack_start (GTK_BOX (results_hbox), calculate, false, false, 10);
688 gtk_widget_show (calculate);
689
690 results_label = gtk_label_new (_("Distance between positions is:"));
691 gtk_box_pack_start (GTK_BOX (results_hbox), results_label, false, false, 0);
692 gtk_misc_set_alignment (GTK_MISC (results_label), 1.0F, 0.5F);
693 gtk_widget_show (results_label);
694
695 star_coords[2*8] = gtk_entry_new();
696 gtk_box_pack_start (GTK_BOX (results_hbox), star_coords[2*8], false,false, 0);
697 gtk_entry_set_editable (GTK_ENTRY (star_coords[2*8]), false);
698 gtk_widget_show (star_coords[2*8]);
699
700 spacer = gtk_label_new ("");
701 gtk_box_pack_start (GTK_BOX (results_hbox), spacer, true, false, 0);
702 gtk_widget_show (spacer);
703
704 g_signal_connect (G_OBJECT (calculate), "clicked",
705 G_CALLBACK (calculate_star_distance), star_coords);
706
707 my_gtk_popup_button(&OK, main_vbox, window);
708
709 // Finally, set the window policy and show it
710 gtk_window_set_focus (GTK_WINDOW (window), OK);
711 gtk_widget_show (window);
712
713 return;
714 }
715