X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/7c8bddffcbf6bef3d938d9925ee312ec1d4688ba..70177381ae2b6540e92c504833aeb546c38dd54b:/src/vikwindow.c diff --git a/src/vikwindow.c b/src/vikwindow.c index 5d0be89a..5c7d484b 100644 --- a/src/vikwindow.c +++ b/src/vikwindow.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003-2005, Evan Battaglia * Copyright (C) 2005-2006, Alex Foobarian - * Copyright (C) 2012-2013, Rob Norris + * Copyright (C) 2012-2014, Rob Norris * * 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 @@ -35,6 +35,7 @@ #include "mapcache.h" #include "print.h" #include "preferences.h" +#include "toolbar.h" #include "viklayer_defaults.h" #include "icons/icons.h" #include "vikexttools.h" @@ -42,6 +43,8 @@ #include "garminsymbols.h" #include "vikmapslayer.h" #include "geonamessearch.h" +#include "vikutils.h" +#include "dir.h" #ifdef HAVE_STDLIB_H #include @@ -112,6 +115,10 @@ static void draw_status ( VikWindow *vw ); /* End Drawing Functions */ +static void toggle_draw_scale ( GtkAction *a, VikWindow *vw ); +static void toggle_draw_centermark ( GtkAction *a, VikWindow *vw ); +static void toggle_draw_highlight ( GtkAction *a, VikWindow *vw ); + 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 ); @@ -131,7 +138,8 @@ typedef struct { VikWindow *vw; } toolbox_tools_t; -static void menu_tool_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ); +static void menu_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ); +static void window_change_coord_mode_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, gint layer_type ); static int toolbox_get_tool(toolbox_tools_t *vt, const gchar *tool_name); @@ -155,11 +163,14 @@ static gboolean window_save ( VikWindow *vw ); struct _VikWindow { GtkWindow gtkwindow; + GtkWidget *hpaned; VikViewport *viking_vvp; VikLayersPanel *viking_vlp; VikStatusbar *viking_vs; + VikToolbar *viking_vtb; - GtkToolbar *toolbar; + GtkWidget *main_vbox; + GtkWidget *menu_hbox; GdkCursor *busy_cursor; GdkCursor *viewport_cursor; // only a reference @@ -172,6 +183,15 @@ struct _VikWindow { GtkActionGroup *action_group; + // Display controls + // NB scale, centermark and highlight are in viewport. + gboolean show_full_screen; + gboolean show_side_panel; + gboolean show_statusbar; + gboolean show_toolbar; + gboolean show_main_menu; + + gboolean select_move; gboolean pan_move; gint pan_x, pan_y; gint delayed_pan_x, delayed_pan_y; // Temporary storage @@ -285,12 +305,17 @@ static gboolean statusbar_idle_update ( statusbar_idle_data *sid ) */ void vik_window_statusbar_update ( VikWindow *vw, const gchar* message, vik_statusbar_type_t vs_type ) { + GThread *thread = vik_window_get_thread ( vw ); + if ( !thread ) + // Do nothing + return; + statusbar_idle_data *sid = g_malloc ( sizeof (statusbar_idle_data) ); sid->vs = vw->viking_vs; sid->vs_type = vs_type; sid->message = g_strdup ( message ); - if ( g_thread_self() == vik_window_get_thread ( vw ) ) { + if ( g_thread_self() == thread ) { g_idle_add ( (GSourceFunc) statusbar_idle_update, sid ); } else { @@ -351,7 +376,7 @@ VikWindow *vik_window_new_window () gboolean toolbar; if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_TOOLBAR, &toolbar ) ) if ( ! toolbar ) { - gtk_widget_hide ( GTK_WIDGET(vw->toolbar) ); + gtk_widget_hide ( toolbar_get_widget (vw->viking_vtb) ); GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewToolBar" ); gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), FALSE ); } @@ -454,7 +479,8 @@ void vik_window_new_window_finish ( VikWindow *vw ) vik_statusbar_set_message ( vw->viking_vs, VIK_STATUSBAR_INFO, _("Trying to determine location...") ); - a_background_thread ( GTK_WINDOW(vw), + a_background_thread ( BACKGROUND_POOL_REMOTE, + GTK_WINDOW(vw), _("Determining location"), (vik_thr_func) determine_location_thread, vw, @@ -503,6 +529,7 @@ void vik_window_selected_layer(VikWindow *vw, VikLayer *vl) action = gtk_action_group_get_action(vw->action_group, layer_interface->tools[j].radioActionEntry.name); g_object_set(action, "sensitive", i == vl->type, NULL); + toolbar_action_set_sensitive ( vw->viking_vtb, vik_layer_get_interface(i)->tools[j].radioActionEntry.name, i == vl->type ); } } } @@ -524,6 +551,8 @@ static void window_finalize ( GObject *gob ) g_free ( vw->vt->tools ); g_free ( vw->vt ); + vik_toolbar_finalize ( vw->viking_vtb ); + G_OBJECT_CLASS(parent_class)->finalize(gob); } @@ -552,7 +581,7 @@ static void zoom_changed (GtkMenuShell *menushell, GtkWidget *aw = gtk_menu_get_active ( GTK_MENU (menushell) ); gint active = GPOINTER_TO_INT(g_object_get_data ( G_OBJECT (aw), "position" )); - gdouble zoom_request = pow (2, active-2 ); + gdouble zoom_request = pow (2, active-5 ); // But has it really changed? gdouble current_zoom = vik_viewport_get_zoom ( vw->viking_vvp ); @@ -569,7 +598,7 @@ static void zoom_changed (GtkMenuShell *menushell, static GtkWidget *create_zoom_menu_all_levels ( gdouble mpp ) { GtkWidget *menu = gtk_menu_new (); - char *itemLabels[] = { "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192", "16384", "32768" }; + char *itemLabels[] = { "0.031", "0.063", "0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192", "16384", "32768" }; int i; for (i = 0 ; i < G_N_ELEMENTS(itemLabels) ; i++) @@ -580,7 +609,7 @@ static GtkWidget *create_zoom_menu_all_levels ( gdouble mpp ) g_object_set_data (G_OBJECT (item), "position", GINT_TO_POINTER(i)); } - gint active = 2 + round ( log (mpp) / log (2) ); + gint active = 5 + round ( log (mpp) / log (2) ); // Ensure value derived from mpp is in bounds of the menu if ( active >= G_N_ELEMENTS(itemLabels) ) active = G_N_ELEMENTS(itemLabels) - 1; @@ -686,20 +715,34 @@ static void drag_data_received_cb ( GtkWidget *widget, gtk_drag_finish ( context, success, FALSE, time ); } +static void toolbar_tool_cb ( GtkAction *old, GtkAction *current, gpointer gp ) +{ + VikWindow *vw = (VikWindow*)gp; + GtkAction *action = gtk_action_group_get_action ( vw->action_group, gtk_action_get_name(current) ); + if ( action ) + gtk_action_activate ( action ); +} + +static void toolbar_reload_cb ( GtkActionGroup *grp, gpointer gp ) +{ + VikWindow *vw = (VikWindow*)gp; + center_changed_cb ( vw ); +} + #define VIK_SETTINGS_WIN_MAX "window_maximized" #define VIK_SETTINGS_WIN_FULLSCREEN "window_fullscreen" #define VIK_SETTINGS_WIN_WIDTH "window_width" #define VIK_SETTINGS_WIN_HEIGHT "window_height" +#define VIK_SETTINGS_WIN_PANE_POSITION "window_horizontal_pane_position" #define VIK_SETTINGS_WIN_SAVE_IMAGE_WIDTH "window_save_image_width" #define VIK_SETTINGS_WIN_SAVE_IMAGE_HEIGHT "window_save_image_height" #define VIK_SETTINGS_WIN_SAVE_IMAGE_PNG "window_save_image_as_png" #define VIK_SETTINGS_WIN_COPY_CENTRE_FULL_FORMAT "window_copy_centre_full_format" +#define VIKING_ACCELERATOR_KEY_FILE "keys.rc" + static void vik_window_init ( VikWindow *vw ) { - GtkWidget *main_vbox; - GtkWidget *hpaned; - vw->action_group = NULL; vw->viking_vvp = vik_viewport_new(); @@ -708,20 +751,18 @@ static void vik_window_init ( VikWindow *vw ) vw->viking_vs = vik_statusbar_new(); vw->vt = toolbox_create(vw); + vw->viking_vtb = vik_toolbar_new (); window_create_ui(vw); window_set_filename (vw, NULL); - vw->toolbar = GTK_TOOLBAR(gtk_ui_manager_get_widget (vw->uim, "/MainToolbar")); vw->busy_cursor = gdk_cursor_new ( GDK_WATCH ); - // Set the default tool - gtk_action_activate ( gtk_action_group_get_action ( vw->action_group, "Pan" ) ); - vw->filename = NULL; vw->loaded_type = LOAD_TYPE_READ_FAILURE; //AKA none vw->modified = FALSE; vw->only_updating_coord_mode_ui = FALSE; - + + vw->select_move = FALSE; vw->pan_move = FALSE; vw->pan_x = vw->pan_y = -1; vw->single_click_pending = FALSE; @@ -742,13 +783,27 @@ static void vik_window_init ( VikWindow *vw ) else vw->draw_image_save_as_png = DRAW_IMAGE_DEFAULT_SAVE_AS_PNG; - main_vbox = gtk_vbox_new(FALSE, 1); - gtk_container_add (GTK_CONTAINER (vw), main_vbox); - - gtk_box_pack_start (GTK_BOX(main_vbox), gtk_ui_manager_get_widget (vw->uim, "/MainMenu"), FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX(main_vbox), GTK_WIDGET(vw->toolbar), FALSE, TRUE, 0); - gtk_toolbar_set_icon_size (vw->toolbar, GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_toolbar_set_style (vw->toolbar, GTK_TOOLBAR_ICONS); + vw->main_vbox = gtk_vbox_new(FALSE, 1); + gtk_container_add (GTK_CONTAINER (vw), vw->main_vbox); + vw->menu_hbox = gtk_hbox_new(FALSE, 1); + GtkWidget *menu_bar = gtk_ui_manager_get_widget (vw->uim, "/MainMenu"); + gtk_box_pack_start (GTK_BOX(vw->menu_hbox), menu_bar, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX(vw->main_vbox), vw->menu_hbox, FALSE, TRUE, 0); + + toolbar_init(vw->viking_vtb, + &vw->gtkwindow, + vw->main_vbox, + vw->menu_hbox, + toolbar_tool_cb, + toolbar_reload_cb, + (gpointer)vw); // This auto packs toolbar into the vbox + // Must be performed post toolbar init + gint i,j; + for (i=0; itools_count; j++ ) { + toolbar_action_set_sensitive ( vw->viking_vtb, vik_layer_get_interface(i)->tools[j].radioActionEntry.name, FALSE ); + } + } vik_ext_tool_datasources_add_menu_items ( vw, vw->uim ); @@ -780,14 +835,14 @@ static void vik_window_init ( VikWindow *vw ) // Set initial button sensitivity center_changed_cb ( vw ); - hpaned = gtk_hpaned_new (); - gtk_paned_pack1 ( GTK_PANED(hpaned), GTK_WIDGET (vw->viking_vlp), FALSE, FALSE ); - gtk_paned_pack2 ( GTK_PANED(hpaned), GTK_WIDGET (vw->viking_vvp), TRUE, TRUE ); + vw->hpaned = gtk_hpaned_new (); + gtk_paned_pack1 ( GTK_PANED(vw->hpaned), GTK_WIDGET (vw->viking_vlp), FALSE, TRUE ); + gtk_paned_pack2 ( GTK_PANED(vw->hpaned), GTK_WIDGET (vw->viking_vvp), TRUE, TRUE ); /* This packs the button into the window (a gtk container). */ - gtk_box_pack_start (GTK_BOX(main_vbox), hpaned, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX(vw->main_vbox), vw->hpaned, TRUE, TRUE, 0); - gtk_box_pack_end (GTK_BOX(main_vbox), GTK_WIDGET(vw->viking_vs), FALSE, TRUE, 0); + gtk_box_pack_end (GTK_BOX(vw->main_vbox), GTK_WIDGET(vw->viking_vs), FALSE, TRUE, 0); a_background_add_window ( vw ); @@ -823,11 +878,19 @@ static void vik_window_init ( VikWindow *vw ) gboolean full; if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_FULLSCREEN, &full ) ) { if ( full ) { + vw->show_full_screen = TRUE; gtk_window_fullscreen ( GTK_WINDOW(vw) ); GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/FullScreen" ); - gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), TRUE ); + if ( check_box ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), TRUE ); } } + + gint position = -1; // Let GTK determine default positioning + if ( !a_settings_get_integer ( VIK_SETTINGS_WIN_PANE_POSITION, &position ) ) { + position = -1; + } + gtk_paned_set_position ( GTK_PANED(vw->hpaned), position ); } gtk_window_set_default_size ( GTK_WINDOW(vw), width, height ); @@ -837,6 +900,11 @@ static void vik_window_init ( VikWindow *vw ) vw->save_img_dia = NULL; vw->save_img_dir_dia = NULL; + vw->show_side_panel = TRUE; + vw->show_statusbar = TRUE; + vw->show_toolbar = TRUE; + vw->show_main_menu = TRUE; + // Only accept Drag and Drop of files onto the viewport gtk_drag_dest_set ( GTK_WIDGET(vw->viking_vvp), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY ); gtk_drag_dest_add_uri_targets ( GTK_WIDGET(vw->viking_vvp) ); @@ -846,6 +914,14 @@ static void vik_window_init ( VikWindow *vw ) // Hopefully we are storing the main thread value here :) // [ATM any window initialization is always be performed by the main thread] vw->thread = g_thread_self(); + + // Set the default tool + mode + gtk_action_activate ( gtk_action_group_get_action ( vw->action_group, "Pan" ) ); + gtk_action_activate ( gtk_action_group_get_action ( vw->action_group, "ModeMercator" ) ); + + gchar *accel_file_name = g_build_filename ( a_get_viking_dir(), VIKING_ACCELERATOR_KEY_FILE, NULL ); + gtk_accel_map_load ( accel_file_name ); + g_free ( accel_file_name ); } static VikWindow *window_new () @@ -899,9 +975,21 @@ static gboolean key_press_event( VikWindow *vw, GdkEventKey *event, gpointer dat map_download = TRUE; map_download_only_new = FALSE; } + // Standard Ctrl+KP+ / Ctrl+KP- to zoom in/out respectively + else if ( event->keyval == GDK_KEY_KP_Add && (event->state & modifiers) == GDK_CONTROL_MASK ) { + vik_viewport_zoom_in ( vw->viking_vvp ); + draw_update(vw); + return TRUE; // handled keypress + } + else if ( event->keyval == GDK_KEY_KP_Subtract && (event->state & modifiers) == GDK_CONTROL_MASK ) { + vik_viewport_zoom_out ( vw->viking_vvp ); + draw_update(vw); + return TRUE; // handled keypress + } if ( map_download ) { simple_map_update ( vw, map_download_only_new ); + return TRUE; // handled keypress } VikLayer *vl = vik_layers_panel_get_selected ( vw->viking_vlp ); @@ -973,7 +1061,7 @@ static gboolean delete_event( VikWindow *vw ) a_settings_set_boolean ( VIK_SETTINGS_WIN_STATUSBAR, GTK_WIDGET_VISIBLE (GTK_WIDGET(vw->viking_vs)) ); - a_settings_set_boolean ( VIK_SETTINGS_WIN_TOOLBAR, GTK_WIDGET_VISIBLE (GTK_WIDGET(vw->toolbar)) ); + a_settings_set_boolean ( VIK_SETTINGS_WIN_TOOLBAR, GTK_WIDGET_VISIBLE (toolbar_get_widget(vw->viking_vtb)) ); // If supersized - no need to save the enlarged width+height values if ( ! (state_fullscreen || state_max) ) { @@ -982,11 +1070,17 @@ static gboolean delete_event( VikWindow *vw ) a_settings_set_integer ( VIK_SETTINGS_WIN_WIDTH, width ); a_settings_set_integer ( VIK_SETTINGS_WIN_HEIGHT, height ); } + + a_settings_set_integer ( VIK_SETTINGS_WIN_PANE_POSITION, gtk_paned_get_position (GTK_PANED(vw->hpaned)) ); } a_settings_set_integer ( VIK_SETTINGS_WIN_SAVE_IMAGE_WIDTH, vw->draw_image_width ); a_settings_set_integer ( VIK_SETTINGS_WIN_SAVE_IMAGE_HEIGHT, vw->draw_image_height ); a_settings_set_boolean ( VIK_SETTINGS_WIN_SAVE_IMAGE_PNG, vw->draw_image_save_as_png ); + + gchar *accel_file_name = g_build_filename ( a_get_viking_dir(), VIKING_ACCELERATOR_KEY_FILE, NULL ); + gtk_accel_map_save ( accel_file_name ); + g_free ( accel_file_name ); } return FALSE; @@ -1446,20 +1540,29 @@ static void draw_ruler(VikViewport *vvp, GdkDrawable *d, GdkGC *gc, gint x1, gin switch (dist_units) { case VIK_UNITS_DISTANCE_KILOMETRES: if (distance >= 1000 && distance < 100000) { - g_sprintf(str, "%3.2f km", distance/1000.0); + g_sprintf(str, "%3.2f km", distance/1000.0); } else if (distance < 1000) { - g_sprintf(str, "%d m", (int)distance); + g_sprintf(str, "%d m", (int)distance); } else { - g_sprintf(str, "%d km", (int)distance/1000); + g_sprintf(str, "%d km", (int)distance/1000); } break; case VIK_UNITS_DISTANCE_MILES: if (distance >= VIK_MILES_TO_METERS(1) && distance < VIK_MILES_TO_METERS(100)) { - g_sprintf(str, "%3.2f miles", VIK_METERS_TO_MILES(distance)); + g_sprintf(str, "%3.2f miles", VIK_METERS_TO_MILES(distance)); } else if (distance < VIK_MILES_TO_METERS(1)) { - g_sprintf(str, "%d yards", (int)(distance*1.0936133)); + g_sprintf(str, "%d yards", (int)(distance*1.0936133)); } else { - g_sprintf(str, "%d miles", (int)VIK_METERS_TO_MILES(distance)); + g_sprintf(str, "%d miles", (int)VIK_METERS_TO_MILES(distance)); + } + break; + case VIK_UNITS_DISTANCE_NAUTICAL_MILES: + if (distance >= VIK_NAUTICAL_MILES_TO_METERS(1) && distance < VIK_NAUTICAL_MILES_TO_METERS(100)) { + g_sprintf(str, "%3.2f NM", VIK_METERS_TO_NAUTICAL_MILES(distance)); + } else if (distance < VIK_NAUTICAL_MILES_TO_METERS(1)) { + g_sprintf(str, "%d yards", (int)(distance*1.0936133)); + } else { + g_sprintf(str, "%d NM", (int)VIK_METERS_TO_NAUTICAL_MILES(distance)); } break; default: @@ -1546,14 +1649,17 @@ static VikLayerToolFuncStatus ruler_click (VikLayer *vl, GdkEventButton *event, vik_units_distance_t dist_units = a_vik_get_units_distance (); switch (dist_units) { case VIK_UNITS_DISTANCE_KILOMETRES: - temp = g_strdup_printf ( "%s %s DIFF %f meters", lat, lon, vik_coord_diff( &coord, &(s->oldcoord) ) ); - break; + temp = g_strdup_printf ( "%s %s DIFF %f meters", lat, lon, vik_coord_diff( &coord, &(s->oldcoord) ) ); + break; case VIK_UNITS_DISTANCE_MILES: - temp = g_strdup_printf ( "%s %s DIFF %f miles", lat, lon, VIK_METERS_TO_MILES(vik_coord_diff( &coord, &(s->oldcoord) )) ); - break; + temp = g_strdup_printf ( "%s %s DIFF %f miles", lat, lon, VIK_METERS_TO_MILES(vik_coord_diff( &coord, &(s->oldcoord) )) ); + break; + case VIK_UNITS_DISTANCE_NAUTICAL_MILES: + temp = g_strdup_printf ( "%s %s DIFF %f NM", lat, lon, VIK_METERS_TO_NAUTICAL_MILES(vik_coord_diff( &coord, &(s->oldcoord) )) ); + break; default: - temp = g_strdup_printf ("Just to keep the compiler happy"); - g_critical("Houston, we've had a problem. distance=%d", dist_units); + temp = g_strdup_printf ("Just to keep the compiler happy"); + g_critical("Houston, we've had a problem. distance=%d", dist_units); } s->has_oldcoord = FALSE; @@ -1623,6 +1729,9 @@ static VikLayerToolFuncStatus ruler_move (VikLayer *vl, GdkEventMotion *event, r case VIK_UNITS_DISTANCE_MILES: temp = g_strdup_printf ( "%s %s DIFF %f miles", lat, lon, VIK_METERS_TO_MILES (vik_coord_diff( &coord, &(s->oldcoord) )) ); break; + case VIK_UNITS_DISTANCE_NAUTICAL_MILES: + temp = g_strdup_printf ( "%s %s DIFF %f NM", lat, lon, VIK_METERS_TO_NAUTICAL_MILES (vik_coord_diff( &coord, &(s->oldcoord) )) ); + break; default: temp = g_strdup_printf ("Just to keep the compiler happy"); g_critical("Houston, we've had a problem. distance=%d", dist_units); @@ -2044,36 +2153,55 @@ static void click_layer_selected (VikLayer *vl, clicker *ck) ck->cont = !vik_layer_get_interface(vl->type)->select_click ( vl, ck->event, ck->vvp, ck->tool_edit ); } +#ifdef WINDOWS +// Hopefully Alt keys by default +#define VIK_MOVE_MODIFIER GDK_MOD1_MASK +#else +// Alt+mouse on Linux desktops tend to be used by the desktop manager +// Thus use an alternate modifier - you may need to set something into this group +#define VIK_MOVE_MODIFIER GDK_MOD5_MASK +#endif + static VikLayerToolFuncStatus selecttool_click (VikLayer *vl, GdkEventButton *event, tool_ed_t *t) { + t->vw->select_move = FALSE; /* Only allow selection on primary button */ if ( event->button == 1 ) { - /* Enable click to apply callback to potentially all track/waypoint layers */ - /* Useful as we can find things that aren't necessarily in the currently selected layer */ - GList* gl = vik_layers_panel_get_all_layers_of_type ( t->vw->viking_vlp, VIK_LAYER_TRW, FALSE ); // Don't get invisible layers - clicker ck; - ck.cont = TRUE; - ck.vvp = t->vw->viking_vvp; - ck.event = event; - ck.tool_edit = t; - g_list_foreach ( gl, (GFunc) click_layer_selected, &ck ); - g_list_free ( gl ); - - // If nothing found then deselect & redraw screen if necessary to remove the highlight - if ( ck.cont ) { - GtkTreeIter iter; - VikTreeview *vtv = vik_layers_panel_get_treeview ( t->vw->viking_vlp ); - - if ( vik_treeview_get_selected_iter ( vtv, &iter ) ) { - // Only clear if selected thing is a TrackWaypoint layer or a sublayer - gint type = vik_treeview_item_get_type ( vtv, &iter ); - if ( type == VIK_TREEVIEW_TYPE_SUBLAYER || - VIK_LAYER(vik_treeview_item_get_pointer ( vtv, &iter ))->type == VIK_LAYER_TRW ) { + + if ( event->state & VIK_MOVE_MODIFIER ) + vik_window_pan_click ( t->vw, event ); + else { + /* Enable click to apply callback to potentially all track/waypoint layers */ + /* Useful as we can find things that aren't necessarily in the currently selected layer */ + GList* gl = vik_layers_panel_get_all_layers_of_type ( t->vw->viking_vlp, VIK_LAYER_TRW, FALSE ); // Don't get invisible layers + clicker ck; + ck.cont = TRUE; + ck.vvp = t->vw->viking_vvp; + ck.event = event; + ck.tool_edit = t; + g_list_foreach ( gl, (GFunc) click_layer_selected, &ck ); + g_list_free ( gl ); + + // If nothing found then deselect & redraw screen if necessary to remove the highlight + if ( ck.cont ) { + GtkTreeIter iter; + VikTreeview *vtv = vik_layers_panel_get_treeview ( t->vw->viking_vlp ); + + if ( vik_treeview_get_selected_iter ( vtv, &iter ) ) { + // Only clear if selected thing is a TrackWaypoint layer or a sublayer + gint type = vik_treeview_item_get_type ( vtv, &iter ); + if ( type == VIK_TREEVIEW_TYPE_SUBLAYER || + VIK_LAYER(vik_treeview_item_get_pointer ( vtv, &iter ))->type == VIK_LAYER_TRW ) { - vik_treeview_item_unselect ( vtv, &iter ); - if ( vik_window_clear_highlight ( t->vw ) ) - draw_update ( t->vw ); - } + vik_treeview_item_unselect ( vtv, &iter ); + if ( vik_window_clear_highlight ( t->vw ) ) + draw_update ( t->vw ); + } + } + } + else { + // Something found - so enable movement + t->vw->select_move = TRUE; } } } @@ -2088,27 +2216,41 @@ static VikLayerToolFuncStatus selecttool_click (VikLayer *vl, GdkEventButton *ev return VIK_LAYER_TOOL_ACK; } -static VikLayerToolFuncStatus selecttool_move (VikLayer *vl, GdkEventButton *event, tool_ed_t *t) +static VikLayerToolFuncStatus selecttool_move (VikLayer *vl, GdkEventMotion *event, tool_ed_t *t) { - /* Only allow selection on primary button */ - if ( event->button == 1 ) { + if ( t->vw->select_move ) { // Don't care about vl here if ( t->vtl ) if ( vik_layer_get_interface(VIK_LAYER_TRW)->select_move ) - vik_layer_get_interface(VIK_LAYER_TRW)->select_move ( vl, event, t->vvp, t ); + vik_layer_get_interface(VIK_LAYER_TRW)->select_move ( vl, event, t->vvp, t ); } + else + // Optional Panning + if ( event->state & VIK_MOVE_MODIFIER ) + vik_window_pan_move ( t->vw, event ); + return VIK_LAYER_TOOL_ACK; } static VikLayerToolFuncStatus selecttool_release (VikLayer *vl, GdkEventButton *event, tool_ed_t *t) { - /* Only allow selection on primary button */ - if ( event->button == 1 ) { + if ( t->vw->select_move ) { // Don't care about vl here if ( t->vtl ) if ( vik_layer_get_interface(VIK_LAYER_TRW)->select_release ) - vik_layer_get_interface(VIK_LAYER_TRW)->select_release ( (VikLayer*)t->vtl, event, t->vvp, t ); + vik_layer_get_interface(VIK_LAYER_TRW)->select_release ( (VikLayer*)t->vtl, event, t->vvp, t ); } + + if ( event->button == 1 && (event->state & VIK_MOVE_MODIFIER) ) + vik_window_pan_release ( t->vw, event ); + + // Force pan off incase it was on + t->vw->pan_move = FALSE; + t->vw->pan_x = t->vw->pan_y = -1; + + // End of this select movement + t->vw->select_move = FALSE; + return VIK_LAYER_TOOL_ACK; } @@ -2148,17 +2290,6 @@ static void draw_pan_cb ( GtkAction *a, VikWindow *vw ) draw_update ( vw ); } -static void full_screen_cb ( GtkAction *a, VikWindow *vw ) -{ - GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/FullScreen" ); - g_assert(check_box); - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box)); - if ( state ) - gtk_window_fullscreen ( GTK_WINDOW(vw) ); - else - gtk_window_unfullscreen ( GTK_WINDOW(vw) ); -} - static void draw_zoom_cb ( GtkAction *a, VikWindow *vw ) { guint what = 128; @@ -2236,6 +2367,8 @@ static void center_changed_cb ( VikWindow *vw ) if ( action_forward ) { gtk_action_set_sensitive ( action_forward, vik_viewport_forward_available(vw->viking_vvp) ); } + + toolbar_action_set_sensitive ( vw->viking_vtb, "GoForward", vik_viewport_forward_available(vw->viking_vvp) ); } /** @@ -2330,11 +2463,190 @@ static void help_help_cb ( GtkAction *a, VikWindow *vw ) #endif /* WINDOWS */ } +static void toggle_side_panel ( VikWindow *vw ) +{ + vw->show_side_panel = !vw->show_side_panel; + if ( vw->show_side_panel ) + gtk_widget_show(GTK_WIDGET(vw->viking_vlp)); + else + gtk_widget_hide(GTK_WIDGET(vw->viking_vlp)); +} + +static void toggle_full_screen ( VikWindow *vw ) +{ + vw->show_full_screen = !vw->show_full_screen; + if ( vw->show_full_screen ) + gtk_window_fullscreen ( GTK_WINDOW(vw) ); + else + gtk_window_unfullscreen ( GTK_WINDOW(vw) ); +} + +static void toggle_statusbar ( VikWindow *vw ) +{ + vw->show_statusbar = !vw->show_statusbar; + if ( vw->show_statusbar ) + gtk_widget_show ( GTK_WIDGET(vw->viking_vs) ); + else + gtk_widget_hide ( GTK_WIDGET(vw->viking_vs) ); +} + +static void toggle_toolbar ( VikWindow *vw ) +{ + vw->show_toolbar = !vw->show_toolbar; + if ( vw->show_toolbar ) + gtk_widget_show ( toolbar_get_widget (vw->viking_vtb) ); + else + gtk_widget_hide ( toolbar_get_widget (vw->viking_vtb) ); +} + +static void toggle_main_menu ( VikWindow *vw ) +{ + vw->show_main_menu = !vw->show_main_menu; + if ( vw->show_main_menu ) + gtk_widget_show ( gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu" ) ); + else + gtk_widget_hide ( gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu" ) ); +} + +// Only for 'view' toggle menu widgets ATM. +GtkWidget *get_show_widget_by_name(VikWindow *vw, const gchar *name) +{ + g_return_val_if_fail(name != NULL, NULL); + + // ATM only FullScreen is *not* in SetShow path + gchar *path; + if ( g_strcmp0 ("FullScreen", name ) ) + path = g_strconcat("/ui/MainMenu/View/SetShow/", name, NULL); + else + path = g_strconcat("/ui/MainMenu/View/", name, NULL); + + GtkWidget *widget = gtk_ui_manager_get_widget(vw->uim, path); + g_free(path); + + return widget; +} + +static void tb_view_side_panel_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_side_panel; + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else + toggle_side_panel ( vw ); +} + +static void tb_full_screen_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_full_screen; + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else + toggle_full_screen ( vw ); +} + +static void tb_view_statusbar_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_statusbar; + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else + toggle_statusbar ( vw ); +} + +static void tb_view_toolbar_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_toolbar; + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else + toggle_toolbar ( vw ); +} + +static void tb_view_main_menu_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_main_menu; + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else + toggle_main_menu ( vw ); +} + +static void tb_set_draw_scale ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vik_viewport_get_draw_scale ( vw->viking_vvp ); + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else { + vik_viewport_set_draw_scale ( vw->viking_vvp, next_state ); + draw_update ( vw ); + } +} + +static void tb_set_draw_centermark ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vik_viewport_get_draw_centermark ( vw->viking_vvp ); + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else { + vik_viewport_set_draw_centermark ( vw->viking_vvp, next_state ); + draw_update ( vw ); + } +} + +static void tb_set_draw_highlight ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vik_viewport_get_draw_highlight ( vw->viking_vvp ); + GtkWidget *check_box = get_show_widget_by_name ( vw, gtk_action_get_name(a) ); + gboolean menu_state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); + if ( next_state != menu_state ) + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), next_state ); + else { + vik_viewport_set_draw_highlight ( vw->viking_vvp, next_state ); + draw_update ( vw ); + } +} + static void help_about_cb ( GtkAction *a, VikWindow *vw ) { a_dialog_about(GTK_WINDOW(vw)); } +static void help_cache_info_cb ( GtkAction *a, VikWindow *vw ) +{ + // NB: No i18n as this is just for debug + gint byte_size = a_mapcache_get_size(); + gchar *msg_sz = NULL; + gchar *msg = NULL; +#if GLIB_CHECK_VERSION(2,30,0) + msg_sz = g_format_size_full ( byte_size, G_FORMAT_SIZE_LONG_FORMAT ); +#else + msg_sz = g_format_size_for_display ( byte_size ); +#endif + msg = g_strdup_printf ( "Map Cache size is %s with %d items", msg_sz, a_mapcache_get_count()); + a_dialog_info_msg_extra ( GTK_WINDOW(vw), "%s", msg ); + g_free ( msg_sz ); + g_free ( msg ); +} + +static void back_forward_info_cb ( GtkAction *a, VikWindow *vw ) +{ + vik_viewport_show_centers ( vw->viking_vvp, GTK_WINDOW(vw) ); +} + static void menu_delete_layer_cb ( GtkAction *a, VikWindow *vw ) { if ( vik_layers_panel_get_selected ( vw->viking_vlp ) ) @@ -2346,51 +2658,79 @@ static void menu_delete_layer_cb ( GtkAction *a, VikWindow *vw ) a_dialog_info_msg ( GTK_WINDOW(vw), _("You must select a layer to delete.") ); } +static void full_screen_cb ( GtkAction *a, VikWindow *vw ) +{ + gboolean next_state = !vw->show_full_screen; + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, gtk_action_get_name(a) ); + if ( tbutton ) { + gboolean tb_state = gtk_toggle_tool_button_get_active ( tbutton ); + if ( next_state != tb_state ) + gtk_toggle_tool_button_set_active ( tbutton, next_state ); + else + toggle_full_screen ( vw ); + } + else + toggle_full_screen ( vw ); +} + static void view_side_panel_cb ( GtkAction *a, VikWindow *vw ) { - GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewSidePanel" ); - g_assert(check_box); - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box)); - if ( state ) - gtk_widget_show(GTK_WIDGET(vw->viking_vlp)); + gboolean next_state = !vw->show_side_panel; + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, gtk_action_get_name(a) ); + if ( tbutton ) { + gboolean tb_state = gtk_toggle_tool_button_get_active ( tbutton ); + if ( next_state != tb_state ) + gtk_toggle_tool_button_set_active ( tbutton, next_state ); + else + toggle_side_panel ( vw ); + } else - gtk_widget_hide(GTK_WIDGET(vw->viking_vlp)); + toggle_side_panel ( vw ); } static void view_statusbar_cb ( GtkAction *a, VikWindow *vw ) { - GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewStatusBar" ); - if ( !check_box ) - return; - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); - if ( state ) - gtk_widget_show ( GTK_WIDGET(vw->viking_vs) ); + gboolean next_state = !vw->show_statusbar; + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, gtk_action_get_name(a) ); + if ( tbutton ) { + gboolean tb_state = gtk_toggle_tool_button_get_active ( tbutton ); + if ( next_state != tb_state ) + gtk_toggle_tool_button_set_active ( tbutton, next_state ); + else + toggle_statusbar ( vw ); + } else - gtk_widget_hide ( GTK_WIDGET(vw->viking_vs) ); + toggle_statusbar ( vw ); } static void view_toolbar_cb ( GtkAction *a, VikWindow *vw ) { - GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewToolbar" ); - if ( !check_box ) - return; - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); - if ( state ) - gtk_widget_show ( GTK_WIDGET(vw->toolbar) ); + gboolean next_state = !vw->show_toolbar; + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, gtk_action_get_name(a) ); + if ( tbutton ) { + gboolean tb_state = gtk_toggle_tool_button_get_active ( tbutton ); + if ( next_state != tb_state ) + gtk_toggle_tool_button_set_active ( tbutton, next_state ); + else + toggle_toolbar ( vw ); + } else - gtk_widget_hide ( GTK_WIDGET(vw->toolbar) ); + toggle_toolbar ( vw ); } static void view_main_menu_cb ( GtkAction *a, VikWindow *vw ) { - GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewMainMenu" ); - if ( !check_box ) - return; - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box) ); - if ( !state ) - gtk_widget_hide ( gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu" ) ); + gboolean next_state = !vw->show_main_menu; + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, gtk_action_get_name(a) ); + if ( tbutton ) { + gboolean tb_state = gtk_toggle_tool_button_get_active ( tbutton ); + if ( next_state != tb_state ) + gtk_toggle_tool_button_set_active ( tbutton, next_state ); + else + toggle_main_menu ( vw ); + } else - gtk_widget_show ( gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu" ) ); + toggle_toolbar ( vw ); } /*************************************** @@ -2514,36 +2854,52 @@ void vik_window_enable_layer_tool ( VikWindow *vw, gint layer_id, gint tool_id ) gtk_action_activate ( gtk_action_group_get_action ( vw->action_group, vik_layer_get_interface(layer_id)->tools[tool_id].radioActionEntry.name ) ); } -/* this function gets called whenever a toolbar tool is clicked */ -static void menu_tool_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ) +// Be careful with usage - as it may trigger actions being continually alternately by the menu and toolbar items +// DON'T Use this from menu callback with toggle toolbar items!! +static void toolbar_sync ( VikWindow *vw, const gchar *name, gboolean state ) +{ + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, name ); + if ( tbutton ) { + // Causes toggle signal action to be raised. + gtk_toggle_tool_button_set_active ( tbutton, state ); + } +} + +/* this function gets called whenever a menu is clicked */ +// Note old is not used +static void menu_cb ( GtkAction *old, GtkAction *a, VikWindow *vw ) { + // Ensure Toolbar kept in sync + const gchar *name = gtk_action_get_name(a); + toolbar_sync ( vw, name, TRUE ); + /* White Magic, my friends ... White Magic... */ gint tool_id; - toolbox_activate(vw->vt, gtk_action_get_name(a)); + toolbox_activate(vw->vt, name); - vw->viewport_cursor = (GdkCursor *)toolbox_get_cursor(vw->vt, gtk_action_get_name(a)); + vw->viewport_cursor = (GdkCursor *)toolbox_get_cursor(vw->vt, name); if ( gtk_widget_get_window(GTK_WIDGET(vw->viking_vvp)) ) /* We set cursor, even if it is NULL: it resets to default */ gdk_window_set_cursor ( gtk_widget_get_window(GTK_WIDGET(vw->viking_vvp)), vw->viewport_cursor ); - if (!strcmp(gtk_action_get_name(a), "Pan")) { + if (!g_strcmp0(name, "Pan")) { vw->current_tool = TOOL_PAN; } - else if (!strcmp(gtk_action_get_name(a), "Zoom")) { + else if (!g_strcmp0(name, "Zoom")) { vw->current_tool = TOOL_ZOOM; } - else if (!strcmp(gtk_action_get_name(a), "Ruler")) { + else if (!g_strcmp0(name, "Ruler")) { vw->current_tool = TOOL_RULER; } - else if (!strcmp(gtk_action_get_name(a), "Select")) { + else if (!g_strcmp0(name, "Select")) { vw->current_tool = TOOL_SELECT; } else { VikLayerTypeEnum layer_id; for (layer_id=0; layer_idtools_count; tool_id++ ) { - if (!strcmp(vik_layer_get_interface(layer_id)->tools[tool_id].radioActionEntry.name, gtk_action_get_name(a))) { + if (!g_strcmp0(vik_layer_get_interface(layer_id)->tools[tool_id].radioActionEntry.name, name)) { vw->current_tool = TOOL_LAYER; vw->tool_layer_id = layer_id; vw->tool_tool_id = tool_id; @@ -2769,18 +3125,30 @@ void vik_window_open_file ( VikWindow *vw, const gchar *filename, gboolean chang vw->only_updating_coord_mode_ui = FALSE; vik_layers_panel_change_coord_mode ( vw->viking_vlp, vik_viewport_get_coord_mode ( vw->viking_vvp ) ); - - mode_button = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowScale" ); - g_assert ( mode_button ); - gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(mode_button),vik_viewport_get_draw_scale(vw->viking_vvp) ); - mode_button = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowCenterMark" ); - g_assert ( mode_button ); - gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(mode_button),vik_viewport_get_draw_centermark(vw->viking_vvp) ); - - mode_button = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowHighlight" ); - g_assert ( mode_button ); - gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(mode_button),vik_viewport_get_draw_highlight (vw->viking_vvp) ); + // Slightly long winded methods to align loaded viewport settings with the UI + // Since the rewrite for toolbar + menu actions + // there no longer exists a simple way to directly change the UI to a value for toggle settings + // it only supports toggling the existing setting (otherwise get infinite loops in trying to align tb+menu elements) + // Thus get state, compare them, if different then invert viewport setting and (re)sync the setting (via toggling) + gboolean vp_state_scale = vik_viewport_get_draw_scale ( vw->viking_vvp ); + gboolean ui_state_scale = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(get_show_widget_by_name(vw, "ShowScale")) ); + if ( vp_state_scale != ui_state_scale ) { + vik_viewport_set_draw_scale ( vw->viking_vvp, !vp_state_scale ); + toggle_draw_scale ( NULL, vw ); + } + gboolean vp_state_centermark = vik_viewport_get_draw_centermark ( vw->viking_vvp ); + gboolean ui_state_centermark = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(get_show_widget_by_name(vw, "ShowCenterMark")) ); + if ( vp_state_centermark != ui_state_centermark ) { + vik_viewport_set_draw_centermark ( vw->viking_vvp, !vp_state_centermark ); + toggle_draw_centermark ( NULL, vw ); + } + gboolean vp_state_highlight = vik_viewport_get_draw_highlight ( vw->viking_vvp ); + gboolean ui_state_highlight = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(get_show_widget_by_name(vw, "ShowHighlight")) ); + if ( vp_state_highlight != ui_state_highlight ) { + vik_viewport_set_draw_highlight ( vw->viking_vvp, !vp_state_highlight ); + toggle_draw_highlight ( NULL, vw ); + } } // NB No break, carry on to redraw //case LOAD_TYPE_OTHER_SUCCESS: @@ -3138,19 +3506,15 @@ static void file_properties_cb ( GtkAction *a, VikWindow *vw ) if ( g_stat ( vw->filename, &stat_buf ) == 0 ) { gchar time_buf[64]; strftime ( time_buf, sizeof(time_buf), "%c", gmtime((const time_t *)&stat_buf.st_mtime) ); - gchar *size = NULL; - gint byte_size = stat_buf.st_size; - // See http://en.wikipedia.org/wiki/Megabyte (and Kilobyte) - // hence using 1000 rather than 1024 - // so get output as per 'ls' or the Gtk file open dialog - if ( byte_size < 1000 ) - size = g_strdup_printf ( _("%d bytes"), byte_size ); - else if ( byte_size < 1000*1000 ) - size = g_strdup_printf ( _("%3.1f kB"), (gdouble)byte_size / 1000 ); - else - size = g_strdup_printf ( _("%3.1f MB"), (gdouble)byte_size / (1000*1000) ); - message = g_strdup_printf ( _("%s\n\n%s\n\n%s"), vw->filename, time_buf, size ); - g_free (size); + gchar *size = NULL; + gint byte_size = stat_buf.st_size; +#if GLIB_CHECK_VERSION(2,30,0) + size = g_format_size_full ( byte_size, G_FORMAT_SIZE_DEFAULT ); +#else + size = g_format_size_for_display ( byte_size ); +#endif + message = g_strdup_printf ( "%s\n\n%s\n\n%s", vw->filename, time_buf, size ); + g_free (size); } } else @@ -3331,6 +3695,12 @@ static void preferences_cb ( GtkAction *a, VikWindow *vw ) // Update all windows g_slist_foreach ( window_list, (GFunc) preferences_change_update, NULL ); } + + // Ensure TZ Lookup initialized + if ( a_vik_get_time_ref_frame() == VIK_TIME_REF_WORLD ) + vu_setup_lat_lon_tz_lookup(); + + toolbar_apply_settings ( vw->viking_vtb, vw->main_vbox, vw->menu_hbox, TRUE ); } static void default_location_cb ( GtkAction *a, VikWindow *vw ) @@ -3604,6 +3974,9 @@ static void draw_to_image_file_total_area_cb (GtkSpinButton *spinbutton, gpointe case VIK_UNITS_DISTANCE_MILES: label_text = g_strdup_printf ( _("Total area: %ldm x %ldm (%.3f sq. miles)"), (glong)w, (glong)h, (w*h/2589988.11)); break; + case VIK_UNITS_DISTANCE_NAUTICAL_MILES: + label_text = g_strdup_printf ( _("Total area: %ldm x %ldm (%.3f sq. NM)"), (glong)w, (glong)h, (w*h/(1852.0*1852.0))); + break; default: label_text = g_strdup_printf ("Just to keep the compiler happy"); g_critical("Houston, we've had a problem. distance=%d", dist_units); @@ -3853,17 +4226,22 @@ static void print_cb ( GtkAction *a, VikWindow *vw ) /* really a misnomer: changes coord mode (actual coordinates) AND/OR draw mode (viewport only) */ static void window_change_coord_mode_cb ( GtkAction *old_a, GtkAction *a, VikWindow *vw ) { + const gchar *name = gtk_action_get_name(a); + GtkToggleToolButton *tbutton = (GtkToggleToolButton *)toolbar_get_widget_by_name ( vw->viking_vtb, name ); + if ( tbutton ) + gtk_toggle_tool_button_set_active ( tbutton, TRUE ); + VikViewportDrawMode drawmode; - if (!strcmp(gtk_action_get_name(a), "ModeUTM")) { + if (!g_strcmp0(name, "ModeUTM")) { drawmode = VIK_VIEWPORT_DRAWMODE_UTM; } - else if (!strcmp(gtk_action_get_name(a), "ModeLatLon")) { + else if (!g_strcmp0(name, "ModeLatLon")) { drawmode = VIK_VIEWPORT_DRAWMODE_LATLON; } - else if (!strcmp(gtk_action_get_name(a), "ModeExpedia")) { + else if (!g_strcmp0(name, "ModeExpedia")) { drawmode = VIK_VIEWPORT_DRAWMODE_EXPEDIA; } - else if (!strcmp(gtk_action_get_name(a), "ModeMercator")) { + else if (!g_strcmp0(name, "ModeMercator")) { drawmode = VIK_VIEWPORT_DRAWMODE_MERCATOR; } else { @@ -3888,30 +4266,36 @@ static void window_change_coord_mode_cb ( GtkAction *old_a, GtkAction *a, VikWin } } -static void set_draw_scale ( GtkAction *a, VikWindow *vw ) +static void toggle_draw_scale ( GtkAction *a, VikWindow *vw ) { + gboolean state = !vik_viewport_get_draw_scale ( vw->viking_vvp ); GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowScale" ); - g_assert(check_box); - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box)); + if ( !check_box ) + return; + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), state ); vik_viewport_set_draw_scale ( vw->viking_vvp, state ); draw_update ( vw ); } -static void set_draw_centermark ( GtkAction *a, VikWindow *vw ) +static void toggle_draw_centermark ( GtkAction *a, VikWindow *vw ) { + gboolean state = !vik_viewport_get_draw_centermark ( vw->viking_vvp ); GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowCenterMark" ); - g_assert(check_box); - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box)); + if ( !check_box ) + return; + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), state ); vik_viewport_set_draw_centermark ( vw->viking_vvp, state ); draw_update ( vw ); } -static void set_draw_highlight ( GtkAction *a, VikWindow *vw ) +static void toggle_draw_highlight ( GtkAction *a, VikWindow *vw ) { + gboolean state = !vik_viewport_get_draw_highlight ( vw->viking_vvp ); GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ShowHighlight" ); - g_assert(check_box); - gboolean state = gtk_check_menu_item_get_active ( GTK_CHECK_MENU_ITEM(check_box)); - vik_viewport_set_draw_highlight ( vw->viking_vvp, state ); + if ( !check_box ) + return; + gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), state ); + vik_viewport_set_draw_highlight ( vw->viking_vvp, state ); draw_update ( vw ); } @@ -3948,7 +4332,6 @@ static void set_highlight_color ( GtkAction *a, VikWindow *vw ) } - /*********************************************************************************************** ** GUI Creation ***********************************************************************************************/ @@ -3993,7 +4376,7 @@ static GtkActionEntry entries[] = { { "SaveAs", GTK_STOCK_SAVE_AS, N_("Save _As..."), NULL, N_("Save the file under different name"), (GCallback)save_file_as }, { "FileProperties", NULL, N_("Properties..."), NULL, N_("File Properties"), (GCallback)file_properties_cb }, { "GenImg", GTK_STOCK_CLEAR, N_("_Generate Image File..."), NULL, N_("Save a snapshot of the workspace into a file"), (GCallback)draw_to_image_file_cb }, - { "GenImgDir", GTK_STOCK_DND_MULTIPLE, N_("Generate _Directory of Images..."), NULL, N_("FIXME:IMGDIR"), (GCallback)draw_to_image_dir_cb }, + { "GenImgDir", GTK_STOCK_DND_MULTIPLE, N_("Generate _Directory of Images..."), NULL, N_("Generate _Directory of Images"), (GCallback)draw_to_image_dir_cb }, { "Print", GTK_STOCK_PRINT, N_("_Print..."), NULL, N_("Print maps"), (GCallback)print_cb }, { "Exit", GTK_STOCK_QUIT, N_("E_xit"), "W", N_("Exit the program"), (GCallback)window_close }, { "SaveExit", GTK_STOCK_QUIT, N_("Save and Exit"), NULL, N_("Save and Exit the program"), (GCallback)save_file_and_exit }, @@ -4005,31 +4388,36 @@ static GtkActionEntry entries[] = { { "GotoLL", GTK_STOCK_JUMP_TO, N_("_Go to Lat/Lon..."), NULL, N_("Go to arbitrary lat/lon coordinate"), (GCallback)draw_goto_cb }, { "GotoUTM", GTK_STOCK_JUMP_TO, N_("Go to UTM..."), NULL, N_("Go to arbitrary UTM coordinate"), (GCallback)draw_goto_cb }, { "Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "F5", N_("Refresh any maps displayed"), (GCallback)draw_refresh_cb }, - { "SetHLColor",GTK_STOCK_SELECT_COLOR, N_("Set _Highlight Color..."), NULL, NULL, (GCallback)set_highlight_color }, - { "SetBGColor",GTK_STOCK_SELECT_COLOR, N_("Set Bac_kground Color..."), NULL, NULL, (GCallback)set_bg_color }, - { "ZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _In"), "plus", NULL, (GCallback)draw_zoom_cb }, - { "ZoomOut", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "minus", NULL, (GCallback)draw_zoom_cb }, - { "ZoomTo", GTK_STOCK_ZOOM_FIT, N_("Zoom _To..."), "Z", NULL, (GCallback)zoom_to_cb }, + { "SetHLColor",GTK_STOCK_SELECT_COLOR, N_("Set _Highlight Color..."), NULL, N_("Set Highlight Color"), (GCallback)set_highlight_color }, + { "SetBGColor",GTK_STOCK_SELECT_COLOR, N_("Set Bac_kground Color..."), NULL, N_("Set Background Color"), (GCallback)set_bg_color }, + { "ZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _In"), "plus", N_("Zoom In"), (GCallback)draw_zoom_cb }, + { "ZoomOut", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "minus", N_("Zoom Out"), (GCallback)draw_zoom_cb }, + { "ZoomTo", GTK_STOCK_ZOOM_FIT, N_("Zoom _To..."), "Z", N_("Zoom To"), (GCallback)zoom_to_cb }, { "PanNorth", NULL, N_("Pan _North"), "Up", NULL, (GCallback)draw_pan_cb }, { "PanEast", NULL, N_("Pan _East"), "Right", NULL, (GCallback)draw_pan_cb }, { "PanSouth", NULL, N_("Pan _South"), "Down", NULL, (GCallback)draw_pan_cb }, { "PanWest", NULL, N_("Pan _West"), "Left", NULL, (GCallback)draw_pan_cb }, - { "BGJobs", GTK_STOCK_EXECUTE, N_("Background _Jobs"), NULL, NULL, (GCallback)a_background_show_window }, + { "BGJobs", GTK_STOCK_EXECUTE, N_("Background _Jobs"), NULL, N_("Background Jobs"), (GCallback)a_background_show_window }, - { "Cut", GTK_STOCK_CUT, N_("Cu_t"), NULL, NULL, (GCallback)menu_cut_layer_cb }, - { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL, NULL, (GCallback)menu_copy_layer_cb }, - { "Paste", GTK_STOCK_PASTE, N_("_Paste"), NULL, NULL, (GCallback)menu_paste_layer_cb }, - { "Delete", GTK_STOCK_DELETE, N_("_Delete"), NULL, NULL, (GCallback)menu_delete_layer_cb }, + { "Cut", GTK_STOCK_CUT, N_("Cu_t"), NULL, N_("Cut selected layer"), (GCallback)menu_cut_layer_cb }, + { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL, N_("Copy selected layer"), (GCallback)menu_copy_layer_cb }, + { "Paste", GTK_STOCK_PASTE, N_("_Paste"), NULL, N_("Paste layer into selected container layer or otherwise above selected layer"), (GCallback)menu_paste_layer_cb }, + { "Delete", GTK_STOCK_DELETE, N_("_Delete"), NULL, N_("Remove selected layer"), (GCallback)menu_delete_layer_cb }, { "DeleteAll", NULL, N_("Delete All"), NULL, NULL, (GCallback)clear_cb }, { "CopyCentre",NULL, N_("Copy Centre _Location"), "h", NULL, (GCallback)menu_copy_centre_cb }, { "MapCacheFlush",NULL, N_("_Flush Map Cache"), NULL, NULL, (GCallback)mapcache_flush_cb }, { "SetDefaultLocation", GTK_STOCK_GO_FORWARD, N_("_Set the Default Location"), NULL, N_("Set the Default Location to the current position"),(GCallback)default_location_cb }, - { "Preferences",GTK_STOCK_PREFERENCES, N_("_Preferences"), NULL, NULL, (GCallback)preferences_cb }, + { "Preferences",GTK_STOCK_PREFERENCES, N_("_Preferences"), NULL, N_("Program Preferences"), (GCallback)preferences_cb }, { "LayerDefaults",GTK_STOCK_PROPERTIES, N_("_Layer Defaults"), NULL, NULL, NULL }, - { "Properties",GTK_STOCK_PROPERTIES, N_("_Properties"), NULL, NULL, (GCallback)menu_properties_cb }, + { "Properties",GTK_STOCK_PROPERTIES, N_("_Properties"), NULL, N_("Layer Properties"), (GCallback)menu_properties_cb }, - { "HelpEntry", GTK_STOCK_HELP, N_("_Help"), "F1", NULL, (GCallback)help_help_cb }, - { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, (GCallback)help_about_cb }, + { "HelpEntry", GTK_STOCK_HELP, N_("_Help"), "F1", N_("Help"), (GCallback)help_help_cb }, + { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), (GCallback)help_about_cb }, +}; + +static GtkActionEntry debug_entries[] = { + { "MapCacheInfo", NULL, "_Map Cache Info", NULL, NULL, (GCallback)help_cache_info_cb }, + { "BackForwardInfo", NULL, "_Back/Forward Info", NULL, NULL, (GCallback)back_forward_info_cb }, }; static GtkActionEntry entries_gpsbabel[] = { @@ -4041,18 +4429,17 @@ static GtkActionEntry entries_geojson[] = { }; /* Radio items */ -/* FIXME use VIEWPORT_DRAWMODE values */ static GtkRadioActionEntry mode_entries[] = { - { "ModeUTM", NULL, N_("_UTM Mode"), "u", NULL, 0 }, - { "ModeExpedia", NULL, N_("_Expedia Mode"), "e", NULL, 1 }, - { "ModeMercator", NULL, N_("_Mercator Mode"), "m", NULL, 4 }, - { "ModeLatLon", NULL, N_("Lat_/Lon Mode"), "l", NULL, 5 }, + { "ModeUTM", NULL, N_("_UTM Mode"), "u", NULL, VIK_VIEWPORT_DRAWMODE_UTM }, + { "ModeExpedia", NULL, N_("_Expedia Mode"), "e", NULL, VIK_VIEWPORT_DRAWMODE_EXPEDIA }, + { "ModeMercator", NULL, N_("_Mercator Mode"), "m", NULL, VIK_VIEWPORT_DRAWMODE_MERCATOR }, + { "ModeLatLon", NULL, N_("Lat_/Lon Mode"), "l", NULL, VIK_VIEWPORT_DRAWMODE_LATLON }, }; static GtkToggleActionEntry toggle_entries[] = { - { "ShowScale", NULL, N_("Show _Scale"), "F5", N_("Show Scale"), (GCallback)set_draw_scale, TRUE }, - { "ShowCenterMark", NULL, N_("Show _Center Mark"), "F6", N_("Show Center Mark"), (GCallback)set_draw_centermark, TRUE }, - { "ShowHighlight", GTK_STOCK_UNDERLINE, N_("Show _Highlight"), "F7", N_("Show Highlight"), (GCallback)set_draw_highlight, TRUE }, + { "ShowScale", NULL, N_("Show _Scale"), "F5", N_("Show Scale"), (GCallback)toggle_draw_scale, TRUE }, + { "ShowCenterMark", NULL, N_("Show _Center Mark"), "F6", N_("Show Center Mark"), (GCallback)toggle_draw_centermark, TRUE }, + { "ShowHighlight", GTK_STOCK_UNDERLINE, N_("Show _Highlight"), "F7", N_("Show Highlight"), (GCallback)toggle_draw_highlight, TRUE }, { "FullScreen", GTK_STOCK_FULLSCREEN, N_("_Full Screen"), "F11", N_("Activate full screen mode"), (GCallback)full_screen_cb, FALSE }, { "ViewSidePanel", GTK_STOCK_INDEX, N_("Show Side _Panel"), "F9", N_("Show Side Panel"), (GCallback)view_side_panel_cb, TRUE }, { "ViewStatusBar", NULL, N_("Show Status_bar"), "F12", N_("Show Statusbar"), (GCallback)view_statusbar_cb, TRUE }, @@ -4060,6 +4447,18 @@ static GtkToggleActionEntry toggle_entries[] = { { "ViewMainMenu", NULL, N_("Show _Menu"), "F4", N_("Show Menu"), (GCallback)view_main_menu_cb, TRUE }, }; +// This must match the toggle entries order above +static gpointer toggle_entries_toolbar_cb[] = { + (GCallback)tb_set_draw_scale, + (GCallback)tb_set_draw_centermark, + (GCallback)tb_set_draw_highlight, + (GCallback)tb_full_screen_cb, + (GCallback)tb_view_side_panel_cb, + (GCallback)tb_view_statusbar_cb, + (GCallback)tb_view_toolbar_cb, + (GCallback)tb_view_main_menu_cb, +}; + #include "menu.xml.h" static void window_create_ui( VikWindow *window ) { @@ -4081,6 +4480,11 @@ static void window_create_ui( VikWindow *window ) toolbox_add_tool(window->vt, &pan_tool, TOOL_LAYER_TYPE_NONE); toolbox_add_tool(window->vt, &select_tool, TOOL_LAYER_TYPE_NONE); + toolbar_action_tool_entry_register ( window->viking_vtb, &pan_tool.radioActionEntry ); + toolbar_action_tool_entry_register ( window->viking_vtb, &zoom_tool.radioActionEntry ); + toolbar_action_tool_entry_register ( window->viking_vtb, &ruler_tool.radioActionEntry ); + toolbar_action_tool_entry_register ( window->viking_vtb, &select_tool.radioActionEntry ); + error = NULL; if (!(mid = gtk_ui_manager_add_ui_from_string (uim, menu_xml, -1, &error))) { g_error_free (error); @@ -4092,6 +4496,34 @@ static void window_create_ui( VikWindow *window ) gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), window); gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), window); gtk_action_group_add_radio_actions (action_group, mode_entries, G_N_ELEMENTS (mode_entries), 4, (GCallback)window_change_coord_mode_cb, window); + if ( vik_debug ) { + if ( gtk_ui_manager_add_ui_from_string ( uim, + "" + "" + "" + "", + -1, NULL ) ) { + gtk_action_group_add_actions (action_group, debug_entries, G_N_ELEMENTS (debug_entries), window); + } + } + + for ( i=0; i < G_N_ELEMENTS (entries); i++ ) { + if ( entries[i].callback ) + toolbar_action_entry_register ( window->viking_vtb, &entries[i] ); + } + + if ( G_N_ELEMENTS (toggle_entries) != G_N_ELEMENTS (toggle_entries_toolbar_cb) ) { + g_print ( "Broken entries definitions\n" ); + exit (1); + } + for ( i=0; i < G_N_ELEMENTS (toggle_entries); i++ ) { + if ( toggle_entries_toolbar_cb[i] ) + toolbar_action_toggle_entry_register ( window->viking_vtb, &toggle_entries[i], toggle_entries_toolbar_cb[i] ); + } + + for ( i=0; i < G_N_ELEMENTS (mode_entries); i++ ) { + toolbar_action_mode_entry_register ( window->viking_vtb, &mode_entries[i] ); + } // Use this to see if GPSBabel is available: if ( a_babel_available () ) { @@ -4149,7 +4581,6 @@ static void window_create_ui( VikWindow *window ) if ( vik_layer_get_interface(i)->tools_count ) { gtk_ui_manager_add_ui(uim, mid, "/ui/MainMenu/Tools/", vik_layer_get_interface(i)->name, NULL, GTK_UI_MANAGER_SEPARATOR, FALSE); - gtk_ui_manager_add_ui(uim, mid, "/ui/MainToolbar/ToolItems/", vik_layer_get_interface(i)->name, NULL, GTK_UI_MANAGER_SEPARATOR, FALSE); } // Further tool copying for to apply to the UI, also apply menu UI setup @@ -4162,12 +4593,9 @@ static void window_create_ui( VikWindow *window ) vik_layer_get_interface(i)->tools[j].radioActionEntry.label, vik_layer_get_interface(i)->tools[j].radioActionEntry.name, GTK_UI_MANAGER_MENUITEM, FALSE); - gtk_ui_manager_add_ui(uim, mid, "/ui/MainToolbar/ToolItems", - vik_layer_get_interface(i)->tools[j].radioActionEntry.label, - vik_layer_get_interface(i)->tools[j].radioActionEntry.name, - GTK_UI_MANAGER_TOOLITEM, FALSE); toolbox_add_tool(window->vt, &(vik_layer_get_interface(i)->tools[j]), i); + toolbar_action_tool_entry_register ( window->viking_vtb, &(vik_layer_get_interface(i)->tools[j].radioActionEntry) ); *radio = vik_layer_get_interface(i)->tools[j].radioActionEntry; // Overwrite with actual number to use @@ -4196,7 +4624,7 @@ static void window_create_ui( VikWindow *window ) } g_object_unref (icon_factory); - gtk_action_group_add_radio_actions(action_group, tools, ntools, 0, (GCallback)menu_tool_cb, window); + gtk_action_group_add_radio_actions(action_group, tools, ntools, 0, (GCallback)menu_cb, window); g_free(tools); gtk_ui_manager_insert_action_group (uim, action_group, 0); @@ -4373,7 +4801,12 @@ gboolean vik_window_clear_highlight ( VikWindow *vw ) return need_redraw; } +/** + * May return NULL if the window no longer exists + */ GThread *vik_window_get_thread ( VikWindow *vw ) { - return vw->thread; + if ( vw ) + return vw->thread; + return NULL; }