/*********************************************************************** * gui.c: The user interface. ***********************************************************************/ /*********************************************************************** * This file is part of SpaceChart. * Copyright (C) 2000 Miguel Coca * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***********************************************************************/ #include #include #include "../include/starmap.h" #include "../include/star.h" #include "../include/link.h" #include "../include/config_dialog.h" #include "../include/settings.h" #include "../include/map.h" #include "../include/star_info_dialog.h" #include "../include/star_catalog.h" #include "../include/star_selection.h" #include "../include/star_selection_dialog.h" #include "../include/gui.h" #define MAX_RADIUS 100 /* How many parsecs the map moves when a movement button is pressed. */ #define DISPLACEMENT 1.0 /* How many degrees the map rotates when a rotation command is given */ #define ROTATION 2.0 typedef enum { MOVEMENT_UP, MOVEMENT_DOWN, MOVEMENT_LEFT, MOVEMENT_RIGHT, MOVEMENT_FRONT, MOVEMENT_REAR } movement_t; typedef enum { ROTATION_UP, ROTATION_DOWN, ROTATION_LEFT, ROTATION_RIGHT } rotation_t; struct st_gui { star_catalog_t *catalog; map_t *map; settings_t *settings; selection_dialog_t* star_selection_dialog; config_dialog_t* config_dialog; star_info_t* star_info_dialog; int changing_coords; /* Used to avoid infinite recursion between the settings and the coords adjustments */ gint sig_lat, sig_lon, sig_north; /* Signal handles */ int load; GtkObject *view_adjustment; GtkObject *max_link; GtkWidget *radio_unit_ly, *radio_unit_pc; GtkWidget *about_box, *open_dialog; GtkWidget *app, *appbar, *menubar; GtkAccelGroup *accel; GtkWidget *toggle_links_menu, *toggle_link_labels_menu, *toggle_star_labels_menu; GtkWidget *toggle_links_bar, *toggle_link_labels_bar, *toggle_star_labels_bar; GtkObject *lat_adj, *lon_adj, *north_adj; GtkWidget *about_data_menu; }; /* Toolbar Pixmaps */ #include "../pixmaps/selection.xpm" #include "../pixmaps/toggle_links.xpm" #include "../pixmaps/toggle_link_labels.xpm" #include "../pixmaps/toggle_star_labels.xpm" #include "../pixmaps/config.xpm" #include "../pixmaps/up.xpm" #include "../pixmaps/down.xpm" #include "../pixmaps/right.xpm" #include "../pixmaps/left.xpm" #include "../pixmaps/front.xpm" #include "../pixmaps/rear.xpm" /* Definition of local functions */ static void create_menus( gui_t *gui ); static void cb_about_clicked( GtkWidget *button, gui_t* gui ); static void cb_about_data_file_clicked( GtkWidget *button, gui_t* gui ); static void cb_open_clicked( GtkWidget *button, gui_t* gui ); static void cb_close_clicked( GtkWidget *button, gui_t* gui ); static void cb_reload_clicked( GtkWidget *button, gui_t* gui ); static void cb_open_ok_clicked( GtkWidget *button, gui_t* gui ); static void cb_open_cancel_clicked( GtkWidget *button, gui_t* gui ); static void cb_mov_clicked( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_links( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_link_labels( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_star_labels( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_links_menu( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_link_labels_menu( GtkWidget* widget, gui_t* gui ); static void cb_toggled_show_star_labels_menu( GtkWidget* widget, gui_t* gui ); static void cb_star_selection_clicked( GtkWidget* widget, gui_t* gui ); static void cb_settings_clicked( GtkWidget* widget, gui_t* gui ); static void cb_star_clicked( star_t *star, gui_t *gui ); static void cb_center_star( star_t *star, gui_t *gui ); static void cb_settings_changed_shown_objects( settings_t *settings, gui_t *gui ); static void cb_settings_changed_unit( settings_t *settings, gui_t *gui ); static void cb_settings_changed_view_radius( settings_t *settings, gui_t *gui ); static void cb_settings_changed_max_link( settings_t *settings, gui_t *gui ); static void cb_settings_changed_keybindings( settings_t *settings, gui_t *gui ); static void cb_changed_radius( GtkAdjustment *adj, gui_t* gui ); static void cb_changed_max_link( GtkAdjustment *adj, gui_t* gui ); static void cb_changed_selection( star_selection_t* selection, gui_t* gui ); static void cb_toggled_unit( GtkWidget *widget, gui_t *gui ); static int is_visible_star( star_t *star, gui_t *gui ); static int is_visible_link( link_t *link, gui_t *gui ); static void load_catalog( gui_t *gui, const char *file ); static int cb_load_progress( float progress, gui_t *gui ); static void cb_settings_changed_toggle_buttons( settings_t *settings, gui_t *gui ); static void cb_settings_changed_sight_params( settings_t *settings, gui_t *gui ); static void cb_settings_changed_catalog_filename( settings_t *settings, gui_t *gui ); static void cb_changed_user_coords( GtkAdjustment *adj, gui_t* gui ); static void cb_cancel_load_clicked( GnomeDialog *dialog, int button, gui_t* gui ); static void cb_rotate_clicked( GtkWidget* widget, gui_t* gui ); /* Public Functions */ gui_t* gui_new( settings_t *settings ) { GtkWidget *central_box, *view_radius, *radius_frame, *max_link_spin, *max_link_frame, *left_box, *unit_frame, *unit_box, *open, *close, *reload, *user_coords_frame, *user_coords_table, *lat_spin, *lon_spin, *north_spin, *label; GtkWidget *up, *down, *rear, *front, *left, *right; gui_t *gui = (gui_t*) malloc( sizeof(gui_t) ); /* Toolbar Structure */ GnomeUIInfo toolbar[] = { GNOMEUIINFO_ITEM_STOCK( NULL, _("Open"), NULL, GNOME_STOCK_PIXMAP_OPEN ), GNOMEUIINFO_ITEM_STOCK( NULL, _("Close"), NULL, GNOME_STOCK_PIXMAP_CLOSE ), GNOMEUIINFO_ITEM_STOCK( NULL, _("Reload settings"), NULL, GNOME_STOCK_PIXMAP_REVERT ), GNOMEUIINFO_SEPARATOR, /* Star selection */ GNOMEUIINFO_ITEM_DATA( NULL, _("Choose which stars are visible"), cb_star_selection_clicked, gui, selection_xpm ), /* Toggle links On/Off */ GNOMEUIINFO_TOGGLEITEM( NULL, _("Show/Hide the links between" " stars"), NULL, toggle_links_xpm ), /* Toggle link labels On/Off */ GNOMEUIINFO_TOGGLEITEM( NULL, _("Show/Hide link labels"), NULL, toggle_link_labels_xpm ), /* Toggle star labels On/Off */ GNOMEUIINFO_TOGGLEITEM( NULL, _("Show/Hide star labels"), NULL, toggle_star_labels_xpm ), /* Settings */ GNOMEUIINFO_ITEM_DATA( NULL, _("Settings"), cb_settings_clicked, gui, config_xpm ), GNOMEUIINFO_SEPARATOR, /* Movement Buttons */ GNOMEUIINFO_ITEM_DATA( NULL, _("Move map upwards"), cb_mov_clicked, gui, up_xpm ), GNOMEUIINFO_ITEM_DATA( NULL, _("Move map downwards"), cb_mov_clicked, gui, down_xpm ), GNOMEUIINFO_ITEM_DATA( NULL, _("Move map to the left"), cb_mov_clicked, gui, left_xpm ), GNOMEUIINFO_ITEM_DATA( NULL, _("Move map to the right"), cb_mov_clicked, gui, right_xpm ), GNOMEUIINFO_ITEM_DATA( NULL, _("Move map to the front"), cb_mov_clicked, gui, front_xpm ), GNOMEUIINFO_ITEM_DATA( NULL, _("Move map to the rear"), cb_mov_clicked, gui, rear_xpm ), GNOMEUIINFO_END }; gui->settings = settings; if( !(gui) || !(gui->settings || (gui->settings = settings_new())) || !(gui->catalog = star_catalog_new()) || !(gui->map = map_new(gui->settings)) || !(gui->star_info_dialog = star_info_new( (void(*)(star_t*,void*))cb_center_star,gui)) || !(gui->star_selection_dialog = selection_dialog_new(settings_get_star_filter(gui->settings), (void(*)(star_selection_t*,void*)) cb_changed_selection,gui))) { emit_error_message( _("Error: Not enough memory") ); return NULL; } gui->changing_coords = 0; /* GUI setup */ gui->menubar = NULL; gui->accel = NULL; gui->app = gnome_app_new( app_name, _("Spacechart: A 3D map of the stars") ); gtk_signal_connect( GTK_OBJECT( gui->app ), "delete_event", GTK_SIGNAL_FUNC( gtk_main_quit ), NULL ); gnome_app_create_toolbar( GNOME_APP(gui->app), toolbar ); gui->open_dialog = gtk_file_selection_new( _("Load Star Database") ); gtk_signal_connect( GTK_OBJECT(GTK_FILE_SELECTION(gui->open_dialog)-> ok_button), "clicked", cb_open_ok_clicked, gui ); gtk_signal_connect( GTK_OBJECT(GTK_FILE_SELECTION(gui->open_dialog)-> cancel_button), "clicked", cb_open_cancel_clicked, gui ); gtk_file_selection_set_filename( GTK_FILE_SELECTION(gui->open_dialog), DATADIR "/gliese.dat" ); gui->appbar = gnome_appbar_new( TRUE, TRUE, GNOME_PREFERENCES_USER ); map_set_star_clicked( gui->map,(void(*)(star_t*,void*)) cb_star_clicked, gui ); /* WARNING: If new button are inserted in the toolbar change this. */ open = toolbar[0].widget; close = toolbar[1].widget; reload = toolbar[2].widget; gui->toggle_links_bar = toolbar[5].widget; gui->toggle_link_labels_bar = toolbar[6].widget; gui->toggle_star_labels_bar = toolbar[7].widget; up = toolbar[10].widget; down = toolbar[11].widget; left = toolbar[12].widget; right = toolbar[13].widget; front = toolbar[14].widget; rear = toolbar[15].widget; /* Set the data in each movemement button, so that the callback knows * which one called it. */ gtk_object_set_data( GTK_OBJECT(up), "mov_type", GINT_TO_POINTER(MOVEMENT_UP) ); gtk_object_set_data( GTK_OBJECT(down), "mov_type", GINT_TO_POINTER(MOVEMENT_DOWN) ); gtk_object_set_data( GTK_OBJECT(left), "mov_type", GINT_TO_POINTER(MOVEMENT_LEFT) ); gtk_object_set_data( GTK_OBJECT(right), "mov_type", GINT_TO_POINTER(MOVEMENT_RIGHT) ); gtk_object_set_data( GTK_OBJECT(front), "mov_type", GINT_TO_POINTER(MOVEMENT_FRONT) ); gtk_object_set_data( GTK_OBJECT(rear), "mov_type", GINT_TO_POINTER(MOVEMENT_REAR) ); /* Set the link buttons. */ gtk_signal_connect( GTK_OBJECT( gui->toggle_links_bar ), "toggled", cb_toggled_show_links, gui ); gtk_signal_connect( GTK_OBJECT( gui->toggle_link_labels_bar ), "toggled", cb_toggled_show_link_labels, gui ); gtk_signal_connect( GTK_OBJECT( gui->toggle_star_labels_bar ), "toggled", cb_toggled_show_star_labels, gui ); /* Bind the open, close and reload buttons */ gtk_signal_connect(GTK_OBJECT(open), "clicked", cb_open_clicked, gui); gtk_signal_connect(GTK_OBJECT(close),"clicked", cb_close_clicked, gui); gtk_signal_connect(GTK_OBJECT(reload),"clicked", cb_reload_clicked, gui); /* Finished with the toolbar */ /* Now the GUI main box */ central_box = gtk_hbox_new( FALSE, 0 ); left_box = gtk_vbox_new( FALSE, 0 ); /* The view radius frame */ gui->view_adjustment = gtk_adjustment_new( 1.0, 1.0, MAX_RADIUS, 0.5, 2.0, 0.0 ); view_radius = gtk_vscale_new( GTK_ADJUSTMENT( gui->view_adjustment ) ); gtk_signal_connect(GTK_OBJECT(gui->view_adjustment), "value_changed", GTK_SIGNAL_FUNC(cb_changed_radius), gui); radius_frame = gtk_frame_new( _("View Radius") ); gtk_container_add( GTK_CONTAINER( radius_frame ), view_radius ); /* The Max Link frame */ gui->max_link = gtk_adjustment_new( 0.0, 0, 100, .1, 1, 0.0); max_link_spin = gtk_spin_button_new( GTK_ADJUSTMENT(gui->max_link), 0.01, 3); gtk_signal_connect(GTK_OBJECT(gui->max_link), "value_changed", GTK_SIGNAL_FUNC(cb_changed_max_link), gui); max_link_frame = gtk_frame_new( _("Max Link Shown") ); gtk_container_add( GTK_CONTAINER( max_link_frame ), max_link_spin ); /* The distance units frame */ unit_frame = gtk_frame_new( _("Units") ); gui->radio_unit_ly = gtk_radio_button_new_with_label(NULL,_("Light Years")); gui->radio_unit_pc = gtk_radio_button_new_with_label( gtk_radio_button_group( GTK_RADIO_BUTTON(gui->radio_unit_ly) ), _("Parsecs") ); unit_box = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(unit_box), gui->radio_unit_ly, FALSE, FALSE, 0); gtk_signal_connect( GTK_OBJECT(gui->radio_unit_ly), "toggled", cb_toggled_unit, gui ); gtk_object_set_data( GTK_OBJECT(gui->radio_unit_ly), "unit", GINT_TO_POINTER(DISTANCE_PARSECS) ); gtk_signal_connect( GTK_OBJECT(gui->radio_unit_pc), "toggled", cb_toggled_unit, gui ); gtk_object_set_data( GTK_OBJECT(gui->radio_unit_pc), "unit", GINT_TO_POINTER(DISTANCE_LIGHT_YEARS) ); gtk_box_pack_start( GTK_BOX(unit_box), gui->radio_unit_pc, FALSE, FALSE, 0); gtk_container_add( GTK_CONTAINER(unit_frame), unit_box ); /* The user coordinates frame */ gui->lon_adj = gtk_adjustment_new( 0, 0, 359, 1, 1, 0.0); lon_spin = gtk_spin_button_new( GTK_ADJUSTMENT(gui->lon_adj), 1, 0); gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(lon_spin), TRUE ); gui->lat_adj = gtk_adjustment_new( 0, -90, 90, 1, 1, 0.0); lat_spin = gtk_spin_button_new( GTK_ADJUSTMENT(gui->lat_adj), 1, 0); gui->north_adj = gtk_adjustment_new( 0, -0, 359, 1, 1, 0.0); north_spin = gtk_spin_button_new(GTK_ADJUSTMENT(gui->north_adj), 1, 0); gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(north_spin), TRUE ); user_coords_table = gtk_table_new( 2, 4, FALSE ); label = gtk_label_new( _("Lat:") ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), label, 0, 1, 0, 1 ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), lat_spin, 1, 2, 0, 1 ); label = gtk_label_new( _("Lon:") ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), label, 0, 1, 1, 2 ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), lon_spin, 1, 2, 1, 2 ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), gtk_hseparator_new(), 0, 2, 2, 3 ); label = gtk_label_new( _("North:") ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), label, 0, 1, 3, 4 ); gtk_table_attach_defaults( GTK_TABLE(user_coords_table), north_spin, 1, 2, 3, 4 ); gui->sig_lon = gtk_signal_connect(GTK_OBJECT(gui->lon_adj), "value_changed", GTK_SIGNAL_FUNC(cb_changed_user_coords), gui); gui->sig_lat =gtk_signal_connect(GTK_OBJECT(gui->lat_adj), "value_changed", GTK_SIGNAL_FUNC(cb_changed_user_coords), gui); gui->sig_north = gtk_signal_connect(GTK_OBJECT(gui->north_adj), "value_changed", GTK_SIGNAL_FUNC(cb_changed_user_coords), gui); user_coords_frame = gtk_frame_new( _("User Coords.") ); gtk_container_add(GTK_CONTAINER(user_coords_frame), user_coords_table); /* Pack everything together */ gnome_app_set_contents( GNOME_APP(gui->app), central_box ); gnome_app_set_statusbar( GNOME_APP(gui->app), gui->appbar ); gtk_box_pack_start( GTK_BOX(left_box), unit_frame, FALSE, FALSE, 5 ); gtk_box_pack_start( GTK_BOX(left_box), max_link_frame, FALSE, FALSE, 5 ); gtk_box_pack_start( GTK_BOX(left_box), radius_frame, TRUE, TRUE, 5 ); gtk_box_pack_start( GTK_BOX(left_box), user_coords_frame, FALSE, FALSE, 5 ); gtk_box_pack_start( GTK_BOX(central_box), left_box, FALSE, FALSE, 5 ); gtk_box_pack_start( GTK_BOX( central_box ), map_get_widget( gui->map ), TRUE, TRUE, 0 ); gtk_widget_show_all( GTK_WIDGET(gui->app) ); /* Set the callbacks from the settings. */ settings_add_callback( gui->settings, PROPERTIES_KEYBINDINGS, (void(*)(settings_t*, void*)) cb_settings_changed_keybindings, gui ); settings_add_callback( gui->settings, PROPERTIES_STAR_FILTER | PROPERTIES_LINK_FILTER | PROPERTIES_VIEW_RADIUS | PROPERTIES_CENTER, (void(*)(settings_t*, void*)) cb_settings_changed_shown_objects, gui ); settings_add_callback( gui->settings, PROPERTIES_SHOW_LINKS | PROPERTIES_SHOW_LINK_LABELS | PROPERTIES_SHOW_STAR_LABELS, (void(*)(settings_t*, void*)) cb_settings_changed_toggle_buttons, gui ); settings_add_callback( gui->settings, PROPERTIES_DISTANCE_UNIT, (void(*)(settings_t*, void*)) cb_settings_changed_unit, gui ); settings_add_callback( gui->settings, PROPERTIES_VIEW_RADIUS, (void(*)(settings_t*, void*)) cb_settings_changed_view_radius, gui ); settings_add_callback( gui->settings, PROPERTIES_LINK_FILTER, (void(*)(settings_t*, void*)) cb_settings_changed_max_link, gui ); settings_add_callback( gui->settings, PROPERTIES_SIGHT_PARAMS, (void(*)(settings_t*, void*)) cb_settings_changed_sight_params, gui ); settings_add_callback( gui->settings, PROPERTIES_CATALOG_FILENAME, (void(*)(settings_t*, void*)) cb_settings_changed_catalog_filename, gui ); return gui; } settings_t* gui_get_settings( gui_t *gui ) { return gui->settings; } star_catalog_t* gui_get_catalog( gui_t *gui ) { return gui->catalog; } void gui_destroy( gui_t *gui ) { map_destroy( gui->map ); selection_dialog_destroy( gui->star_selection_dialog ); star_info_destroy( gui->star_info_dialog ); } /* Local Functions. */ void create_menus( gui_t *gui ) { key_press_t keybindings[KEY_END_OF_LIST]; GtkWidget *rotate, *movement; /* Menubar Structure. */ GnomeUIInfo file_menu[] = { GNOMEUIINFO_MENU_OPEN_ITEM(cb_open_clicked, gui), GNOMEUIINFO_MENU_CLOSE_ITEM(cb_close_clicked, gui), GNOMEUIINFO_ITEM_DATA( _("Reload settings"), _("Reload settings"), cb_reload_clicked, gui, NULL), GNOMEUIINFO_MENU_EXIT_ITEM(gtk_main_quit, NULL), GNOMEUIINFO_END }; GnomeUIInfo view_menu[] = { /* Star selection */ GNOMEUIINFO_ITEM_DATA( _("Star Selection"), _("Choose which stars are visible"), cb_star_selection_clicked, gui, NULL ), /* Toggle links On/Off */ GNOMEUIINFO_TOGGLEITEM( _("Show/Hide the links between stars"), _("Show/Hide the links between stars"), NULL, NULL ), /* Toggle link labels On/Off */ GNOMEUIINFO_TOGGLEITEM( _("Show/Hide link labels"), _("Show/Hide link labels"), NULL, NULL ), /* Toggle star labels On/Off */ GNOMEUIINFO_TOGGLEITEM( _("Show/Hide star labels"), _("Show/Hide star labels"), NULL, NULL ), GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_ITEM_DATA( _("Rotate Up"), _("Rotate the map up"), cb_rotate_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Rotate Down"), _("Rotate the map down"), cb_rotate_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Rotate Left"), _("Rotate the map to the left"), cb_rotate_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Rotate Right"), _("Rotate the map to the right"), cb_rotate_clicked, gui, NULL ), GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_ITEM_DATA( _("Move map upwards"), _("Move map upwards"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Move map downwards"), _("Move map downwards"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Move map to the left"), _("Move map to the left"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Move map to the right"), _("Move map to the right"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Move map to the front"), _("Move map to the front"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_ITEM_DATA( _("Move map to the rear"), _("Move map to the rear"), cb_mov_clicked, gui, NULL ), GNOMEUIINFO_SEPARATOR, /* Settings */ GNOMEUIINFO_ITEM_DATA( _("Settings"), _("Settings"), cb_settings_clicked, gui, NULL ), GNOMEUIINFO_END }; GnomeUIInfo help_menu[] = { GNOMEUIINFO_MENU_ABOUT_ITEM(cb_about_clicked, gui), /* About the data file */ GNOMEUIINFO_ITEM_DATA( _("About data file..."), NULL, cb_about_data_file_clicked, gui, NULL ), GNOMEUIINFO_END }; GnomeUIInfo menubar[] = { GNOMEUIINFO_MENU_FILE_TREE(file_menu), GNOMEUIINFO_MENU_VIEW_TREE(view_menu), GNOMEUIINFO_MENU_HELP_TREE(help_menu), GNOMEUIINFO_END }; /* Set keybindings */ settings_get_keybindings( gui->settings, keybindings ); /* File Menu */ file_menu[2].accelerator_key = keybindings[KEY_RELOAD_SETTINGS].key; file_menu[2].ac_mods = keybindings[KEY_RELOAD_SETTINGS].mods; /* Star Selection */ view_menu[0].accelerator_key = keybindings[KEY_STAR_SEL].key; view_menu[0].ac_mods = keybindings[KEY_STAR_SEL].mods; /* Show Links */ view_menu[1].accelerator_key = keybindings[KEY_TOGGLE_LINKS].key; view_menu[1].ac_mods = keybindings[KEY_TOGGLE_LINKS].mods; /* Show Link Labels */ view_menu[2].accelerator_key = keybindings[KEY_TOGGLE_LINK_LABELS].key; view_menu[2].ac_mods = keybindings[KEY_TOGGLE_LINK_LABELS].mods; /* Show Star Labels */ view_menu[3].accelerator_key = keybindings[KEY_TOGGLE_STAR_LABELS].key; view_menu[3].ac_mods = keybindings[KEY_TOGGLE_STAR_LABELS].mods; /* Rotation */ view_menu[5].accelerator_key = keybindings[KEY_ROT_UP].key; view_menu[5].ac_mods = keybindings[KEY_ROT_UP].mods; view_menu[6].accelerator_key = keybindings[KEY_ROT_DOWN].key; view_menu[6].ac_mods = keybindings[KEY_ROT_DOWN].mods; view_menu[7].accelerator_key = keybindings[KEY_ROT_LEFT].key; view_menu[7].ac_mods = keybindings[KEY_ROT_LEFT].mods; view_menu[8].accelerator_key = keybindings[KEY_ROT_RIGHT].key; view_menu[8].ac_mods = keybindings[KEY_ROT_RIGHT].mods; /* Movement */ view_menu[10].accelerator_key = keybindings[KEY_MOVE_UP].key; view_menu[10].ac_mods = keybindings[KEY_MOVE_UP].mods; view_menu[11].accelerator_key = keybindings[KEY_MOVE_DOWN].key; view_menu[11].ac_mods = keybindings[KEY_MOVE_DOWN].mods; view_menu[12].accelerator_key = keybindings[KEY_MOVE_LEFT].key; view_menu[12].ac_mods = keybindings[KEY_MOVE_LEFT].mods; view_menu[13].accelerator_key = keybindings[KEY_MOVE_RIGHT].key; view_menu[13].ac_mods = keybindings[KEY_MOVE_RIGHT].mods; view_menu[14].accelerator_key = keybindings[KEY_MOVE_FRONT].key; view_menu[14].ac_mods = keybindings[KEY_MOVE_FRONT].mods; view_menu[15].accelerator_key = keybindings[KEY_MOVE_REAR].key; view_menu[15].ac_mods = keybindings[KEY_MOVE_REAR].mods; /* Settings */ view_menu[17].accelerator_key = keybindings[KEY_SETTINGS].key; view_menu[17].ac_mods = keybindings[KEY_SETTINGS].mods; gui->menubar = gtk_menu_bar_new(); gui->accel = gtk_accel_group_new(); gnome_app_fill_menu( GTK_MENU_SHELL(gui->menubar), menubar, gui->accel, TRUE, 0 ); gnome_app_set_menus( GNOME_APP(gui->app), GTK_MENU_BAR(gui->menubar) ); gtk_window_add_accel_group( GTK_WINDOW(gui->app), gui->accel ); /* Set up the menu */ gui->toggle_links_menu = view_menu[1].widget; gui->toggle_link_labels_menu = view_menu[2].widget; gui->toggle_star_labels_menu = view_menu[3].widget; gtk_signal_connect( GTK_OBJECT( gui->toggle_links_menu ), "toggled", cb_toggled_show_links_menu, gui ); gtk_signal_connect( GTK_OBJECT( gui->toggle_link_labels_menu ), "toggled", cb_toggled_show_link_labels_menu, gui ); gtk_signal_connect( GTK_OBJECT( gui->toggle_star_labels_menu ), "toggled", cb_toggled_show_star_labels_menu, gui ); rotate = view_menu[5].widget; gtk_object_set_data( GTK_OBJECT(rotate), "rot_type", GINT_TO_POINTER(ROTATION_UP) ); rotate = view_menu[6].widget; gtk_object_set_data( GTK_OBJECT(rotate), "rot_type", GINT_TO_POINTER(ROTATION_DOWN) ); rotate = view_menu[7].widget; gtk_object_set_data( GTK_OBJECT(rotate), "rot_type", GINT_TO_POINTER(ROTATION_LEFT) ); rotate = view_menu[8].widget; gtk_object_set_data( GTK_OBJECT(rotate), "rot_type", GINT_TO_POINTER(ROTATION_RIGHT) ); movement = view_menu[10].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_UP) ); movement = view_menu[11].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_DOWN) ); movement = view_menu[12].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_LEFT) ); movement = view_menu[13].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_RIGHT) ); movement = view_menu[14].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_FRONT) ); movement = view_menu[15].widget; gtk_object_set_data( GTK_OBJECT(movement), "mov_type", GINT_TO_POINTER(MOVEMENT_REAR) ); /* Disable the "About Data File" button (no data file yet) */ gui->about_data_menu = help_menu[1].widget; gtk_widget_set_sensitive( gui->about_data_menu, FALSE ); /* Finished with the menu */ } void cb_about_clicked( GtkWidget *button, gui_t* gui ) { gui->about_box = gnome_about_new( app_name, app_version, "Copyright \251 2000 Miguel Coca", app_authors, _("A map of the stars in 3D.\n" "For documentation check " DOCSDIR "."), NULL ); gnome_dialog_set_parent( GNOME_DIALOG(gui->about_box), GTK_WINDOW(gui->app) ); gtk_widget_show(gui->about_box); } void cb_about_data_file_clicked( GtkWidget *button, gui_t* gui ) { GtkWidget *dialog; GtkWidget *label; GtkWidget *frame; dialog = gnome_dialog_new( _("About data file"), GNOME_STOCK_BUTTON_OK, NULL ); gnome_dialog_set_parent( GNOME_DIALOG(dialog), GTK_WINDOW(gui->app) ); label = gtk_label_new( star_catalog_info( gui->catalog ) ); frame = gtk_frame_new(NULL); gtk_container_add( GTK_CONTAINER(frame), label ); gtk_box_pack_start( GTK_BOX(GNOME_DIALOG(dialog)->vbox),frame, FALSE,FALSE,0 ); gtk_signal_connect( GTK_OBJECT(dialog), "clicked", gnome_dialog_close, NULL ); gtk_widget_show_all(dialog); } void cb_open_clicked( GtkWidget *button, gui_t* gui ) { gtk_widget_show_all( gui->open_dialog ); } void cb_close_clicked( GtkWidget *button, gui_t* gui ) { map_set_shown_objects( gui->map, NULL, NULL ); star_catalog_destroy( gui->catalog ); gui->catalog = star_catalog_new(); gtk_widget_set_sensitive( gui->about_data_menu, FALSE ); settings_set_catalog_filename( gui->settings, NULL ); } void cb_reload_clicked( GtkWidget *button, gui_t* gui ) { settings_load_from_files( gui->settings ); } void cb_open_ok_clicked( GtkWidget *button, gui_t* gui ) { gtk_widget_hide( gui->open_dialog ); settings_set_catalog_filename( gui->settings, gtk_file_selection_get_filename( GTK_FILE_SELECTION( gui->open_dialog))); } void cb_open_cancel_clicked( GtkWidget *button, gui_t* gui ) { gtk_widget_hide( gui->open_dialog ); } void cb_mov_clicked( GtkWidget* widget, gui_t* gui ) { coords_3d_t movement, center, los, up; double displace; settings_get_center( gui->settings, ¢er ); settings_get_sight_params( gui->settings, &los, &up ); /* Check which button is this and calculate the movement needed */ switch( GPOINTER_TO_INT(gtk_object_get_data( GTK_OBJECT(widget), "mov_type")) ) { char error[80]; case MOVEMENT_UP: movement = up; break; case MOVEMENT_DOWN: movement.x = -up.x; movement.y = -up.y; movement.z = -up.z; break; case MOVEMENT_RIGHT: /* movement = los x up */ movement.x = (up.y * los.z) - (up.z * los.y ); movement.y = - (up.x * los.z) + (up.z * los.x ); movement.z = (up.x * los.y) - (up.y * los.x ); break; case MOVEMENT_LEFT: /* movement = up x los */ movement.x = (los.y * up.z) - (los.z * up.y ); movement.y = - (los.x * up.z) + (los.z * up.x ); movement.z = (los.x * up.y) - (los.y * up.x ); break; case MOVEMENT_FRONT: movement = los; break; case MOVEMENT_REAR: movement.x = -los.x; movement.y = -los.y; movement.z = -los.z; break; default: /* Can't happen. */ sprintf( error, _("Error in file %s, line %d: Can't happen"), __FILE__, __LINE__ ); emit_error_message( error ); return; } /* We move only one parsec */ displace = DISPLACEMENT / magnitude( &movement ); movement.x *= displace; movement.y *= displace; movement.z *= displace; center.x += movement.x; center.y += movement.y; center.z += movement.z; settings_set_center( gui->settings, ¢er ); } void cb_toggled_show_links( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_links(gui->settings) != GTK_TOGGLE_BUTTON(widget)->active) ) settings_set_show_links( gui->settings, GTK_TOGGLE_BUTTON(widget)->active ); } void cb_toggled_show_link_labels( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_link_labels(gui->settings) != GTK_TOGGLE_BUTTON(widget)->active) ) settings_set_show_link_labels( gui->settings, GTK_TOGGLE_BUTTON(widget)->active ); } void cb_toggled_show_star_labels( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_star_labels(gui->settings) != GTK_TOGGLE_BUTTON(widget)->active) ) settings_set_show_star_labels(gui->settings, GTK_TOGGLE_BUTTON( widget )->active ); } void cb_toggled_show_links_menu( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_links(gui->settings) != GTK_CHECK_MENU_ITEM(widget)->active) ) settings_set_show_links( gui->settings, GTK_CHECK_MENU_ITEM(widget)->active ); } void cb_toggled_show_link_labels_menu( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_link_labels(gui->settings) != GTK_CHECK_MENU_ITEM(widget)->active) ) settings_set_show_link_labels( gui->settings, GTK_CHECK_MENU_ITEM(widget)->active ); } void cb_toggled_show_star_labels_menu( GtkWidget* widget, gui_t* gui ) { if( (settings_get_show_star_labels(gui->settings) != GTK_CHECK_MENU_ITEM(widget)->active) ) settings_set_show_star_labels( gui->settings, GTK_CHECK_MENU_ITEM(widget)->active ); } void cb_star_selection_clicked( GtkWidget* widget, gui_t* gui ) { selection_dialog_show( gui->star_selection_dialog ); } void cb_settings_clicked( GtkWidget* widget, gui_t* gui ) { gui->config_dialog = config_dialog_new(gui->settings); } void cb_star_clicked( star_t *star, gui_t *gui ) { star_info_set_star( gui->star_info_dialog, star ); gtk_window_set_transient_for( GTK_WINDOW(star_info_get_dialog(gui->star_info_dialog)), GTK_WINDOW(gui->app) ); } void cb_center_star( star_t *star, gui_t *gui ) { coords_3d_t center; star_get_coords( star, ¢er ); settings_set_center( gui->settings, ¢er ); } void cb_settings_changed_shown_objects( settings_t *settings, gui_t *gui ) { star_t **star_list; link_t **link_list; star_catalog_select_objs( gui->catalog, &star_list, &link_list, (int(*)(star_t*,void*)) is_visible_star, (int(*)(link_t*,void*)) is_visible_link, gui ); map_set_shown_objects( gui->map, star_list, link_list ); } int is_visible_star( star_t *star, gui_t *gui ) { int matches; coords_3d_t center, star_coords; settings_get_center( gui->settings, ¢er ); star_get_coords( star, &star_coords); matches = star_selection_match( settings_get_star_filter(gui->settings), star) && (distance_3d( ¢er, &star_coords ) <= settings_get_view_radius(gui->settings)); return matches; } int is_visible_link( link_t *link, gui_t *gui ) { return link_selection_match(settings_get_link_filter(gui->settings), link ); } void cb_settings_changed_unit( settings_t *settings, gui_t *gui ) { double d; star_info_set_distance_units( gui->star_info_dialog, settings_get_distance_unit( settings ) ); d = settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ? settings_get_view_radius(gui->settings) : settings_get_view_radius(gui->settings) * PARSEC_TO_LY; gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->view_adjustment), d ); d = settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ? link_selection_get_max_length( settings_get_link_filter(gui->settings)) : link_selection_get_max_length( settings_get_link_filter(gui->settings))*PARSEC_TO_LY; gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->max_link), d ); if( settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (gui->radio_unit_pc), TRUE ); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (gui->radio_unit_ly), TRUE ); } void cb_settings_changed_view_radius( settings_t *settings, gui_t *gui ) { double radius; if( settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ) radius = settings_get_view_radius(gui->settings); else radius = settings_get_view_radius(gui->settings) * PARSEC_TO_LY; gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->view_adjustment), radius ); } void cb_settings_changed_max_link( settings_t *settings, gui_t *gui ) { double d; d = settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ? link_selection_get_max_length( settings_get_link_filter(gui->settings)) : link_selection_get_max_length( settings_get_link_filter(gui->settings))*PARSEC_TO_LY; gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->max_link), d ); } void cb_settings_changed_keybindings( settings_t *settings, gui_t *gui ) { create_menus( gui ); } void cb_changed_radius( GtkAdjustment *adj, gui_t* gui ) { double radius; if( settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ) radius = adj->value; else radius = adj->value / PARSEC_TO_LY; settings_set_view_radius(gui->settings, radius); } void cb_changed_max_link( GtkAdjustment *adj, gui_t* gui ) { link_selection_t *selection; double max; if( settings_get_distance_unit(gui->settings) == DISTANCE_PARSECS ) max = adj->value; else max = adj->value / PARSEC_TO_LY; selection = settings_get_link_filter(gui->settings); link_selection_act_max_length(selection, max ); settings_set_link_filter(gui->settings, selection); } void cb_changed_selection( star_selection_t* selection, gui_t* gui ) { settings_set_star_filter( gui->settings, selection ); } void cb_toggled_unit( GtkWidget *widget, gui_t *gui ) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui->radio_unit_pc)) && (GPOINTER_TO_INT(gtk_object_get_data( GTK_OBJECT(widget), "unit")) == DISTANCE_PARSECS ) ) settings_set_distance_unit( gui->settings, DISTANCE_PARSECS ); else if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(gui->radio_unit_ly)) && (GPOINTER_TO_INT( gtk_object_get_data(GTK_OBJECT(widget), "unit")) == DISTANCE_LIGHT_YEARS )) settings_set_distance_unit(gui->settings,DISTANCE_LIGHT_YEARS); } void load_catalog( gui_t *gui, const char *file ) { int ret_code; char mesg[200]; GtkWidget *dialog; sprintf( mesg, _("Loading file %s"), file ); star_catalog_destroy( gui->catalog ); gui->catalog = star_catalog_new(); dialog = gnome_message_box_new( mesg, GNOME_MESSAGE_BOX_INFO, GNOME_STOCK_BUTTON_CANCEL, NULL ); gnome_dialog_set_parent( GNOME_DIALOG(dialog), GTK_WINDOW(gui->app) ); gtk_signal_connect( GTK_OBJECT(dialog), "clicked", cb_cancel_load_clicked, gui ); gtk_widget_show( dialog ); gnome_app_flash( GNOME_APP(gui->app), mesg ); gtk_widget_set_sensitive(gui->app, FALSE); gui->load = TRUE; ret_code = star_catalog_read(gui->catalog,file,(int(*)(float,void*)) cb_load_progress,gui); switch(ret_code) { char error[200]; case 1: sprintf( error, _("File %s not found"), file); emit_error_message( error ); break; case 2: sprintf( error, _("File %s is not a valid catalogue file"), file ); emit_error_message( error ); break; case 3: emit_error_message( _("Error: Not enough memory") ); break; case 4: star_catalog_destroy( gui->catalog ); gui->catalog = star_catalog_new(); dialog = NULL; break; } gtk_widget_set_sensitive(gui->app, TRUE); if(dialog) gtk_widget_destroy( dialog ); gtk_progress_set_percentage( gnome_appbar_get_progress(GNOME_APPBAR(gui->appbar)), 0); } int cb_load_progress( float progress, gui_t *gui ) { gtk_progress_set_percentage( gnome_appbar_get_progress(GNOME_APPBAR(gui->appbar)),progress); while (gtk_main_iteration_do(FALSE)); return gui->load; } void cb_settings_changed_toggle_buttons( settings_t *settings, gui_t *gui ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(gui->toggle_links_bar), settings_get_show_links(gui->settings) ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(gui->toggle_link_labels_bar), settings_get_show_link_labels(gui->settings) ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(gui->toggle_star_labels_bar), settings_get_show_star_labels(gui->settings) ); gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM(gui->toggle_links_menu), settings_get_show_links(gui->settings) ); gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM(gui->toggle_link_labels_menu), settings_get_show_link_labels(gui->settings) ); gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM(gui->toggle_star_labels_menu), settings_get_show_star_labels(gui->settings) ); } void cb_settings_changed_sight_params( settings_t *settings, gui_t *gui ) { double lon, lat, north; if( gui->changing_coords ) return; settings_get_sight_params_polar( settings, &lon, &lat, &north ); lon *= 180/M_PI; lat *= 180/M_PI; north *= 180/M_PI; gtk_signal_handler_block( GTK_OBJECT(gui->lon_adj), gui->sig_lon ); gtk_signal_handler_block( GTK_OBJECT(gui->lat_adj), gui->sig_lat ); gtk_signal_handler_block( GTK_OBJECT(gui->north_adj), gui->sig_north ); gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->lon_adj), lon ); gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->lat_adj), lat ); gtk_adjustment_set_value( GTK_ADJUSTMENT(gui->north_adj), north ); gtk_signal_handler_unblock( GTK_OBJECT(gui->lon_adj), gui->sig_lon ); gtk_signal_handler_unblock( GTK_OBJECT(gui->lat_adj), gui->sig_lat ); gtk_signal_handler_unblock( GTK_OBJECT(gui->north_adj), gui->sig_north ); } void cb_settings_changed_catalog_filename( settings_t *settings, gui_t *gui ) { star_t **star_list; link_t **link_list; map_set_shown_objects( gui->map, NULL, NULL ); star_info_hide(gui->star_info_dialog); load_catalog( gui, settings_get_catalog_filename(settings) ); star_catalog_select_objs( gui->catalog, &star_list, &link_list, (int(*)(star_t*,void*)) is_visible_star, (int(*)(link_t*,void*)) is_visible_link, gui ); map_set_shown_objects( gui->map, star_list, link_list ); gtk_widget_set_sensitive( gui->about_data_menu, TRUE ); } void cb_changed_user_coords( GtkAdjustment *adj, gui_t* gui ) { double lon, lat, north; gui->changing_coords = 1; lon = GTK_ADJUSTMENT(gui->lon_adj)->value * (M_PI/180); lat = GTK_ADJUSTMENT(gui->lat_adj)->value * (M_PI/180); north = GTK_ADJUSTMENT(gui->north_adj)->value * (M_PI/180); settings_set_sight_params_polar( gui->settings, lon, lat, north ); gui->changing_coords = 0; } void cb_cancel_load_clicked( GnomeDialog *dialog, int button, gui_t* gui ) { gui->load = FALSE; } void cb_rotate_clicked( GtkWidget* widget, gui_t* gui ) { double v_ang, h_ang; switch( GPOINTER_TO_INT(gtk_object_get_data( GTK_OBJECT(widget), "rot_type")) ) { char error[80]; case ROTATION_UP: v_ang = ROTATION*((2*M_PI)/360); h_ang = 0; break; case ROTATION_DOWN: v_ang = (-1)*ROTATION*((2*M_PI)/360); h_ang = 0; break; case ROTATION_RIGHT: v_ang = 0; h_ang = ROTATION*((2*M_PI)/360); break; case ROTATION_LEFT: v_ang = 0; h_ang = (-1)*ROTATION*((2*M_PI)/360); break; default: /* Can't happen. */ sprintf( error, _("Error in file %s, line %d: Can't happen"), __FILE__, __LINE__ ); emit_error_message( error ); return; } map_rotate( gui->map, v_ang, h_ang ); }