/***********************************************************************
* gui.c: The user interface.
***********************************************************************/
/***********************************************************************
* This file is part of SpaceChart.
* Copyright (C) 2000 Miguel Coca <e970095@zipi.fi.upm.es>
*
* 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 <stdlib.h>
#include <math.h>
#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 );
}
syntax highlighted by Code2HTML, v. 0.9.1