#endif
#include "viking.h"
+#include "settings.h"
#include <string.h>
enum {
VLP_UPDATE_SIGNAL,
+ VLP_DELETE_LAYER_SIGNAL,
VLP_LAST_SIGNAL
};
VikTreeview *vt;
VikViewport *vvp; /* reference */
-
- GtkItemFactory *popup_factory;
};
-static GtkItemFactoryEntry base_entries[] = {
- { N_("/C_ut"), NULL, (GtkItemFactoryCallback) vik_layers_panel_cut_selected, -1, "<StockItem>", GTK_STOCK_CUT },
- { N_("/_Copy"), NULL, (GtkItemFactoryCallback) vik_layers_panel_copy_selected, -1, "<StockItem>", GTK_STOCK_COPY },
- { N_("/_Paste"), NULL, (GtkItemFactoryCallback) vik_layers_panel_paste_selected, -1, "<StockItem>", GTK_STOCK_PASTE },
- { N_("/_Delete"), NULL, (GtkItemFactoryCallback) vik_layers_panel_delete_selected, -1, "<StockItem>", GTK_STOCK_DELETE },
- { N_("/New Layer"), NULL, NULL, -1, "<Branch>" },
+static GtkActionEntry entries[] = {
+ { "Cut", GTK_STOCK_CUT, N_("C_ut"), NULL, NULL, (GCallback) vik_layers_panel_cut_selected },
+ { "Copy", GTK_STOCK_COPY, N_("_Copy"), NULL, NULL, (GCallback) vik_layers_panel_copy_selected },
+ { "Paste", GTK_STOCK_PASTE, N_("_Paste"), NULL, NULL, (GCallback) vik_layers_panel_paste_selected },
+ { "Delete", GTK_STOCK_DELETE, N_("_Delete"), NULL, NULL, (GCallback) vik_layers_panel_delete_selected },
};
-#define NUM_BASE_ENTRIES (sizeof(base_entries)/sizeof(base_entries[0]))
-
static void layers_item_toggled (VikLayersPanel *vlp, GtkTreeIter *iter);
static void layers_item_edited (VikLayersPanel *vlp, GtkTreeIter *iter, const gchar *new_text);
static void menu_popup_cb (VikLayersPanel *vlp);
parent_class = g_type_class_peek_parent (klass);
layers_panel_signals[VLP_UPDATE_SIGNAL] = g_signal_new ( "update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (VikLayersPanelClass, update), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ layers_panel_signals[VLP_DELETE_LAYER_SIGNAL] = g_signal_new ( "delete_layer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (VikLayersPanelClass, update), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
VikLayersPanel *vik_layers_panel_new ()
return vlp->vvp;
}
+static gboolean layers_panel_new_layer ( gpointer lpnl[2] )
+{
+ return vik_layers_panel_new_layer ( lpnl[0], GPOINTER_TO_INT(lpnl[1]) );
+}
+
+/**
+ * Create menu popup on demand
+ * @full: offer cut/copy options as well - not just the new layer options
+ */
+static GtkWidget* layers_panel_create_popup ( VikLayersPanel *vlp, gboolean full )
+{
+ GtkWidget *menu = gtk_menu_new ();
+ GtkWidget *menuitem;
+ guint ii;
+
+ if ( full ) {
+ for ( ii = 0; ii < G_N_ELEMENTS(entries); ii++ ) {
+ if ( entries[ii].stock_id ) {
+ menuitem = gtk_image_menu_item_new_with_mnemonic ( entries[ii].label );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)menuitem, gtk_image_new_from_stock (entries[ii].stock_id, GTK_ICON_SIZE_MENU) );
+ }
+ else
+ menuitem = gtk_menu_item_new_with_mnemonic ( entries[ii].label );
+
+ g_signal_connect_swapped ( G_OBJECT(menuitem), "activate", G_CALLBACK(entries[ii].callback), vlp );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show ( menuitem );
+ }
+ }
+
+ GtkWidget *submenu = gtk_menu_new();
+ menuitem = gtk_menu_item_new_with_mnemonic ( _("New Layer") );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ gtk_widget_show ( menuitem );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu );
+
+ // Static: so memory accessible yet not continually allocated
+ static gpointer lpnl[VIK_LAYER_NUM_TYPES][2];
+
+ for ( ii = 0; ii < VIK_LAYER_NUM_TYPES; ii++ ) {
+ if ( vik_layer_get_interface(ii)->icon ) {
+ menuitem = gtk_image_menu_item_new_with_mnemonic ( vik_layer_get_interface(ii)->name );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)menuitem, gtk_image_new_from_pixbuf ( vik_layer_load_icon (ii) ) );
+ }
+ else
+ menuitem = gtk_menu_item_new_with_mnemonic ( vik_layer_get_interface(ii)->name );
+
+ lpnl[ii][0] = vlp;
+ lpnl[ii][1] = GINT_TO_POINTER(ii);
+
+ g_signal_connect_swapped ( G_OBJECT(menuitem), "activate", G_CALLBACK(layers_panel_new_layer), lpnl[ii] );
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menuitem);
+ gtk_widget_show ( menuitem );
+ }
+
+ return menu;
+}
+
static void vik_layers_panel_init ( VikLayersPanel *vlp )
{
GtkWidget *hbox;
GtkWidget *copybutton, *copyimage;
GtkWidget *pastebutton, *pasteimage;
GtkWidget *scrolledwindow;
- GtkItemFactoryEntry entry;
- guint i, tmp;
vlp->vvp = NULL;
vik_layer_rename ( VIK_LAYER(vlp->toplayer), _("Top Layer"));
g_signal_connect_swapped ( G_OBJECT(vlp->toplayer), "update", G_CALLBACK(vik_layers_panel_emit_update), vlp );
- vik_treeview_add_layer ( vlp->vt, NULL, &(vlp->toplayer_iter), VIK_LAYER(vlp->toplayer)->name, NULL, vlp->toplayer, VIK_LAYER_AGGREGATE, VIK_LAYER_AGGREGATE );
+ vik_treeview_add_layer ( vlp->vt, NULL, &(vlp->toplayer_iter), VIK_LAYER(vlp->toplayer)->name, NULL, TRUE, vlp->toplayer, VIK_LAYER_AGGREGATE, VIK_LAYER_AGGREGATE, 0 );
vik_layer_realize ( VIK_LAYER(vlp->toplayer), vlp->vt, &(vlp->toplayer_iter) );
g_signal_connect_swapped ( vlp->vt, "popup_menu", G_CALLBACK(menu_popup_cb), vlp);
pasteimage = gtk_image_new_from_stock ( GTK_STOCK_PASTE, GTK_ICON_SIZE_SMALL_TOOLBAR );
pastebutton = gtk_button_new ( );
gtk_container_add ( GTK_CONTAINER(pastebutton),pasteimage );
- gtk_widget_set_tooltip_text ( GTK_WIDGET(pastebutton), _("Paste layer below selected layer"));
+ gtk_widget_set_tooltip_text ( GTK_WIDGET(pastebutton), _("Paste layer into selected container layer or otherwise above selected layer"));
gtk_box_pack_start ( GTK_BOX(hbox), pastebutton, TRUE, TRUE, 0 );
g_signal_connect_swapped ( G_OBJECT(pastebutton), "clicked", G_CALLBACK(vik_layers_panel_paste_selected), vlp );
gtk_box_pack_start ( GTK_BOX(vlp), scrolledwindow, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX(vlp), hbox, FALSE, FALSE, 0 );
+}
- vlp->popup_factory = gtk_item_factory_new ( GTK_TYPE_MENU, "<main>", NULL );
- gtk_item_factory_set_translate_func (vlp->popup_factory,
- (GtkTranslateFunc) gettext, NULL, NULL);
- gtk_item_factory_create_items ( vlp->popup_factory, NUM_BASE_ENTRIES, base_entries, vlp );
- for ( i = 0; i < VIK_LAYER_NUM_TYPES; i++ )
- {
- /* TODO: FIXME: if name has a '/' in it it will get all messed up. why not have an itemfactory field with
- name, icon, shortcut, etc.? */
- gchar *label = g_strdup_printf(_("New _%s Layer"), vik_layer_get_interface(i)->name );
- entry.path = g_strdup_printf("%s/%s", base_entries[NUM_BASE_ENTRIES-1].path, label );
- g_free ( label );
- entry.accelerator = NULL;
- entry.callback = (GtkItemFactoryCallback) vik_layers_panel_new_layer;
- entry.callback_action = i;
- if ( vik_layer_get_interface(i)->icon )
- {
- entry.item_type = "<ImageItem>";
- entry.extra_data = gdk_pixdata_serialize ( vik_layer_get_interface(i)->icon, &tmp );
- }
- else
- entry.item_type = "<Item>";
-
- gtk_item_factory_create_item ( vlp->popup_factory, &entry, vlp, 1 );
- g_free ( (gpointer) entry.extra_data );
- g_free ( entry.path );
- }
+/**
+ * Invoke the actual drawing via signal method
+ */
+static gboolean idle_draw_panel ( VikLayersPanel *vlp )
+{
+ g_signal_emit ( G_OBJECT(vlp), layers_panel_signals[VLP_UPDATE_SIGNAL], 0 );
+ return FALSE; // Nothing else to do
}
void vik_layers_panel_emit_update ( VikLayersPanel *vlp )
{
- g_signal_emit ( G_OBJECT(vlp), layers_panel_signals[VLP_UPDATE_SIGNAL], 0 );
+ GThread *thread = vik_window_get_thread (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(vlp)));
+ if ( !thread )
+ // Do nothing
+ return;
+
+ // Only ever draw when there is time to do so
+ if ( g_thread_self() != thread )
+ // Drawing requested from another (background) thread, so handle via the gdk thread method
+ gdk_threads_add_idle ( (GSourceFunc) idle_draw_panel, vlp );
+ else
+ g_idle_add ( (GSourceFunc) idle_draw_panel, vlp );
}
static void layers_item_toggled (VikLayersPanel *vlp, GtkTreeIter *iter)
static void layers_item_edited (VikLayersPanel *vlp, GtkTreeIter *iter, const gchar *new_text)
{
+ if ( !new_text )
+ return;
+
+ if ( new_text[0] == '\0' ) {
+ a_dialog_error_msg ( GTK_WINDOW(VIK_WINDOW_FROM_WIDGET(vlp)), _("New name can not be blank.") );
+ return;
+ }
+
if ( vik_treeview_item_get_type ( vlp->vt, iter ) == VIK_TREEVIEW_TYPE_LAYER )
{
VikLayer *l;
{
if (event->button == 3)
{
- GtkTreeIter iter;
+ static GtkTreeIter iter;
if ( vik_treeview_get_iter_at_pos ( vlp->vt, &iter, event->x, event->y ) )
{
layers_popup ( vlp, &iter, 3 );
VikLayer *layer = VIK_LAYER(vik_treeview_item_get_pointer ( vlp->vt, iter ));
if ( layer->type == VIK_LAYER_AGGREGATE )
- menu = GTK_MENU(gtk_item_factory_get_widget ( vlp->popup_factory, "<main>" ));
+ menu = GTK_MENU ( layers_panel_create_popup ( vlp, TRUE ) );
else
{
GtkWidget *del, *prop;
gtk_menu_shell_append (GTK_MENU_SHELL (menu), del);
gtk_widget_show ( del );
}
-
- vik_layer_add_menu_items ( layer, menu, vlp );
- }
+ }
+ vik_layer_add_menu_items ( layer, menu, vlp );
}
else
{
}
}
else
- menu = GTK_MENU(gtk_item_factory_get_widget ( vlp->popup_factory, base_entries[NUM_BASE_ENTRIES-1].path ));
+ {
+ menu = GTK_MENU ( layers_panel_create_popup ( vlp, FALSE ) );
+ }
gtk_menu_popup ( menu, NULL, NULL, NULL, NULL, mouse_button, gtk_get_current_event_time() );
}
layers_popup ( vlp, NULL, 0 );
}
+#define VIK_SETTINGS_LAYERS_TRW_CREATE_DEFAULT "layers_create_trw_auto_default"
/**
* vik_layers_panel_new_layer:
* @type: type of the new layer
*
* Create a new layer and add to panel.
*/
-gboolean vik_layers_panel_new_layer ( VikLayersPanel *vlp, gint type )
+gboolean vik_layers_panel_new_layer ( VikLayersPanel *vlp, VikLayerTypeEnum type )
{
VikLayer *l;
g_assert ( vlp->vvp );
- l = vik_layer_create ( type, vlp->vvp, VIK_GTK_WINDOW_FROM_WIDGET(vlp), TRUE );
+ gboolean ask_user = FALSE;
+ if ( type == VIK_LAYER_TRW )
+ a_settings_get_boolean ( VIK_SETTINGS_LAYERS_TRW_CREATE_DEFAULT, &ask_user );
+ ask_user = !ask_user;
+ l = vik_layer_create ( type, vlp->vvp, ask_user );
if ( l )
{
vik_layers_panel_add_layer ( vlp, l );
vik_layer_change_coord_mode ( l, vik_viewport_get_coord_mode(vlp->vvp) );
if ( ! vik_treeview_get_selected_iter ( vlp->vt, &iter ) )
- vik_aggregate_layer_add_layer ( vlp->toplayer, l );
+ vik_aggregate_layer_add_layer ( vlp->toplayer, l, TRUE );
else
{
VikAggregateLayer *addtoagg;
if ( replace_iter )
vik_aggregate_layer_insert_layer ( addtoagg, l, replace_iter );
else
- vik_aggregate_layer_add_layer ( addtoagg, l );
+ vik_aggregate_layer_add_layer ( addtoagg, l, TRUE );
}
vik_layers_panel_emit_update ( vlp );
a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vlp), _("Aggregate Layers have no settable properties.") );
VikLayer *layer = VIK_LAYER( vik_treeview_item_get_pointer ( vlp->vt, &iter ) );
if (vik_layer_properties ( layer, vlp->vvp ))
- vik_layer_emit_update ( layer, FALSE );
+ vik_layer_emit_update ( layer );
return TRUE;
}
else
a_clipboard_copy_selected ( vlp );
if (IS_VIK_AGGREGATE_LAYER(parent)) {
- if ( vik_aggregate_layer_delete ( parent, &iter ) )
- vik_layers_panel_emit_update ( vlp );
+
+ g_signal_emit ( G_OBJECT(vlp), layers_panel_signals[VLP_DELETE_LAYER_SIGNAL], 0 );
+
+ if ( vik_aggregate_layer_delete ( parent, &iter ) )
+ vik_layers_panel_emit_update ( vlp );
}
}
else
a_clipboard_copy_selected ( vlp );
}
-void vik_layers_panel_paste_selected ( VikLayersPanel *vlp )
+gboolean vik_layers_panel_paste_selected ( VikLayersPanel *vlp )
{
GtkTreeIter iter;
if ( ! vik_treeview_get_selected_iter ( vlp->vt, &iter ) )
/* Nothing to do */
- return;
- a_clipboard_paste ( vlp );
+ return FALSE;
+ return a_clipboard_paste ( vlp );
}
void vik_layers_panel_delete_selected ( VikLayersPanel *vlp )
vik_viewport_set_trigger ( vlp->vvp, NULL );
if (IS_VIK_AGGREGATE_LAYER(parent)) {
+
+ g_signal_emit ( G_OBJECT(vlp), layers_panel_signals[VLP_DELETE_LAYER_SIGNAL], 0 );
+
if ( vik_aggregate_layer_delete ( parent, &iter ) )
vik_layers_panel_emit_update ( vlp );
}
}
#endif
-VikLayer *vik_layers_panel_get_layer_of_type ( VikLayersPanel *vlp, gint type )
+VikLayer *vik_layers_panel_get_layer_of_type ( VikLayersPanel *vlp, VikLayerTypeEnum type )
{
VikLayer *rv = vik_layers_panel_get_selected ( vlp );
if ( rv == NULL || rv->type != type )
void vik_layers_panel_clear ( VikLayersPanel *vlp )
{
- if ( (! vik_aggregate_layer_is_empty(vlp->toplayer)) && a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_WIDGET(vlp), _("Are you sure you wish to delete all layers?"), NULL ) )
+ if ( (! vik_aggregate_layer_is_empty(vlp->toplayer)) && a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_WIDGET(vlp), _("Are you sure you wish to delete all layers?"), NULL ) ) {
+ g_signal_emit ( G_OBJECT(vlp), layers_panel_signals[VLP_DELETE_LAYER_SIGNAL], 0 );
vik_aggregate_layer_clear ( vlp->toplayer ); /* simply deletes all layers */
+ }
}
void vik_layers_panel_change_coord_mode ( VikLayersPanel *vlp, VikCoordMode mode )
{
VikLayersPanel *vlp = VIK_LAYERS_PANEL ( gob );
g_object_unref ( VIK_LAYER(vlp->toplayer) );
- g_object_unref ( G_OBJECT(vlp->popup_factory) );
G_OBJECT_CLASS(parent_class)->finalize(gob);
}