/***********************************************************************
 * 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, &center );
        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, &center );
}

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, &center );
        settings_set_center( gui->settings, &center );
}

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, &center );
        star_get_coords( star, &star_coords);
        matches = star_selection_match(
                settings_get_star_filter(gui->settings), star) && 
                (distance_3d( &center, &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