X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/50a14534a51f892500ee82f867e8ab2f85b936ae..70177381ae2b6540e92c504833aeb546c38dd54b:/src/vikstatus.c?ds=inline diff --git a/src/vikstatus.c b/src/vikstatus.c index 3ea89267..cbf1afbe 100644 --- a/src/vikstatus.c +++ b/src/vikstatus.c @@ -2,6 +2,8 @@ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * * Copyright (C) 2003-2005, Evan Battaglia + * Copyright (C) 2011, Rob Norris + * Copyright (C) 2012, Guilhem Bonnefille * * 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 @@ -19,85 +21,172 @@ * */ -/* gtk status bars: just plain dumb. this file -shouldn't have to exist. */ +/* gtk status bars: just plain dumb. this file shouldn't have to exist. + NB as of gtk 2.18 there are 'info bars' that could be useful... */ #include +#include + +#include + #include "vikstatus.h" +#include "background.h" -#define STATUS_COUNT 5 +enum +{ + CLICKED, + LAST_SIGNAL +}; struct _VikStatusbar { - GtkStatusbar parent; - gint num_extra_bars; - GtkWidget *status[STATUS_COUNT-1]; - gboolean empty[STATUS_COUNT]; + GtkHBox hbox; + GtkWidget *status[VIK_STATUSBAR_NUM_TYPES]; + gboolean empty[VIK_STATUSBAR_NUM_TYPES]; }; -GType vik_statusbar_get_type (void) -{ - static GType vs_type = 0; +G_DEFINE_TYPE (VikStatusbar, vik_statusbar, GTK_TYPE_HBOX) - if (!vs_type) - { - static const GTypeInfo vs_info = - { - sizeof (VikStatusbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - NULL, /* class init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (VikStatusbar), - 0, - NULL /* instance init */ - }; - vs_type = g_type_register_static ( GTK_TYPE_STATUSBAR, "VikStatusbar", &vs_info, 0 ); - } +static guint vik_statusbar_signals[LAST_SIGNAL] = { 0 }; - return vs_type; +static gint +forward_signal (GObject *object, gpointer user_data) +{ + gint item = GPOINTER_TO_INT (g_object_get_data ( object, "type" )); + VikStatusbar *vs = VIK_STATUSBAR (user_data); + + // Clicking on the items field will bring up the background jobs window + if ( item == VIK_STATUSBAR_ITEMS ) + a_background_show_window(); + else if ( item == VIK_STATUSBAR_INFO ) + // Clear current info message + vik_statusbar_set_message ( vs, VIK_STATUSBAR_INFO, "" ); + else + g_signal_emit (G_OBJECT (vs), + vik_statusbar_signals[CLICKED], 0, + item); + + return TRUE; } -VikStatusbar *vik_statusbar_new () +static void +vik_statusbar_class_init (VikStatusbarClass *klass) { - VikStatusbar *vs = VIK_STATUSBAR ( g_object_new ( VIK_STATUSBAR_TYPE, NULL ) ); - gint i; - - gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs), FALSE ); + vik_statusbar_signals[CLICKED] = + g_signal_new ("clicked", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (VikStatusbarClass, clicked), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + klass->clicked = NULL; +} - vs->status[0] = gtk_statusbar_new(); - gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs->status[0]), FALSE ); - gtk_box_pack_start ( GTK_BOX(vs), vs->status[0], FALSE, FALSE, 1); - gtk_widget_set_size_request ( vs->status[0], 100, -1 ); +static gboolean button_release_event (GtkWidget* widget, GdkEvent *event, gpointer *user_data) +{ + if ( ((GdkEventButton*)event)->button == 3 ) { + gint type = GPOINTER_TO_INT (g_object_get_data ( G_OBJECT(widget), "type" )); + VikStatusbar *vs = VIK_STATUSBAR (user_data); + // Right Click: so copy the text in the INFO buffer only ATM + if ( type == VIK_STATUSBAR_INFO ) { + const gchar* msg = gtk_button_get_label (GTK_BUTTON(vs->status[VIK_STATUSBAR_INFO])); + if ( msg ) { + GtkClipboard *clipboard = gtk_clipboard_get ( GDK_SELECTION_CLIPBOARD ); + gtk_clipboard_set_text ( clipboard, msg, -1 ); + } + } + // We've handled the event + return TRUE; + } + // Otherwise carry on with other event handlers - i.e. ensure forward_signal() is called + return FALSE; +} - vs->status[1] = gtk_statusbar_new(); - gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs->status[1]), FALSE ); - gtk_box_pack_start ( GTK_BOX(vs), vs->status[1], FALSE, FALSE, 1); - gtk_widget_set_size_request ( vs->status[1], 100, -1 ); +static void +vik_statusbar_init (VikStatusbar *vs) +{ + gint i; - vs->status[2] = gtk_statusbar_new(); - gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs->status[2]), FALSE ); - gtk_box_pack_end ( GTK_BOX(vs), vs->status[2], TRUE, TRUE, 1); + for ( i = 0; i < VIK_STATUSBAR_NUM_TYPES; i++ ) { + vs->empty[i] = TRUE; + + if (i == VIK_STATUSBAR_ITEMS || i == VIK_STATUSBAR_ZOOM || i == VIK_STATUSBAR_INFO ) + vs->status[i] = gtk_button_new(); + else + { + vs->status[i] = gtk_statusbar_new(); + gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs->status[i]), FALSE ); + } + g_object_set_data (G_OBJECT (vs->status[i]), "type", GINT_TO_POINTER(i)); + } - vs->status[3] = gtk_statusbar_new(); - gtk_statusbar_set_has_resize_grip ( GTK_STATUSBAR(vs->status[3]), FALSE ); - gtk_box_pack_end ( GTK_BOX(vs), vs->status[3], TRUE, TRUE, 1); + gtk_box_pack_start ( GTK_BOX(vs), vs->status[VIK_STATUSBAR_TOOL], FALSE, FALSE, 1); + gtk_widget_set_size_request ( vs->status[VIK_STATUSBAR_TOOL], 125, -1 ); + + g_signal_connect ( G_OBJECT(vs->status[VIK_STATUSBAR_ITEMS]), "clicked", G_CALLBACK (forward_signal), vs); + gtk_button_set_relief ( GTK_BUTTON(vs->status[VIK_STATUSBAR_ITEMS]), GTK_RELIEF_NONE ); + gtk_widget_set_tooltip_text (GTK_WIDGET (vs->status[VIK_STATUSBAR_ITEMS]), _("Current number of background tasks. Click to see the background jobs.")); + gtk_box_pack_start ( GTK_BOX(vs), vs->status[VIK_STATUSBAR_ITEMS], FALSE, FALSE, 1); + gtk_widget_set_size_request ( vs->status[VIK_STATUSBAR_ITEMS], 100, -1 ); + + g_signal_connect ( G_OBJECT(vs->status[VIK_STATUSBAR_ZOOM]), "clicked", G_CALLBACK (forward_signal), vs); + gtk_button_set_relief ( GTK_BUTTON(vs->status[VIK_STATUSBAR_ZOOM]), GTK_RELIEF_NONE ); + gtk_widget_set_tooltip_text (GTK_WIDGET (vs->status[VIK_STATUSBAR_ZOOM]), _("Current zoom level. Click to select a new one.")); + gtk_box_pack_start ( GTK_BOX(vs), vs->status[VIK_STATUSBAR_ZOOM], FALSE, FALSE, 1); + gtk_widget_set_size_request ( vs->status[VIK_STATUSBAR_ZOOM], 100, -1 ); + + gtk_box_pack_start ( GTK_BOX(vs), vs->status[VIK_STATUSBAR_POSITION], FALSE, FALSE, 1); + gtk_widget_set_size_request ( vs->status[VIK_STATUSBAR_POSITION], 275, -1 ); + + g_signal_connect ( G_OBJECT(vs->status[VIK_STATUSBAR_INFO]), "button-release-event", G_CALLBACK (button_release_event), vs); + g_signal_connect ( G_OBJECT(vs->status[VIK_STATUSBAR_INFO]), "clicked", G_CALLBACK (forward_signal), vs); + gtk_widget_set_tooltip_text (GTK_WIDGET (vs->status[VIK_STATUSBAR_INFO]), _("Left click to clear the message. Right click to copy the message.")); + gtk_button_set_alignment ( GTK_BUTTON(vs->status[VIK_STATUSBAR_INFO]), 0.0, 0.5 ); // Left align the text + gtk_box_pack_end ( GTK_BOX(vs), vs->status[VIK_STATUSBAR_INFO], TRUE, TRUE, 1); + + // Set minimum overall size + // otherwise the individual size_requests above create an implicit overall size, + // and so one can't downsize horizontally as much as may be desired when the statusbar is on + gtk_widget_set_size_request ( GTK_WIDGET(vs), 50, -1 ); +} - for ( i = 0; i < STATUS_COUNT; i++ ) - vs->empty[i] = TRUE; +/** + * vik_statusbar_new: + * + * Creates a new #VikStatusbar widget. + * + * Return value: the new #VikStatusbar widget. + **/ +VikStatusbar * +vik_statusbar_new () +{ + VikStatusbar *vs = VIK_STATUSBAR ( g_object_new ( VIK_STATUSBAR_TYPE, NULL ) ); return vs; } -void vik_statusbar_set_message ( VikStatusbar *vs, gint field, const gchar *message ) +/** + * vik_statusbar_set_message: + * @vs: the #VikStatusbar itself + * @field: the field to update + * @message: the message to use + * + * Update the message of the given field. + **/ +void +vik_statusbar_set_message ( VikStatusbar *vs, vik_statusbar_type_t field, const gchar *message ) { - if ( field >= 0 && field < STATUS_COUNT ) + if ( field >= 0 && field < VIK_STATUSBAR_NUM_TYPES ) { - GtkStatusbar *gsb; - if ( field == 0 ) - gsb = GTK_STATUSBAR(vs); + if ( field == VIK_STATUSBAR_ITEMS || field == VIK_STATUSBAR_ZOOM || field == VIK_STATUSBAR_INFO ) + { + gtk_button_set_label ( GTK_BUTTON(vs->status[field]), message); + } else - gsb = GTK_STATUSBAR(vs->status[field-1]); + { + GtkStatusbar *gsb = GTK_STATUSBAR(vs->status[field]); if ( !vs->empty[field] ) gtk_statusbar_pop ( gsb, 0 ); @@ -105,5 +194,6 @@ void vik_statusbar_set_message ( VikStatusbar *vs, gint field, const gchar *mess vs->empty[field] = FALSE; gtk_statusbar_push ( gsb, 0, message ); + } } }