X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/b9f777e49bfc5880152c9c9b6f3e33d1a504fa31..70177381ae2b6540e92c504833aeb546c38dd54b:/src/vikwindow.c?ds=sidebyside diff --git a/src/vikwindow.c b/src/vikwindow.c index 798983b2..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 @@ -29,11 +29,13 @@ #include "background.h" #include "acquire.h" #include "datasources.h" +#include "geojson.h" #include "vikgoto.h" #include "dems.h" #include "mapcache.h" #include "print.h" #include "preferences.h" +#include "toolbar.h" #include "viklayer_defaults.h" #include "icons/icons.h" #include "vikexttools.h" @@ -41,6 +43,8 @@ #include "garminsymbols.h" #include "vikmapslayer.h" #include "geonamessearch.h" +#include "vikutils.h" +#include "dir.h" #ifdef HAVE_STDLIB_H #include @@ -111,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 ); @@ -130,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); @@ -154,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 @@ -171,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 @@ -284,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 { @@ -350,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 ); } @@ -453,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, @@ -502,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 ); } } } @@ -523,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); } @@ -551,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 ); @@ -568,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++) @@ -579,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; @@ -685,19 +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(); @@ -706,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; @@ -740,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 ); @@ -778,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 ); @@ -821,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 ); @@ -835,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) ); @@ -844,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 () @@ -897,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 ); @@ -971,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) ) { @@ -980,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; @@ -1156,11 +1252,34 @@ static void vik_window_pan_move (VikWindow *vw, GdkEventMotion *event) } } +/** + * get_location_strings: + * + * Utility function to get positional strings for the given location + * lat and lon strings will get allocated and so need to be freed after use + */ +static void get_location_strings ( VikWindow *vw, struct UTM utm, gchar **lat, gchar **lon ) +{ + if ( vik_viewport_get_drawmode ( vw->viking_vvp ) == VIK_VIEWPORT_DRAWMODE_UTM ) { + // Reuse lat for the first part (Zone + N or S, and lon for the second part (easting and northing) of a UTM format: + // ZONE[N|S] EASTING NORTHING + *lat = g_malloc(4*sizeof(gchar)); + // NB zone is stored in a char but is an actual number + g_snprintf (*lat, 4, "%d%c", utm.zone, utm.letter); + *lon = g_malloc(16*sizeof(gchar)); + g_snprintf (*lon, 16, "%d %d", (gint)utm.easting, (gint)utm.northing); + } + else { + struct LatLon ll; + a_coords_utm_to_latlon ( &utm, &ll ); + a_coords_latlon_to_string ( &ll, lat, lon ); + } +} + static void draw_mouse_motion (VikWindow *vw, GdkEventMotion *event) { static VikCoord coord; static struct UTM utm; - static struct LatLon ll; #define BUFFER_SIZE 50 static char pointer_buf[BUFFER_SIZE]; gchar *lat = NULL, *lon = NULL; @@ -1180,19 +1299,7 @@ static void draw_mouse_motion (VikWindow *vw, GdkEventMotion *event) vik_viewport_screen_to_coord ( vw->viking_vvp, event->x, event->y, &coord ); vik_coord_to_utm ( &coord, &utm ); - if ( vik_viewport_get_drawmode ( vw->viking_vvp ) == VIK_VIEWPORT_DRAWMODE_UTM ) { - // Reuse lat for the first part (Zone + N or S, and lon for the second part (easting and northing) of a UTM format: - // ZONE[N|S] EASTING NORTHING - lat = g_malloc(4*sizeof(gchar)); - // NB zone is stored in a char but is an actual number - g_snprintf (lat, 4, "%d%c", utm.zone, utm.letter); - lon = g_malloc(16*sizeof(gchar)); - g_snprintf (lon, 16, "%d %d", (gint)utm.easting, (gint)utm.northing); - } - else { - a_coords_utm_to_latlon ( &utm, &ll ); - a_coords_latlon_to_string ( &ll, &lat, &lon ); - } + get_location_strings ( vw, utm, &lat, &lon ); /* Change interpolate method according to scale */ zoom = vik_viewport_get_zoom(vw->viking_vvp); @@ -1433,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: @@ -1533,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; @@ -1610,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); @@ -2031,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; } } } @@ -2075,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; } @@ -2135,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; @@ -2223,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) ); } /** @@ -2317,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 ) ) @@ -2333,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 ); } /*************************************** @@ -2501,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; @@ -2652,7 +3021,10 @@ static void setup_recent_files (VikWindow *self) G_CALLBACK (on_activate_recent_item), (gpointer) self); } -static void update_recently_used_document(const gchar *filename) +/* + * + */ +static void update_recently_used_document (VikWindow *vw, const gchar *filename) { /* Update Recently Used Document framework */ GtkRecentManager *manager = gtk_recent_manager_get_default(); @@ -2673,7 +3045,9 @@ static void update_recently_used_document(const gchar *filename) recent_data->is_private = FALSE; if (!gtk_recent_manager_add_full (manager, uri, recent_data)) { - g_warning (_("Unable to add '%s' to the list of recently used documents"), uri); + gchar *msg = g_strdup_printf (_("Unable to add '%s' to the list of recently used documents"), uri); + vik_statusbar_set_message ( vw->viking_vs, VIK_STATUSBAR_INFO, msg ); + g_free ( msg ); } g_free (uri); @@ -2751,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: @@ -2770,7 +3156,7 @@ void vik_window_open_file ( VikWindow *vw, const gchar *filename, gboolean chang success = TRUE; // When LOAD_TYPE_OTHER_SUCCESS *only*, this will maintain the existing Viking project restore_original_filename = ! restore_original_filename; - update_recently_used_document(filename); + update_recently_used_document (vw, filename); draw_update ( vw ); break; } @@ -2967,7 +3353,7 @@ static gboolean window_save ( VikWindow *vw ) if ( a_file_save ( vik_layers_panel_get_top_layer ( vw->viking_vlp ), vw->viking_vvp, vw->filename ) ) { - update_recently_used_document ( vw->filename ); + update_recently_used_document ( vw, vw->filename ); } else { @@ -3120,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 @@ -3146,64 +3528,70 @@ static void file_properties_cb ( GtkAction *a, VikWindow *vw ) g_free ( message ); } +static void my_acquire ( VikWindow *vw, VikDataSourceInterface *datasource ) +{ + vik_datasource_mode_t mode = datasource->mode; + if ( mode == VIK_DATASOURCE_AUTO_LAYER_MANAGEMENT ) + mode = VIK_DATASOURCE_CREATENEWLAYER; + a_acquire ( vw, vw->viking_vlp, vw->viking_vvp, mode, datasource, NULL, NULL ); +} + static void acquire_from_gps ( GtkAction *a, VikWindow *vw ) { - // Via the file menu, acquiring from a GPS makes a new layer - // this has always been the way (not entirely sure if this was the real intention!) - // thus maintain the behaviour ATM. - // Hence explicit setting here (as the value may be changed elsewhere) - vik_datasource_gps_interface.mode = VIK_DATASOURCE_CREATENEWLAYER; - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gps_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_gps_interface ); } static void acquire_from_file ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_file_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_file_interface ); +} + +static void acquire_from_geojson ( GtkAction *a, VikWindow *vw ) +{ + my_acquire ( vw, &vik_datasource_geojson_interface ); } static void acquire_from_routing ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_routing_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_routing_interface ); } #ifdef VIK_CONFIG_OPENSTREETMAP static void acquire_from_osm ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_osm_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_osm_interface ); } static void acquire_from_my_osm ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_osm_my_traces_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_osm_my_traces_interface ); } #endif #ifdef VIK_CONFIG_GEOCACHES static void acquire_from_gc ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gc_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_gc_interface ); } #endif #ifdef VIK_CONFIG_GEOTAG static void acquire_from_geotag ( GtkAction *a, VikWindow *vw ) { - vik_datasource_geotag_interface.mode = VIK_DATASOURCE_CREATENEWLAYER; - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_geotag_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_geotag_interface ); } #endif #ifdef VIK_CONFIG_GEONAMES static void acquire_from_wikipedia ( GtkAction *a, VikWindow *vw ) { - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_wikipedia_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_wikipedia_interface ); } #endif static void acquire_from_url ( GtkAction *a, VikWindow *vw ) { - vik_datasource_url_interface.mode = VIK_DATASOURCE_CREATENEWLAYER; - a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_url_interface, NULL, NULL ); + my_acquire ( vw, &vik_datasource_url_interface ); } static void goto_default_location( GtkAction *a, VikWindow *vw) @@ -3227,6 +3615,38 @@ static void mapcache_flush_cb ( GtkAction *a, VikWindow *vw ) a_mapcache_flush(); } +static void menu_copy_centre_cb ( GtkAction *a, VikWindow *vw ) +{ + const VikCoord* coord; + struct UTM utm; + gchar *lat = NULL, *lon = NULL; + + coord = vik_viewport_get_center ( vw->viking_vvp ); + vik_coord_to_utm ( coord, &utm ); + + gboolean full_format = FALSE; + a_settings_get_boolean ( VIK_SETTINGS_WIN_COPY_CENTRE_FULL_FORMAT, &full_format ); + + if ( full_format ) + // Bells & Whistles - may include degrees, minutes and second symbols + get_location_strings ( vw, utm, &lat, &lon ); + else { + // Simple x.xx y.yy format + struct LatLon ll; + a_coords_utm_to_latlon ( &utm, &ll ); + lat = g_strdup_printf ( "%.6f", ll.lat ); + lon = g_strdup_printf ( "%.6f", ll.lon ); + } + + gchar *msg = g_strdup_printf ( "%s %s", lat, lon ); + g_free (lat); + g_free (lon); + + a_clipboard_copy ( VIK_CLIPBOARD_DATA_TEXT, 0, 0, 0, msg, NULL ); + + g_free ( msg ); +} + static void layer_defaults_cb ( GtkAction *a, VikWindow *vw ) { gchar **texts = g_strsplit ( gtk_action_get_name(a), "Layer", 0 ); @@ -3275,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 ) @@ -3480,7 +3906,9 @@ static void save_image_dir ( VikWindow *vw, const gchar *fn, guint w, guint h, g gdk_pixbuf_save ( pixbuf_to_save, name_of_file, save_as_png ? "png" : "jpeg", &error, NULL ); if (error) { - g_warning("Unable to write to file %s: %s", name_of_file, error->message ); + gchar *msg = g_strdup_printf (_("Unable to write to file %s: %s"), name_of_file, error->message ); + vik_statusbar_set_message ( vw->viking_vs, VIK_STATUSBAR_INFO, msg ); + g_free ( msg ); g_error_free (error); } @@ -3546,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); @@ -3795,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 { @@ -3830,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 ); } @@ -3890,7 +4332,6 @@ static void set_highlight_color ( GtkAction *a, VikWindow *vw ) } - /*********************************************************************************************** ** GUI Creation ***********************************************************************************************/ @@ -3935,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 }, @@ -3947,49 +4388,58 @@ 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", N_("Help"), (GCallback)help_help_cb }, + { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), (GCallback)help_about_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 }, +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[] = { { "ExportKML", NULL, N_("_KML..."), NULL, N_("Export as KML"), (GCallback)export_to_kml }, }; +static GtkActionEntry entries_geojson[] = { + { "AcquireGeoJSON", NULL, N_("Import Geo_JSON File..."), NULL, N_("Import GeoJSON file"), (GCallback)acquire_from_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 }, @@ -3997,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 ) { @@ -4018,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); @@ -4029,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 () ) { @@ -4039,6 +4534,14 @@ static void window_create_ui( VikWindow *window ) gtk_action_group_add_actions ( action_group, entries_gpsbabel, G_N_ELEMENTS (entries_gpsbabel), window ); } + // GeoJSON import capability + if ( g_find_program_in_path ( a_geojson_program_import() ) ) { + if ( gtk_ui_manager_add_ui_from_string ( uim, + "", + -1, &error ) ) + gtk_action_group_add_actions ( action_group, entries_geojson, G_N_ELEMENTS (entries_geojson), window ); + } + icon_factory = gtk_icon_factory_new (); gtk_icon_factory_add_default (icon_factory); @@ -4078,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 @@ -4091,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 @@ -4125,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); @@ -4302,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; }