X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/1d1bc3c1f9e862a76235bb69a4e419136b0f54a3..e044ae9e96b95fc6e58b4f05f759e5fc59bb79ab:/src/vikwindow.c?ds=sidebyside diff --git a/src/vikwindow.c b/src/vikwindow.c index a9fe0dfd..37eb13da 100644 --- a/src/vikwindow.c +++ b/src/vikwindow.c @@ -21,8 +21,9 @@ #include "viking.h" #include "background.h" #include "acquire.h" +#include "datasources.h" -#define VIKING_TITLE " - Viking " VIKING_VERSION " " VIKING_VERSION_NAME " " VIKING_URL +#define VIKING_TITLE " - Viking" #include #include @@ -39,6 +40,8 @@ #define make_dir(dir) mkdir(dir,0777) #endif +#define VIKING_WINDOW_WIDTH 1000 +#define VIKING_WINDOW_HEIGHT 800 #define DRAW_IMAGE_DEFAULT_WIDTH 1280 #define DRAW_IMAGE_DEFAULT_HEIGHT 1024 #define DRAW_IMAGE_DEFAULT_SAVE_AS_PNG TRUE @@ -59,7 +62,7 @@ static gboolean delete_event( VikWindow *vw ); static void draw_sync ( VikWindow *vw ); static void draw_redraw ( VikWindow *vw ); -static void draw_scroll ( VikWindow *vw, GdkEvent *event ); +static void draw_scroll ( VikWindow *vw, GdkEventScroll *event ); static void draw_click ( VikWindow *vw, GdkEventButton *event ); static void draw_release ( VikWindow *vw, GdkEventButton *event ); static void draw_mouse_motion ( VikWindow *vw, GdkEventMotion *event ); @@ -73,16 +76,40 @@ static void draw_status (); static void menu_addlayer_cb ( GtkAction *a, VikWindow *vw ); static void menu_properties_cb ( GtkAction *a, VikWindow *vw ); static void menu_delete_layer_cb ( GtkAction *a, VikWindow *vw ); + +/* tool management */ +typedef struct { + VikToolInterface ti; + gpointer state; +} toolbox_tool_t; + +typedef struct { + int active_tool; + int n_tools; + toolbox_tool_t *tools; + VikWindow *vw; +} toolbox_tools_t; + static void menu_tool_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ); +static toolbox_tools_t* toolbox_create(VikWindow *vw); +static void toolbox_add_tool(toolbox_tools_t *vt, VikToolInterface *vti); +static int toolbox_get_tool(toolbox_tools_t *vt, const gchar *tool_name); +static void toolbox_activate(toolbox_tools_t *vt, const gchar *tool_name); +static void toolbox_click (toolbox_tools_t *vt, GdkEventButton *event); +static void toolbox_move (toolbox_tools_t *vt, GdkEventButton *event); +static void toolbox_release (toolbox_tools_t *vt, GdkEventButton *event); + +/* ui creation */ static void window_create_ui( VikWindow *window ); +static void register_vik_icons (GtkIconFactory *icon_factory); +/* i/o */ static void load_file ( GtkAction *a, VikWindow *vw ); static gboolean save_file_as ( GtkAction *a, VikWindow *vw ); static gboolean save_file ( GtkAction *a, VikWindow *vw ); +static gboolean save_file_and_exit ( GtkAction *a, VikWindow *vw ); static gboolean window_save ( VikWindow *vw ); -static void register_vik_icons (GtkIconFactory *icon_factory); - struct _VikWindow { GtkWindow gtkwindow; @@ -94,16 +121,14 @@ struct _VikWindow { GtkItemFactory *item_factory; - /* ruler variables */ - VikCoord oldcoord; - gboolean has_oldcoord; - - + /* tool management state */ guint current_tool; - + toolbox_tools_t *vt; guint16 tool_layer_id; guint16 tool_tool_id; + GtkActionGroup *action_group; + gint pan_x, pan_y; guint draw_image_width, draw_image_height; @@ -159,6 +184,26 @@ GType vik_window_get_type (void) return vw_type; } +void vik_window_selected_layer(VikWindow *vw, VikLayer *vl) +{ + int i, j, tool_count; + VikLayerInterface *layer_interface; + + if (!vw->action_group) return; + + for (i=0; itools_count; + + for (j = 0; j < tool_count; j++) { + action = gtk_action_group_get_action(vw->action_group, + layer_interface->tools[j].name); + g_object_set(action, "sensitive", i == vl->type, NULL); + } + } +} + static void window_finalize ( GObject *gob ) { VikWindow *vw = VIK_WINDOW(gob); @@ -190,20 +235,25 @@ static void window_init ( VikWindow *vw ) GtkWidget *main_vbox; GtkWidget *hpaned; - window_create_ui(vw); - gtk_window_set_title ( GTK_WINDOW(vw), "Untitled" VIKING_TITLE ); + vw->action_group = NULL; vw->viking_vvp = vik_viewport_new(); vw->viking_vlp = vik_layers_panel_new(); vik_layers_panel_set_viewport ( vw->viking_vlp, vw->viking_vvp ); vw->viking_vs = vik_statusbar_new(); + vw->vt = toolbox_create(vw); + window_create_ui(vw); + gtk_window_set_title ( GTK_WINDOW(vw), "Untitled" VIKING_TITLE ); + + toolbox_activate(vw->vt, "Zoom"); + vw->filename = NULL; vw->item_factory = NULL; - vw->has_oldcoord = FALSE; vw->modified = FALSE; vw->only_updating_coord_mode_ui = FALSE; + vw->pan_x = vw->pan_y = -1; vw->draw_image_width = DRAW_IMAGE_DEFAULT_WIDTH; @@ -229,7 +279,7 @@ static void window_init ( VikWindow *vw ) g_signal_connect_swapped (G_OBJECT(vw->viking_vvp), "motion_notify_event", G_CALLBACK(draw_mouse_motion), vw); g_signal_connect_swapped (G_OBJECT(vw->viking_vlp), "update", G_CALLBACK(draw_update), vw); - gtk_window_set_default_size ( GTK_WINDOW(vw), 1000, 800); + gtk_window_set_default_size ( GTK_WINDOW(vw), VIKING_WINDOW_WIDTH, VIKING_WINDOW_HEIGHT); hpaned = gtk_hpaned_new (); gtk_paned_add1 ( GTK_PANED(hpaned), GTK_WIDGET (vw->viking_vlp) ); @@ -253,7 +303,11 @@ VikWindow *vik_window_new () static gboolean delete_event( VikWindow *vw ) { +#ifdef VIKING_PROMPT_IF_MODIFIED if ( vw->modified ) +#else + if (0) +#endif { GtkDialog *dia; dia = GTK_DIALOG ( gtk_message_dialog_new ( GTK_WINDOW(vw), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, @@ -308,6 +362,88 @@ static void draw_redraw ( VikWindow *vw ) vik_viewport_draw_scale ( vw->viking_vvp ); } +gboolean draw_buf_done = TRUE; + +static gboolean draw_buf(gpointer data) +{ + gpointer *pass_along = data; + gdk_threads_enter(); + gdk_draw_drawable (pass_along[0], pass_along[1], + pass_along[2], 0, 0, 0, 0, -1, -1); + draw_buf_done = TRUE; + gdk_threads_leave(); + return FALSE; +} + + +/* Mouse event handlers ************************************************************************/ + +static void draw_click (VikWindow *vw, GdkEventButton *event) +{ + + /* middle button pressed. we reserve all middle button and scroll events + * for panning and zooming; tools only get left/right/movement + */ + if ( event->button == 2) { + /* set panning origin */ + vw->pan_x = (gint) event->x; + vw->pan_y = (gint) event->y; + } + else { + toolbox_click(vw->vt, event); + } +} + +static void draw_mouse_motion (VikWindow *vw, GdkEventMotion *event) +{ + static VikCoord coord; + static struct UTM utm; + static struct LatLon ll; + static char pointer_buf[36]; + + toolbox_move(vw->vt, (GdkEventButton *)event); + + vik_viewport_screen_to_coord ( vw->viking_vvp, event->x, event->y, &coord ); + vik_coord_to_utm ( &coord, &utm ); + a_coords_utm_to_latlon ( &utm, &ll ); + g_snprintf ( pointer_buf, 36, "Cursor: %f %f", ll.lat, ll.lon ); + vik_statusbar_set_message ( vw->viking_vs, 4, pointer_buf ); + + if ( vw->pan_x != -1 ) { + vik_viewport_pan_sync ( vw->viking_vvp, event->x - vw->pan_x, event->y - vw->pan_y ); + } +} + +static void draw_release ( VikWindow *vw, GdkEventButton *event ) +{ + if ( event->button == 2 ) { /* move / pan */ + if ( ABS(vw->pan_x - event->x) <= 1 && ABS(vw->pan_y - event->y) <= 1 ) + vik_viewport_set_center_screen ( vw->viking_vvp, vw->pan_x, vw->pan_y ); + else + vik_viewport_set_center_screen ( vw->viking_vvp, vik_viewport_get_width(vw->viking_vvp)/2 - event->x + vw->pan_x, + vik_viewport_get_height(vw->viking_vvp)/2 - event->y + vw->pan_y ); + draw_update ( vw ); + vw->pan_x = vw->pan_y = -1; + } + else { + toolbox_release(vw->vt, event); + } +} + +static void draw_scroll (VikWindow *vw, GdkEventScroll *event) +{ + if ( event->direction == GDK_SCROLL_UP ) + vik_viewport_zoom_in (vw->viking_vvp); + else + vik_viewport_zoom_out(vw->viking_vvp); + draw_update(vw); +} + + + +/******************************************************************************** + ** Ruler tool code + ********************************************************************************/ static void draw_ruler(VikViewport *vvp, GdkDrawable *d, GdkGC *gc, gint x1, gint y1, gint x2, gint y2, gdouble distance) { PangoFontDescription *pfd; @@ -472,166 +608,168 @@ static void draw_ruler(VikViewport *vvp, GdkDrawable *d, GdkGC *gc, gint x1, gin g_object_unref ( G_OBJECT ( thickgc ) ); } -gboolean draw_buf_done = TRUE; +typedef struct { + VikWindow *vw; + VikViewport *vvp; + gboolean has_oldcoord; + VikCoord oldcoord; +} ruler_tool_state_t; -static gboolean draw_buf(gpointer data) +static gpointer ruler_create (VikWindow *vw, VikViewport *vvp) { - gpointer *pass_along = data; - gdk_threads_enter(); - gdk_draw_drawable (pass_along[0], pass_along[1], - pass_along[2], 0, 0, 0, 0, -1, -1); - gdk_threads_leave(); - draw_buf_done = TRUE; - return FALSE; + ruler_tool_state_t *s = g_new(ruler_tool_state_t, 1); + s->vw = vw; + s->vvp = vvp; + s->has_oldcoord = FALSE; + return s; } -static void draw_mouse_motion (VikWindow *vw, GdkEventMotion *event) +static void ruler_destroy (ruler_tool_state_t *s) { - VikViewport *vvp = vw->viking_vvp; - static VikCoord coord; - static struct UTM utm; - static struct LatLon ll; - static char pointer_buf[36]; + g_free(s); +} - vik_viewport_screen_to_coord ( vw->viking_vvp, event->x, event->y, &coord ); - vik_coord_to_utm ( &coord, &utm ); - a_coords_utm_to_latlon ( &utm, &ll ); +static VikLayerToolFuncStatus ruler_click (VikLayer *vl, GdkEventButton *event, ruler_tool_state_t *s) +{ + struct LatLon ll; + VikCoord coord; + gchar *temp; + if ( event->button == 1 ) { + vik_viewport_screen_to_coord ( s->vvp, (gint) event->x, (gint) event->y, &coord ); + vik_coord_to_latlon ( &coord, &ll ); + if ( s->has_oldcoord ) { + temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(s->oldcoord) ) ); + s->has_oldcoord = FALSE; + } + else { + temp = g_strdup_printf ( "%f %f", ll.lat, ll.lon ); + s->has_oldcoord = TRUE; + } - if ( vw->current_tool == TOOL_RULER ) - { - struct LatLon ll; - VikCoord coord; - gchar *temp; - - if ( vw->has_oldcoord ) { - int oldx, oldy, w1, h1, w2, h2; - static GdkPixmap *buf = NULL; - w1 = vik_viewport_get_width(vvp); - h1 = vik_viewport_get_height(vvp); - if (!buf) { - buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); - } - gdk_drawable_get_size(buf, &w2, &h2); - if (w1 != w2 || h1 != h2) { - g_object_unref ( G_OBJECT ( buf ) ); - buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); - } + vik_statusbar_set_message ( s->vw->viking_vs, 3, temp ); + g_free ( temp ); - vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord ); - vik_coord_to_latlon ( &coord, &ll ); - vik_viewport_coord_to_screen ( vvp, &vw->oldcoord, &oldx, &oldy ); - - gdk_draw_drawable (buf, GTK_WIDGET(vvp)->style->black_gc, - vik_viewport_get_pixmap(vvp), 0, 0, 0, 0, -1, -1); - draw_ruler(vvp, buf, GTK_WIDGET(vvp)->style->black_gc, oldx, oldy, event->x, event->y, vik_coord_diff( &coord, &(vw->oldcoord)) ); - if (draw_buf_done) { - static gpointer pass_along[3]; - pass_along[0] = GTK_WIDGET(vvp)->window; - pass_along[1] = GTK_WIDGET(vvp)->style->black_gc; - pass_along[2] = buf; - g_idle_add (draw_buf, pass_along); - draw_buf_done = FALSE; - } + s->oldcoord = coord; + } + else { + vik_viewport_set_center_screen ( s->vvp, (gint) event->x, (gint) event->y ); + draw_update ( s->vw ); + } + return VIK_LAYER_TOOL_ACK; +} - temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(vw->oldcoord) ) ); - vik_statusbar_set_message ( vw->viking_vs, 3, temp ); - g_free ( temp ); +static VikLayerToolFuncStatus ruler_move (VikLayer *vl, GdkEventButton *event, ruler_tool_state_t *s) +{ + VikViewport *vvp = s->vvp; + VikWindow *vw = s->vw; + + struct LatLon ll; + VikCoord coord; + gchar *temp; + + if ( s->has_oldcoord ) { + int oldx, oldy, w1, h1, w2, h2; + static GdkPixmap *buf = NULL; + w1 = vik_viewport_get_width(vvp); + h1 = vik_viewport_get_height(vvp); + if (!buf) { + buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); + } + gdk_drawable_get_size(buf, &w2, &h2); + if (w1 != w2 || h1 != h2) { + g_object_unref ( G_OBJECT ( buf ) ); + buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); } - } - g_snprintf ( pointer_buf, 36, "Cursor: %f %f", ll.lat, ll.lon ); + vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord ); + vik_coord_to_latlon ( &coord, &ll ); + vik_viewport_coord_to_screen ( vvp, &s->oldcoord, &oldx, &oldy ); + + gdk_draw_drawable (buf, GTK_WIDGET(vvp)->style->black_gc, + vik_viewport_get_pixmap(vvp), 0, 0, 0, 0, -1, -1); + draw_ruler(vvp, buf, GTK_WIDGET(vvp)->style->black_gc, oldx, oldy, event->x, event->y, vik_coord_diff( &coord, &(s->oldcoord)) ); + if (draw_buf_done) { + static gpointer pass_along[3]; + pass_along[0] = GTK_WIDGET(vvp)->window; + pass_along[1] = GTK_WIDGET(vvp)->style->black_gc; + pass_along[2] = buf; + g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, draw_buf, pass_along, NULL); + draw_buf_done = FALSE; + } - if ( vw->pan_x != -1 ) { - vik_viewport_pan_sync ( vw->viking_vvp, event->x - vw->pan_x, event->y - vw->pan_y ); + temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(s->oldcoord) ) ); + vik_statusbar_set_message ( vw->viking_vs, 3, temp ); + g_free ( temp ); } + return VIK_LAYER_TOOL_ACK; +} - vik_statusbar_set_message ( vw->viking_vs, 4, pointer_buf ); +static VikLayerToolFuncStatus ruler_release (VikLayer *vl, GdkEventButton *event, ruler_tool_state_t *s) +{ + return VIK_LAYER_TOOL_ACK; } -static void draw_scroll (VikWindow *vw, GdkEvent *event) +static void ruler_deactivate (VikLayer *vl, ruler_tool_state_t *s) { - if ( event->scroll.direction == GDK_SCROLL_UP ) - vik_viewport_zoom_in (vw->viking_vvp); - else - vik_viewport_zoom_out(vw->viking_vvp); - draw_update(vw); + draw_update ( s->vw ); } -static void draw_release ( VikWindow *vw, GdkEventButton *event ) +static VikToolInterface ruler_tool = + { "Ruler", + (VikToolConstructorFunc) ruler_create, + (VikToolDestructorFunc) ruler_destroy, + (VikToolActivationFunc) NULL, + (VikToolActivationFunc) ruler_deactivate, + (VikToolMouseFunc) ruler_click, + (VikToolMouseFunc) ruler_move, + (VikToolMouseFunc) ruler_release }; +/*** end ruler code ********************************************************/ + + + +/******************************************************************************** + ** Zoom tool code + ********************************************************************************/ +static gpointer zoomtool_create (VikWindow *vw, VikViewport *vvp) { - if ( event->button == 2 ) { /* move / pan */ - if ( ABS(vw->pan_x - event->x) <= 1 && ABS(vw->pan_y - event->y) <= 1 ) - vik_viewport_set_center_screen ( vw->viking_vvp, vw->pan_x, vw->pan_y ); - else - vik_viewport_set_center_screen ( vw->viking_vvp, vik_viewport_get_width(vw->viking_vvp)/2 - event->x + vw->pan_x, - vik_viewport_get_height(vw->viking_vvp)/2 - event->y + vw->pan_y ); - draw_update ( vw ); - vw->pan_x = vw->pan_y = -1; - } - if ( vw->current_tool == TOOL_LAYER && ( event->button == 1 || event->button == 3 ) && - vik_layer_get_interface(vw->tool_layer_id)->tools[vw->tool_tool_id].callback_release ) - { - vik_layers_panel_tool ( vw->viking_vlp, vw->tool_layer_id, - vik_layer_get_interface(vw->tool_layer_id)->tools[vw->tool_tool_id].callback_release, - event, vw->viking_vvp ); - } + return vw; } -static void draw_click (VikWindow *vw, GdkEventButton *event) +static VikLayerToolFuncStatus zoomtool_click (VikLayer *vl, GdkEventButton *event, VikWindow *vw) { - if ( event->button == 2) { - vw->pan_x = (gint) event->x; - vw->pan_y = (gint) event->y; - } else if ( vw->current_tool == TOOL_ZOOM ) - { - vw->modified = TRUE; - vik_viewport_set_center_screen ( vw->viking_vvp, (gint) event->x, (gint) event->y ); - if ( event->button == 1 ) - vik_viewport_zoom_in (vw->viking_vvp); - else if ( event->button == 3 ) - vik_viewport_zoom_out (vw->viking_vvp); - draw_update ( vw ); - } - else if ( vw->current_tool == TOOL_RULER ) - { - struct LatLon ll; - VikCoord coord; - gchar *temp; - if ( event->button == 1 || event->button == 3 ) - { - vik_viewport_screen_to_coord ( vw->viking_vvp, (gint) event->x, (gint) event->y, &coord ); - vik_coord_to_latlon ( &coord, &ll ); - if ( vw->has_oldcoord ) { - temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(vw->oldcoord) ) ); - vw->has_oldcoord = FALSE; - } - else { - temp = g_strdup_printf ( "%f %f", ll.lat, ll.lon ); - vw->has_oldcoord = TRUE; - } + vw->modified = TRUE; + vik_viewport_set_center_screen ( vw->viking_vvp, (gint) event->x, (gint) event->y ); + if ( event->button == 1 ) + vik_viewport_zoom_in (vw->viking_vvp); + else if ( event->button == 3 ) + vik_viewport_zoom_out (vw->viking_vvp); + draw_update ( vw ); + return VIK_LAYER_TOOL_ACK; +} - vik_statusbar_set_message ( vw->viking_vs, 3, temp ); - g_free ( temp ); +static VikLayerToolFuncStatus zoomtool_move (VikLayer *vl, GdkEventButton *event, VikViewport *vvp) +{ + return VIK_LAYER_TOOL_ACK; +} - vw->oldcoord = coord; - /* we don't use anything else so far */ - } - else - { - vik_viewport_set_center_screen ( vw->viking_vvp, (gint) event->x, (gint) event->y ); - draw_update ( vw ); - } - } - else if ( vw->current_tool == TOOL_LAYER ) - { - vw->modified = TRUE; - if ( ! vik_layers_panel_tool ( vw->viking_vlp, vw->tool_layer_id, - vik_layer_get_interface(vw->tool_layer_id)->tools[vw->tool_tool_id].callback, - event, vw->viking_vvp ) ) - a_dialog_info_msg_extra ( GTK_WINDOW(vw), "A %s Layer must exist and be either selected or visible before you can use this function.", vik_layer_get_interface ( vw->tool_layer_id )->name ); - } +static VikLayerToolFuncStatus zoomtool_release (VikLayer *vl, GdkEventButton *event, VikViewport *vvp) +{ + return VIK_LAYER_TOOL_ACK; } +static VikToolInterface zoom_tool = + { "Zoom", + (VikToolConstructorFunc) zoomtool_create, + (VikToolDestructorFunc) NULL, + (VikToolActivationFunc) NULL, + (VikToolActivationFunc) NULL, + (VikToolMouseFunc) zoomtool_click, + (VikToolMouseFunc) zoomtool_move, + (VikToolMouseFunc) zoomtool_release }; +/*** end ruler code ********************************************************/ + + + static void draw_zoom_cb ( GtkAction *a, VikWindow *vw ) { guint what = 128; @@ -708,12 +846,12 @@ static void menu_addlayer_cb ( GtkAction *a, VikWindow *vw ) static void menu_copy_layer_cb ( GtkAction *a, VikWindow *vw ) { - a_clipboard_copy ( vw->viking_vlp ); + a_clipboard_copy_selected ( vw->viking_vlp ); } static void menu_cut_layer_cb ( GtkAction *a, VikWindow *vw ) { - a_clipboard_copy ( vw->viking_vlp ); + a_clipboard_copy_selected ( vw->viking_vlp ); menu_delete_layer_cb ( a, vw ); } @@ -732,6 +870,11 @@ static void menu_properties_cb ( GtkAction *a, VikWindow *vw ) a_dialog_info_msg ( GTK_WINDOW(vw), "You must select a layer to show its properties." ); } +static void help_about_cb ( GtkAction *a, VikWindow *vw ) +{ + a_dialog_about(GTK_WINDOW(vw)); +} + static void menu_delete_layer_cb ( GtkAction *a, VikWindow *vw ) { if ( vik_layers_panel_get_selected ( vw->viking_vlp ) ) @@ -743,11 +886,110 @@ static void menu_delete_layer_cb ( GtkAction *a, VikWindow *vw ) a_dialog_info_msg ( GTK_WINDOW(vw), "You must select a layer to delete." ); } +/*************************************** + ** tool management routines + ** + ***************************************/ + +static toolbox_tools_t* toolbox_create(VikWindow *vw) +{ + toolbox_tools_t *vt = g_new(toolbox_tools_t, 1); + vt->tools = NULL; + vt->n_tools = 0; + vt->active_tool = -1; + vt->vw = vw; + if (!vw->viking_vvp) { + printf("Error: no viewport found.\n"); + exit(1); + } + return vt; +} + +static void toolbox_add_tool(toolbox_tools_t *vt, VikToolInterface *vti) +{ + vt->tools = g_renew(toolbox_tool_t, vt->tools, vt->n_tools+1); + vt->tools[vt->n_tools].ti = *vti; + if (vti->create) { + vt->tools[vt->n_tools].state = vti->create(vt->vw, vt->vw->viking_vvp); + } + else { + vt->tools[vt->n_tools].state = NULL; + } + vt->n_tools++; +} + +static int toolbox_get_tool(toolbox_tools_t *vt, const gchar *tool_name) +{ + int i; + for (i=0; in_tools; i++) { + if (!strcmp(tool_name, vt->tools[i].ti.name)) { + break; + } + } + return i; +} + +static void toolbox_activate(toolbox_tools_t *vt, const gchar *tool_name) +{ + int tool = toolbox_get_tool(vt, tool_name); + toolbox_tool_t *t = &vt->tools[tool]; + VikLayer *vl = vik_layers_panel_get_selected ( vt->vw->viking_vlp ); + + if (tool == vt->n_tools) { + printf("panic: trying to activate a non-existent tool... \n"); + exit(1); + } + /* is the tool already active? */ + if (vt->active_tool == tool) { + return; + } + + if (vt->active_tool != -1) { + if (vt->tools[vt->active_tool].ti.deactivate) { + vt->tools[vt->active_tool].ti.deactivate(NULL, vt->tools[vt->active_tool].state); + } + } + if (t->ti.activate) { + t->ti.activate(vl, t->state); + } + vt->active_tool = tool; +} + +static void toolbox_click (toolbox_tools_t *vt, GdkEventButton *event) +{ + VikLayer *vl = vik_layers_panel_get_selected ( vt->vw->viking_vlp ); + if (vt->active_tool != -1 && vt->tools[vt->active_tool].ti.click) { + vt->tools[vt->active_tool].ti.click(vl, event, vt->tools[vt->active_tool].state); + } +} + +static void toolbox_move (toolbox_tools_t *vt, GdkEventButton *event) +{ + VikLayer *vl = vik_layers_panel_get_selected ( vt->vw->viking_vlp ); + if (vt->active_tool != -1 && vt->tools[vt->active_tool].ti.move) { + vt->tools[vt->active_tool].ti.move(vl, event, vt->tools[vt->active_tool].state); + } +} + +static void toolbox_release (toolbox_tools_t *vt, GdkEventButton *event) +{ + VikLayer *vl = vik_layers_panel_get_selected ( vt->vw->viking_vlp ); + if (vt->active_tool != -1 && vt->tools[vt->active_tool].ti.release) { + vt->tools[vt->active_tool].ti.release(vl, event, vt->tools[vt->active_tool].state); + } +} +/** End tool management ************************************/ + + + +/* this function gets called whenever a toolbar tool is clicked */ static void menu_tool_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ) { /* White Magic, my friends ... White Magic... */ int i, j; + toolbox_activate(vw->vt, gtk_action_get_name(a)); + if (!strcmp(gtk_action_get_name(a), "Zoom")) { vw->current_tool = TOOL_ZOOM; } @@ -755,6 +997,7 @@ static void menu_tool_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ) vw->current_tool = TOOL_RULER; } else { + /* TODO: only enable tools from active layer */ for (i=0; itools_count; j++ ) { if (!strcmp(vik_layer_get_interface(i)->tools[j].name, gtk_action_get_name(a))) { @@ -842,7 +1085,11 @@ static void load_file ( GtkAction *a, VikWindow *vw ) if ( gtk_dialog_run ( GTK_DIALOG(vw->open_dia) ) == GTK_RESPONSE_OK ) { gtk_widget_hide ( vw->open_dia ); +#ifdef VIKING_PROMPT_IF_MODIFIED if ( (vw->modified || vw->filename) && newwindow ) +#else + if ( vw->filename && newwindow ) +#endif g_signal_emit ( G_OBJECT(vw), window_signals[VW_OPENWINDOW_SIGNAL], 0, gtk_file_selection_get_selections (GTK_FILE_SELECTION(vw->open_dia) ) ); else { gchar **files = gtk_file_selection_get_selections (GTK_FILE_SELECTION(vw->open_dia) ); @@ -907,7 +1154,17 @@ static gboolean save_file ( GtkAction *a, VikWindow *vw ) static void acquire_from_gps ( GtkAction *a, VikWindow *vw ) { - a_acquire_from_gps(vw, vw->viking_vlp, vw->viking_vvp ); + a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gps_interface ); +} + +static void acquire_from_google ( GtkAction *a, VikWindow *vw ) +{ + a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_google_interface ); +} + +static void acquire_from_gc ( GtkAction *a, VikWindow *vw ) +{ + a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gc_interface ); } static void clear_cb ( GtkAction *a, VikWindow *vw ) @@ -923,6 +1180,14 @@ static void window_close ( GtkAction *a, VikWindow *vw ) gtk_widget_destroy ( GTK_WIDGET(vw) ); } +static gboolean save_file_and_exit ( GtkAction *a, VikWindow *vw ) +{ + if (save_file( NULL, vw)) + window_close( NULL, vw); + else + return(FALSE); +} + static void zoom_to_cb ( GtkAction *a, VikWindow *vw ) { gdouble xmpp = vik_viewport_get_xmpp ( vw->viking_vvp ), ympp = vik_viewport_get_ympp ( vw->viking_vvp ); @@ -1293,22 +1558,34 @@ static void set_bg_color ( GtkAction *a, VikWindow *vw ) gtk_widget_destroy ( colorsd ); } + + +/*********************************************************************************************** + ** GUI Creation + ***********************************************************************************************/ + static GtkActionEntry entries[] = { { "File", NULL, "_File", 0, 0, 0 }, + { "Edit", NULL, "_Edit", 0, 0, 0 }, { "View", NULL, "_View", 0, 0, 0 }, { "SetZoom", NULL, "_Zoom", 0, 0, 0 }, { "Layers", NULL, "_Layers", 0, 0, 0 }, { "Tools", NULL, "_Tools", 0, 0, 0 }, + { "Help", NULL, "_Help", 0, 0, 0 }, { "New", GTK_STOCK_NEW, "_New", "N", "New file", (GCallback)newwindow_cb }, { "Open", GTK_STOCK_OPEN, "_Open", "O", "Open a file", (GCallback)load_file }, { "Append", GTK_STOCK_ADD, "A_ppend File", NULL, "Append data from a different file", (GCallback)load_file }, - { "Acquire", NULL, "A_cquire from GPS", NULL, "Transfer data from a GPS device", (GCallback)acquire_from_gps }, + { "Acquire", NULL, "A_cquire", 0, 0, 0 }, + { "AcquireGPS", NULL, "From _GPS", NULL, "Transfer data from a GPS device", (GCallback)acquire_from_gps }, + { "AcquireGoogle", NULL, "Google _Directions", NULL, "Get driving directions from Google", (GCallback)acquire_from_google }, + { "AcquireGC", NULL, "Geo_caches", NULL, "Get Geocaches from geocaching.com", (GCallback)acquire_from_gc }, { "Save", GTK_STOCK_SAVE, "_Save", "S", "Save the file", (GCallback)save_file }, { "SaveAs", GTK_STOCK_SAVE_AS, "Save _As", NULL, "Save the file under different name", (GCallback)save_file_as }, { "GenImg", GTK_STOCK_CLEAR, "_Generate Image File", NULL, "Save a snapshot of the workspace into a file", (GCallback)draw_to_image_file_cb }, { "GenImgDir", GTK_STOCK_DND_MULTIPLE, "Generate _Directory of Images", NULL, "FIXME:IMGDIR", (GCallback)draw_to_image_dir_cb }, { "Exit", GTK_STOCK_QUIT, "E_xit", "W", "Exit the program", (GCallback)window_close }, + { "SaveExit", GTK_STOCK_QUIT, "Save and Exit", NULL, "Save and Exit the program", (GCallback)save_file_and_exit }, { "GotoLL", GTK_STOCK_QUIT, "_Go to Lat\\/Lon...", NULL, "Go to arbitrary lat\\/lon coordinate", (GCallback)draw_goto_cb }, { "GotoUTM", GTK_STOCK_QUIT, "Go to UTM...", NULL, "Go to arbitrary UTM coordinate", (GCallback)draw_goto_cb }, @@ -1334,15 +1611,17 @@ static GtkActionEntry entries[] = { { "Delete", GTK_STOCK_DELETE, "_Delete", NULL, NULL, (GCallback)menu_delete_layer_cb }, { "DeleteAll", NULL, "Delete All", NULL, NULL, (GCallback)clear_cb }, { "Properties",GTK_STOCK_PROPERTIES, "_Properties", NULL, NULL, (GCallback)menu_properties_cb }, + + { "About", GTK_STOCK_ABOUT, "_About", NULL, NULL, (GCallback)help_about_cb }, }; /* Radio items */ static GtkRadioActionEntry mode_entries[] = { { "ModeUTM", NULL, "_UTM Mode", "u", NULL, 0 }, { "ModeExpedia", NULL, "_Expedia Mode", "e", NULL, 1 }, - { "ModeGoogle", NULL, "_Google Mode", "g", NULL, 2 }, - { "ModeKH", NULL, "_KH\\/Flat LatLon Mode", "k", NULL, 3 }, - { "ModeMercator", NULL, "_Mercator (New Google)", "m", NULL, 4 } + { "ModeGoogle", NULL, "_Old Google Mode", "o", NULL, 2 }, + { "ModeKH", NULL, "Old _KH Mode", "k", NULL, 3 }, + { "ModeMercator", NULL, "_Google Mode", "g", NULL, 4 } }; static GtkRadioActionEntry tool_entries[] = { @@ -1370,7 +1649,9 @@ static void window_create_ui( VikWindow *window ) uim = gtk_ui_manager_new (); window->uim = uim; - + toolbox_add_tool(window->vt, &ruler_tool); + toolbox_add_tool(window->vt, &zoom_tool); + error = NULL; if (!(mid = gtk_ui_manager_add_ui_from_string (uim, menu_xml, -1, &error))) { g_error_free (error); @@ -1383,6 +1664,7 @@ static void window_create_ui( VikWindow *window ) gtk_action_group_add_radio_actions (action_group, mode_entries, G_N_ELEMENTS (mode_entries), 0, (GCallback)window_change_coord_mode_cb, window); icon_factory = gtk_icon_factory_new (); + gtk_icon_factory_add_default (icon_factory); register_vik_icons(icon_factory); @@ -1433,6 +1715,8 @@ static void window_create_ui( VikWindow *window ) vik_layer_get_interface(i)->tools[j].name, GTK_UI_MANAGER_TOOLITEM, FALSE); + toolbox_add_tool(window->vt, &(vik_layer_get_interface(i)->tools[j])); + radio->name = vik_layer_get_interface(i)->tools[j].name; radio->stock_id = vik_layer_get_interface(i)->tools[j].name, radio->label = vik_layer_get_interface(i)->tools[j].name; @@ -1441,20 +1725,29 @@ static void window_create_ui( VikWindow *window ) radio->value = ntools; } } + g_object_unref (icon_factory); gtk_action_group_add_radio_actions(action_group, tools, ntools, 0, (GCallback)menu_tool_cb, window); g_free(tools); gtk_ui_manager_insert_action_group (uim, action_group, 0); + for (i=0; itools_count; j++ ) { + GtkAction *action = gtk_action_group_get_action(action_group, + vik_layer_get_interface(i)->tools[j].name); + g_object_set(action, "sensitive", FALSE, NULL); + } + } + window->action_group = action_group; + accel_group = gtk_ui_manager_get_accel_group (uim); gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); gtk_ui_manager_ensure_update (uim); - gtk_icon_factory_add_default (icon_factory); - g_object_unref (icon_factory); } + #include "icons/icons.h" static struct { const GdkPixdata *data; @@ -1472,7 +1765,6 @@ static struct { { &showpic_18, "Show Picture" }, }; - static gint n_stock_icons = G_N_ELEMENTS (stock_icons); static void