+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
- * toolbar.c - this file is part of Geany, a fast and lightweight IDE
+ * toolbar.c - this file was part of Geany (v1.24.1), a fast and lightweight IDE
*
* Copyright 2009-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* Copyright 2009-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ * Copyright 2014 Rob Norris <rw_norris@hotmail.com>
*
* 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
*/
/* Utility functions to create the toolbar */
-#include "geany.h"
-#include "support.h"
-#include "ui_utils.h"
-#include "toolbar.h"
-#include "callbacks.h"
-#include "utils.h"
-#include "dialogs.h"
-#include "document.h"
-#include "build.h"
-#include "main.h"
-#include "geanymenubuttonaction.h"
-#include "geanyentryaction.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "toolbar.h"
+#include "dir.h"
+#include "ui_util.h"
+#include "util.h"
#include <string.h>
+#include <glib/gi18n.h>
#include <glib/gstdio.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "preferences.h"
+
+
+struct _VikToolbarClass
+{
+ GObjectClass object_class;
+};
+
+struct _VikToolbar {
+ GObject obj;
+ GtkWidget *widget;
+ GtkUIManager *uim;
+ guint merge_id;
+ GtkActionGroup *group_actions;
+ GtkActionGroup *group_toggles;
+ GtkActionGroup *group_tools;
+ GtkActionGroup *group_modes;
+ GSList *list_of_actions;
+ GSList *list_of_toggles;
+ GSList *list_of_tools;
+ GSList *list_of_modes;
+};
+
+G_DEFINE_TYPE (VikToolbar, vik_toolbar, G_TYPE_OBJECT)
+
+static void vik_toolbar_class_init (VikToolbarClass *klass)
+{
+}
+
+static void vik_toolbar_init (VikToolbar *vtb)
+{
+ vtb->widget = NULL;
+ vtb->merge_id = 0;
+ vtb->list_of_actions = NULL;
+ vtb->list_of_toggles = NULL;
+ vtb->list_of_tools = NULL;
+ vtb->list_of_modes = NULL;
+}
+VikToolbar *vik_toolbar_new ()
+{
+ VikToolbar *vtb = (VikToolbar *)g_object_new(vik_toolbar_get_type(), NULL);
+ return vtb;
+}
-GeanyToolbarPrefs toolbar_prefs;
-static GtkUIManager *uim;
-static GtkActionGroup *group;
-static GSList *plugin_items = NULL;
-
-/* Available toolbar actions
- * Fields: name, stock_id, label, accelerator, tooltip, callback */
-static const GtkActionEntry ui_entries[] = {
- /* custom actions defined in toolbar_init(): "New", "Open", "SearchEntry", "GotoEntry", "Build" */
- { "Save", GTK_STOCK_SAVE, NULL, NULL, N_("Save the current file"), G_CALLBACK(on_toolbutton_save_clicked) },
- { "SaveAs", GTK_STOCK_SAVE_AS, NULL, NULL, N_("Save as"), G_CALLBACK(on_save_as1_activate) },
- { "SaveAll", GEANY_STOCK_SAVE_ALL, NULL, NULL, N_("Save all open files"), G_CALLBACK(on_save_all1_activate) },
- { "Reload", GTK_STOCK_REVERT_TO_SAVED, NULL, NULL, N_("Reload the current file from disk"), G_CALLBACK(on_toolbutton_reload_clicked) },
- { "Close", GTK_STOCK_CLOSE, NULL, NULL, N_("Close the current file"), G_CALLBACK(on_toolbutton_close_clicked) },
- { "CloseAll", GEANY_STOCK_CLOSE_ALL, NULL, NULL, N_("Close all open files"), G_CALLBACK(on_toolbutton_close_all_clicked) },
- { "Cut", GTK_STOCK_CUT, NULL, NULL, N_("Cut the current selection"), G_CALLBACK(on_cut1_activate) },
- { "Copy", GTK_STOCK_COPY, NULL, NULL, N_("Copy the current selection"), G_CALLBACK(on_copy1_activate) },
- { "Paste", GTK_STOCK_PASTE, NULL, NULL, N_("Paste the contents of the clipboard"), G_CALLBACK(on_paste1_activate) },
- { "Delete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the current selection"), G_CALLBACK(on_delete1_activate) },
- { "Undo", GTK_STOCK_UNDO, NULL, NULL, N_("Undo the last modification"), G_CALLBACK(on_undo1_activate) },
- { "Redo", GTK_STOCK_REDO, NULL, NULL, N_("Redo the last modification"), G_CALLBACK(on_redo1_activate) },
- { "NavBack", GTK_STOCK_GO_BACK, NULL, NULL, N_("Navigate back a location"), G_CALLBACK(on_back_activate) },
- { "NavFor", GTK_STOCK_GO_FORWARD, NULL, NULL, N_("Navigate forward a location"), G_CALLBACK(on_forward_activate) },
- { "Compile", GTK_STOCK_CONVERT, N_("Compile"), NULL, N_("Compile the current file"), G_CALLBACK(on_toolbutton_compile_clicked) },
- { "Run", GTK_STOCK_EXECUTE, NULL, NULL, N_("Run or view the current file"), G_CALLBACK(on_toolbutton_run_clicked) },
- { "Color", GTK_STOCK_SELECT_COLOR, N_("Color Chooser"), NULL, N_("Open a color chooser dialog, to interactively pick colors from a palette"), G_CALLBACK(on_show_color_chooser1_activate) },
- { "ZoomIn", GTK_STOCK_ZOOM_IN, NULL, NULL, N_("Zoom in the text"), G_CALLBACK(on_zoom_in1_activate) },
- { "ZoomOut", GTK_STOCK_ZOOM_OUT, NULL, NULL, N_("Zoom out the text"), G_CALLBACK(on_zoom_out1_activate) },
- { "UnIndent", GTK_STOCK_UNINDENT, NULL, NULL, N_("Decrease indentation"), G_CALLBACK(on_menu_decrease_indent1_activate) },
- { "Indent", GTK_STOCK_INDENT, NULL, NULL, N_("Increase indentation"), G_CALLBACK(on_menu_increase_indent1_activate) },
- { "Search", GTK_STOCK_FIND, NULL, NULL, N_("Find the entered text in the current file"), G_CALLBACK(on_toolbutton_search_clicked) },
- { "Goto", GTK_STOCK_JUMP_TO, NULL, NULL, N_("Jump to the entered line number"), G_CALLBACK(on_toolbutton_goto_clicked) },
- { "Preferences", GTK_STOCK_PREFERENCES, NULL, NULL, N_("Show the preferences dialog"), G_CALLBACK(on_toolbutton_preferences_clicked) },
- { "Quit", GTK_STOCK_QUIT, NULL, NULL, N_("Quit Geany"), G_CALLBACK(on_toolbutton_quit_clicked) },
- { "Print", GTK_STOCK_PRINT, NULL, NULL, N_("Print document"), G_CALLBACK(on_print1_activate) },
- { "Replace", GTK_STOCK_FIND_AND_REPLACE, NULL, NULL, N_("Replace text in the current document"), G_CALLBACK(on_replace1_activate) }
+#define TOOLBAR_PARAMS_GROUP_KEY "toolbar"
+#define TOOLBAR_PARAMS_NAMESPACE "toolbar."
+
+static gchar *params_icon_size[] = { N_("System Default"), N_("Small"), N_("Medium"), N_("Large"), NULL };
+static gchar *params_icon_style[] = { N_("System Default"), N_("Icons Only"), N_("Text Only"), N_("Icons and Text"), NULL };
+
+typedef struct {
+ VikToolbar *vtb;
+ GtkWindow *parent;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ ReloadCB *reload_cb;
+ gpointer user_data;
+} config_t;
+
+static config_t extra_widget_data;
+
+static VikLayerParam prefs[] = {
+ { VIK_LAYER_NUM_TYPES, TOOLBAR_PARAMS_NAMESPACE "append_to_menu", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Append to Menu:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL,
+ N_("Pack the toolbar to the main menu to save vertical space"), NULL, NULL, NULL },
+ { VIK_LAYER_NUM_TYPES, TOOLBAR_PARAMS_NAMESPACE "icon_size", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Icon Size:"), VIK_LAYER_WIDGET_COMBOBOX, params_icon_size, NULL,
+ NULL, NULL, NULL, NULL },
+ { VIK_LAYER_NUM_TYPES, TOOLBAR_PARAMS_NAMESPACE "icon_style", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Icon Style:"), VIK_LAYER_WIDGET_COMBOBOX, params_icon_style, NULL,
+ NULL, NULL, NULL, NULL },
+ { VIK_LAYER_NUM_TYPES, TOOLBAR_PARAMS_NAMESPACE "NOTSAVED1", VIK_LAYER_PARAM_PTR, VIK_LAYER_GROUP_NONE, N_("Customize:"), VIK_LAYER_WIDGET_BUTTON, N_("Customize Buttons"), NULL,
+ NULL, NULL, NULL, NULL },
};
-static const guint ui_entries_n = G_N_ELEMENTS(ui_entries);
-
-
-/* fallback UI definition */
-static const gchar *toolbar_markup =
-"<ui>"
- "<toolbar name='GeanyToolbar'>"
- "<toolitem action='New'/>"
- "<toolitem action='Open'/>"
- "<toolitem action='Save'/>"
- "<toolitem action='SaveAll'/>"
- "<separator/>"
- "<toolitem action='Reload'/>"
- "<toolitem action='Close'/>"
- "<separator/>"
- "<toolitem action='NavBack'/>"
- "<toolitem action='NavFor'/>"
- "<separator/>"
- "<toolitem action='Compile'/>"
- "<toolitem action='Build'/>"
- "<toolitem action='Run'/>"
- "<separator/>"
- "<toolitem action='Color'/>"
- "<separator/>"
- "<toolitem action='SearchEntry'/>"
- "<toolitem action='Search'/>"
- "<separator/>"
- "<toolitem action='GotoEntry'/>"
- "<toolitem action='Goto'/>"
- "<separator/>"
- "<toolitem action='Quit'/>"
- "</toolbar>"
-"</ui>";
+// Global storage to enable freeing upon closure
+static GHashTable *signal_data;
+static GSList *toggle_overrides = NULL;
+
+// Forward declaration
+void toolbar_configure (VikToolbar *vtb, GtkWidget *toolbar, GtkWindow *parent, GtkWidget *vbox, GtkWidget *hbox, ReloadCB reload_cb, gpointer user_data);
+
+void toolbar_configure_cb(void)
+{
+ // Values not known at prefs initialization.
+ // So trying to pass these values via the UI builder is not possible currently.
+ // ATM cheat via internal values - although this doesn't work properly for multiple Windows...
+ toolbar_configure ( extra_widget_data.vtb,
+ extra_widget_data.vtb->widget,
+ extra_widget_data.parent,
+ extra_widget_data.vbox,
+ extra_widget_data.hbox,
+ extra_widget_data.reload_cb,
+ extra_widget_data.user_data );
+}
+
+/**
+ * a_toolbar_init:
+ *
+ * Initialize stuff for the toolbar.
+ */
+void a_toolbar_init (void)
+{
+ // Preferences
+ a_preferences_register_group ( TOOLBAR_PARAMS_GROUP_KEY, _("Toolbar") );
+
+ guint i = 0;
+ VikLayerParamData tmp;
+ tmp.b = FALSE;
+ a_preferences_register (&prefs[i++], tmp, TOOLBAR_PARAMS_GROUP_KEY);
+ tmp.u = 0;
+ a_preferences_register (&prefs[i++], tmp, TOOLBAR_PARAMS_GROUP_KEY);
+#ifdef WINDOWS
+ tmp.u = 1; // Small Icons for Windows by default as 'System Defaults' is more GNOME Theme driven.
+#else
+ tmp.u = 0;
+#endif
+ a_preferences_register (&prefs[i++], tmp, TOOLBAR_PARAMS_GROUP_KEY);
+ tmp.ptr = toolbar_configure_cb;
+ a_preferences_register (&prefs[i++], tmp, TOOLBAR_PARAMS_GROUP_KEY);
+
+ // Signal data hash
+ signal_data = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
+}
+
+/**
+ * a_toolbar_uninit:
+ *
+ * Uninitialize toolbar related stuff.
+ */
+void a_toolbar_uninit ( void )
+{
+ g_hash_table_destroy ( signal_data );
+ g_slist_foreach ( toggle_overrides, (GFunc)g_free, NULL );
+ g_slist_free ( toggle_overrides );
+}
+
+static gboolean prefs_get_append_to_menu (void)
+{
+ return a_preferences_get(TOOLBAR_PARAMS_NAMESPACE "append_to_menu")->b;
+}
+
+static guint prefs_get_icon_size (void)
+{
+ return a_preferences_get(TOOLBAR_PARAMS_NAMESPACE "icon_size")->b;
+}
+
+static guint prefs_get_icon_style (void)
+{
+ return a_preferences_get(TOOLBAR_PARAMS_NAMESPACE "icon_style")->b;
+}
/* Note: The returned widget pointer is only valid until the toolbar is reloaded. So, either
* update the widget pointer in this case (i.e. request it again) or better use
* toolbar_get_action_by_name() instead. The action objects will remain the same even when the
* toolbar is reloaded. */
-GtkWidget *toolbar_get_widget_by_name(const gchar *name)
+GtkWidget *toolbar_get_widget_by_name(VikToolbar *vtb, const gchar *name)
{
GtkWidget *widget;
gchar *path;
g_return_val_if_fail(name != NULL, NULL);
+ g_return_val_if_fail(VIK_IS_TOOLBAR(vtb), NULL);
- path = g_strconcat("/ui/GeanyToolbar/", name, NULL);
- widget = gtk_ui_manager_get_widget(uim, path);
+ path = g_strconcat("/ui/MainToolbar/", name, NULL);
+ widget = gtk_ui_manager_get_widget(vtb->uim, path);
g_free(path);
return widget;
}
-
-/* Note: The returned widget pointer is only valid until the toolbar is reloaded. See
- * toolbar_get_widget_by_name for details(). */
-GtkWidget *toolbar_get_widget_child_by_name(const gchar *name)
+static GtkAction *get_action ( VikToolbar *vtb, const gchar *name )
{
- GtkWidget *widget = toolbar_get_widget_by_name(name);
-
- if (G_LIKELY(widget != NULL))
- return gtk_bin_get_child(GTK_BIN(widget));
- else
- return NULL;
+ // Try all groups
+ GtkAction *action = gtk_action_group_get_action (vtb->group_actions, name);
+ if ( !action )
+ action = gtk_action_group_get_action (vtb->group_tools, name);
+ if ( !action )
+ action = gtk_action_group_get_action (vtb->group_toggles, name);
+ if ( !action )
+ action = gtk_action_group_get_action (vtb->group_modes, name);
+ return action;
}
-
-GtkAction *toolbar_get_action_by_name(const gchar *name)
+/**
+ * toolbar_get_action_by_name:
+ *
+ * Find an action in the specified toolbar via the action name
+ */
+GtkAction *toolbar_get_action_by_name(VikToolbar *vtb, const gchar *name)
{
g_return_val_if_fail(name != NULL, NULL);
+ g_return_val_if_fail(VIK_IS_TOOLBAR(vtb), NULL);
- return gtk_action_group_get_action(group, name);
+ return get_action(vtb,name);
}
+/**
+ * toolbar_action_tool_entry_register:
+ *
+ * Register a tool button in the specified toolbar
+ * Only one of these tools can be active at a time (hence it is a GtkRadioActionEntry)
+ */
+void toolbar_action_tool_entry_register(VikToolbar *vtb, GtkRadioActionEntry *action)
+{
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+ g_return_if_fail(action != NULL);
+ vtb->list_of_tools = g_slist_append(vtb->list_of_tools, action);
+}
-static void toolbar_item_destroy_cb(GtkWidget *widget, G_GNUC_UNUSED gpointer data)
+/**
+ * toolbar_action_mode_entry_register:
+ *
+ * Register a drawing projection mode button in the specified toolbar
+ * Only one of these modes can be active at a time (hence it is a GtkRadioActionEntry)
+ */
+void toolbar_action_mode_entry_register(VikToolbar *vtb, GtkRadioActionEntry *action)
{
- plugin_items = g_slist_remove(plugin_items, widget);
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+ g_return_if_fail(action != NULL);
+ vtb->list_of_modes = g_slist_append(vtb->list_of_modes, action);
}
+/**
+ * toolbar_action_toggle_entry_register:
+ *
+ * Register a toggle button in the specified toolbar with the specified callback
+ * Used in preventing circluar callbacks of a toolbar toggle event calling the menu toggle event
+ * (that then calls toolbar callback and so on and so on...)
+ * The toggle action must be given a pointer to a function that is used on the callback for toolbar only
+ * (that must offer a way to have a finite call chain!)
+ */
+void toolbar_action_toggle_entry_register(VikToolbar *vtb, GtkToggleActionEntry *action, gpointer callback)
+{
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+ g_return_if_fail(action != NULL);
+
+ GtkToggleActionEntry *myaction = g_malloc (sizeof (GtkToggleActionEntry) );
+ memcpy ( myaction, action, sizeof (GtkToggleActionEntry) );
+ // Overwrite with specific callback
+ myaction->callback = callback;
+ vtb->list_of_toggles = g_slist_append(vtb->list_of_toggles, myaction);
-void toolbar_item_ref(GtkToolItem *item)
+ // Store override so it can be freed upon toolbar destruction
+ toggle_overrides = g_slist_append ( toggle_overrides, myaction );
+}
+
+/**
+ * toolbar_action_entry_register:
+ *
+ * Register a standard action button in the specified toolbar
+ */
+void toolbar_action_entry_register(VikToolbar *vtb, GtkActionEntry *action)
{
- g_return_if_fail(item != NULL);
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+ g_return_if_fail(action != NULL);
+ vtb->list_of_actions = g_slist_append(vtb->list_of_actions, action);
+}
- plugin_items = g_slist_append(plugin_items, item);
- g_signal_connect(item, "destroy", G_CALLBACK(toolbar_item_destroy_cb), NULL);
+static void configure_cb (GtkWidget *widget, gpointer user_data)
+{
+ config_t *data = (config_t*)user_data;
+ toolbar_configure ( data->vtb, data->vtb->widget, data->parent, data->vbox, data->hbox, data->reload_cb, data->user_data);
}
+static gboolean toolbar_popup_menu (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ // Only display menu on right button clicks
+ if (event->button == 3) {
+ GtkWidget *tmenu;
+ tmenu = gtk_menu_new();
+ GtkWidget *item = gtk_menu_item_new_with_mnemonic ( _("_Customize") );
+ g_signal_connect ( G_OBJECT(item), "activate", G_CALLBACK(configure_cb), user_data );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(tmenu), item );
+ gtk_menu_popup ( GTK_MENU(tmenu), NULL, NULL, NULL, NULL, event->button, event->time );
+ gtk_widget_show_all ( GTK_WIDGET(tmenu) );
+ g_object_ref_sink (tmenu);
+ return TRUE;
+ }
+ return FALSE;
+}
-static GtkWidget *toolbar_reload(const gchar *markup)
+/* sets the icon style of the toolbar */
+static void toolbar_set_icon_style (GtkWidget *toolbar)
{
- gint i;
- GSList *l;
- GtkWidget *entry;
- GError *error = NULL;
- gchar *filename;
- static guint merge_id = 0;
- GtkWidget *toolbar_new_file_menu = NULL;
- GtkWidget *toolbar_recent_files_menu = NULL;
- GtkWidget *toolbar_build_menu = NULL;
+ gint icon_style = prefs_get_icon_style();
- /* Cleanup old toolbar */
- if (merge_id > 0)
- {
- /* ref plugins toolbar items to keep them after we destroyed the toolbar */
- foreach_slist(l, plugin_items)
- {
- g_object_ref(l->data);
- gtk_container_remove(GTK_CONTAINER(main_widgets.toolbar), GTK_WIDGET(l->data));
- }
- /* ref and hold the submenus of the New, Open and Build toolbar items */
- toolbar_new_file_menu = geany_menu_button_action_get_menu(
- GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "New")));
- g_object_ref(toolbar_new_file_menu);
- toolbar_recent_files_menu = geany_menu_button_action_get_menu(
- GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "Open")));
- g_object_ref(toolbar_recent_files_menu);
- toolbar_build_menu = geany_menu_button_action_get_menu(
- GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "Build")));
- g_object_ref(toolbar_build_menu);
+ if (icon_style == 0)
+ icon_style = ui_get_gtk_settings_integer("gtk-toolbar-style", GTK_TOOLBAR_ICONS);
+ else
+ // Adjust to enum GtkToolbarStyle
+ icon_style--;
- /* Get rid of it! */
- gtk_widget_destroy(main_widgets.toolbar);
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), icon_style);
+}
- gtk_ui_manager_remove_ui(uim, merge_id);
- gtk_ui_manager_ensure_update(uim);
- }
- if (markup != NULL)
- {
- merge_id = gtk_ui_manager_add_ui_from_string(uim, markup, -1, &error);
+/* sets the icon size of the toolbar */
+static void toolbar_set_icon_size (GtkWidget *toolbar)
+{
+ gint icon_size = prefs_get_icon_size();
+
+ if ( icon_size == 0 )
+ icon_size = ui_get_gtk_settings_integer("gtk-toolbar-icon-size", GTK_ICON_SIZE_SMALL_TOOLBAR);
+ else {
+ // Adjust to enum GtkIconSize
+ if ( icon_size == 1 )
+ icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
+ else if ( icon_size == 2 )
+ icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
+ else if ( icon_size == 3 )
+ icon_size = GTK_ICON_SIZE_DND;
}
- else
- {
- /* Load the toolbar UI XML file from disk (first from config dir, then try data dir) */
- filename = g_build_filename(app->configdir, "ui_toolbar.xml", NULL);
- merge_id = gtk_ui_manager_add_ui_from_file(uim, filename, &error);
- if (merge_id == 0)
- {
- if (! g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- geany_debug("Loading user toolbar UI definition failed (%s).", error->message);
- g_error_free(error);
- error = NULL;
- SETPTR(filename, g_build_filename(app->datadir, "ui_toolbar.xml", NULL));
- merge_id = gtk_ui_manager_add_ui_from_file(uim, filename, &error);
- }
- g_free(filename);
- }
- if (error != NULL)
- {
- geany_debug("UI creation failed, using internal fallback definition. Error message: %s",
- error->message);
- g_error_free(error);
- /* finally load the internally defined markup as fallback */
- merge_id = gtk_ui_manager_add_ui_from_string(uim, toolbar_markup, -1, NULL);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), icon_size);
+}
+
+/**
+ * toolbar_apply_settings:
+ * @vbox: Potential vertical container for the specified toolbar
+ * @hbox: Potential horizontal container for the specified toolbar
+ * @Reset: Specify if the toolbar should be reparented
+ * (when called externally this should always be TRUE)
+ *
+ * Updates the specified toolbar with current setting values
+ */
+void toolbar_apply_settings(VikToolbar *vtb,
+ GtkWidget *vbox,
+ GtkWidget *hbox,
+ gboolean reset)
+{
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+
+ if ( reset ) {
+ g_object_ref (vtb->widget); // ensure not deleted when removed
+ // Try both places it could be
+ if ( gtk_widget_get_parent (vtb->widget) == hbox )
+ gtk_container_remove(GTK_CONTAINER(hbox), vtb->widget );
+ if ( gtk_widget_get_parent (vtb->widget) == vbox )
+ gtk_container_remove(GTK_CONTAINER(vbox), vtb->widget );
}
- main_widgets.toolbar = gtk_ui_manager_get_widget(uim, "/ui/GeanyToolbar");
- ui_init_toolbar_widgets();
+
+ toolbar_set_icon_style(vtb->widget);
+ toolbar_set_icon_size(vtb->widget);
/* add the toolbar again to the main window */
- if (toolbar_prefs.append_to_menu)
+ // Use reorder to ensure toolbar always comes after the menu
+ if (prefs_get_append_to_menu())
{
- GtkWidget *hbox_menubar = ui_lookup_widget(main_widgets.window, "hbox_menubar");
- gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
- gtk_box_reorder_child(GTK_BOX(hbox_menubar), main_widgets.toolbar, 1);
+ if ( hbox ) {
+ gtk_box_pack_start(GTK_BOX(hbox), vtb->widget, TRUE, TRUE, 0);
+ gtk_box_reorder_child(GTK_BOX(hbox), vtb->widget, 1);
+ }
}
else
{
- GtkWidget *box = ui_lookup_widget(main_widgets.window, "vbox1");
-
- gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
- gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
+ if ( vbox ) {
+ gtk_box_pack_start(GTK_BOX(vbox), vtb->widget, FALSE, TRUE, 0);
+ gtk_box_reorder_child(GTK_BOX(vbox), vtb->widget, 1);
+ }
}
- gtk_widget_show(main_widgets.toolbar);
+}
+
+/**
+ * toolbar_get_widget:
+ *
+ */
+GtkWidget* toolbar_get_widget(VikToolbar *vtb)
+{
+ g_return_val_if_fail(VIK_IS_TOOLBAR(vtb), NULL);
+ return vtb->widget;
+}
- /* re-add und unref the plugin toolbar items */
- i = toolbar_get_insert_position();
- foreach_slist(l, plugin_items)
+#include "toolbar.xml.h"
+static void toolbar_reload ( VikToolbar *vtb,
+ const gchar *markup,
+ GtkWindow *parent,
+ GtkWidget *vbox,
+ GtkWidget *hbox,
+ ReloadCB reload_cb,
+ gpointer user_data )
+{
+ GError *error = NULL;
+ g_debug ( "%s: %d", __FUNCTION__, g_hash_table_size(signal_data) );
+
+ /* Cleanup old toolbar */
+ if (vtb->merge_id > 0)
{
- gtk_toolbar_insert(GTK_TOOLBAR(main_widgets.toolbar), l->data, i);
- g_object_unref(l->data);
- i++;
+ /* Get rid of it! */
+ gtk_widget_destroy(vtb->widget);
+
+ gtk_ui_manager_remove_ui(vtb->uim, vtb->merge_id);
+ gtk_ui_manager_ensure_update(vtb->uim);
+
+ g_hash_table_remove ( signal_data, vtb );
}
- /* re-add und unref the submenus of menu toolbar items */
- if (toolbar_new_file_menu != NULL)
+
+ if (markup != NULL)
{
- geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION(
- gtk_action_group_get_action(group, "New")), toolbar_new_file_menu);
- g_object_unref(toolbar_new_file_menu);
+ vtb->merge_id = gtk_ui_manager_add_ui_from_string(vtb->uim, markup, -1, &error);
}
- if (toolbar_recent_files_menu != NULL)
+ else
{
- geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION(
- gtk_action_group_get_action(group, "Open")), toolbar_recent_files_menu);
- g_object_unref(toolbar_recent_files_menu);
+ gchar *filename = NULL;
+ /* Load the toolbar UI XML file from disk */
+ // Consider using a_get_viking_data_path() first
+ filename = g_build_filename (a_get_viking_dir(), "ui_toolbar.xml", NULL);
+ vtb->merge_id = gtk_ui_manager_add_ui_from_file(vtb->uim, filename, &error);
+ g_free(filename);
}
- if (toolbar_build_menu != NULL)
+ if (error != NULL)
{
- geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION(
- gtk_action_group_get_action(group, "Build")), toolbar_build_menu);
- g_object_unref(toolbar_build_menu);
+ g_debug("UI creation failed, using internal fallback definition. Error message: %s", error->message);
+ g_error_free(error);
+ error = NULL;
+
+ /* finally load the internally defined markup as fallback */
+ vtb->merge_id = gtk_ui_manager_add_ui_from_string(vtb->uim, toolbar_xml, -1, &error);
+ if (error) {
+ // Abort - this should only happen if you're missing around with the code
+ g_error("Internal UI creation failed. Error message: %s", error->message);
+ }
+
}
+ vtb->widget = gtk_ui_manager_get_widget(vtb->uim, "/ui/MainToolbar");
/* update button states */
- if (main_status.main_window_realized)
- {
- GeanyDocument *doc = document_get_current();
- gboolean doc_changed = (doc != NULL) ? doc->changed : FALSE;
+ reload_cb ( vtb->group_actions, user_data );
- ui_document_buttons_update();
- ui_save_buttons_toggle(doc_changed); /* update save all */
- ui_update_popup_reundo_items(doc);
+ toolbar_apply_settings(vtb, vbox, hbox, FALSE);
- toolbar_apply_settings();
- }
+ gtk_widget_show(vtb->widget);
/* Signals */
- g_signal_connect(main_widgets.toolbar, "button-press-event",
- G_CALLBACK(toolbar_popup_menu), NULL);
- g_signal_connect(main_widgets.toolbar, "key-press-event",
- G_CALLBACK(on_escape_key_press_event), NULL);
+ config_t *data = g_malloc(sizeof(config_t));
+ data->vtb = vtb;
+ data->parent = parent;
+ data->vbox = vbox;
+ data->hbox = hbox;
+ data->reload_cb = reload_cb;
+ data->user_data = user_data;
+
+ // Store data in a hash so it can be freed when the toolbar is reconfigured
+ g_hash_table_insert (signal_data, vtb, data);
+
+ g_signal_connect(vtb->widget, "button-press-event", G_CALLBACK(toolbar_popup_menu), data);
/* We don't need to disconnect those signals as this is done automatically when the entry
* widgets are destroyed, happens when the toolbar itself is destroyed. */
- entry = toolbar_get_widget_child_by_name("SearchEntry");
- if (entry != NULL)
- g_signal_connect(entry, "motion-notify-event", G_CALLBACK(on_motion_event), NULL);
- entry = toolbar_get_widget_child_by_name("GotoEntry");
- if (entry != NULL)
- g_signal_connect(entry, "motion-notify-event", G_CALLBACK(on_motion_event), NULL);
-
- return main_widgets.toolbar;
}
-
static void toolbar_notify_style_cb(GObject *object, GParamSpec *arg1, gpointer data)
{
const gchar *arg_name = g_param_spec_get_name(arg1);
gint value;
- if (toolbar_prefs.use_gtk_default_style && utils_str_equal(arg_name, "gtk-toolbar-style"))
+ if (prefs_get_icon_style() == 0 && !g_strcmp0(arg_name, "gtk-toolbar-style"))
{
- value = ui_get_gtk_settings_integer(arg_name, toolbar_prefs.icon_style);
- gtk_toolbar_set_style(GTK_TOOLBAR(main_widgets.toolbar), value);
+ value = ui_get_gtk_settings_integer(arg_name, GTK_TOOLBAR_ICONS);
+ if ( GTK_IS_TOOLBAR (data) )
+ gtk_toolbar_set_style(GTK_TOOLBAR(data), value);
}
- else if (toolbar_prefs.use_gtk_default_icon && utils_str_equal(arg_name, "gtk-toolbar-size"))
+ else if (prefs_get_icon_size() == 0 && !g_strcmp0(arg_name, "gtk-toolbar-size"))
{
- value = ui_get_gtk_settings_integer(arg_name, toolbar_prefs.icon_size);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(main_widgets.toolbar), value);
+ value = ui_get_gtk_settings_integer(arg_name, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ if ( GTK_IS_TOOLBAR (data) )
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(data), value);
}
}
-
-GtkWidget *toolbar_init(void)
+/**
+ * toolbar_init:
+ *
+ * Initialize the specified toolbar using the given values
+ */
+void toolbar_init (VikToolbar *vtb,
+ GtkWindow *parent,
+ GtkWidget *vbox,
+ GtkWidget *hbox,
+ ToolCB tool_cb,
+ ReloadCB reload_cb,
+ gpointer user_data)
{
- GtkWidget *toolbar;
- GtkAction *action_new;
- GtkAction *action_open;
- GtkAction *action_build;
- GtkAction *action_searchentry;
- GtkAction *action_gotoentry;
- GtkSettings *gtk_settings;
-
- uim = gtk_ui_manager_new();
- group = gtk_action_group_new("GeanyToolbar");
-
- gtk_action_group_set_translation_domain(group, GETTEXT_PACKAGE);
- gtk_action_group_add_actions(group, ui_entries, ui_entries_n, NULL);
-
- /* Create our custom actions */
- action_new = geany_menu_button_action_new(
- "New", NULL,
- _("Create a new file"),
- _("Create a new file from a template"),
- GTK_STOCK_NEW);
- g_signal_connect(action_new, "button-clicked", G_CALLBACK(on_toolbutton_new_clicked), NULL);
- gtk_action_group_add_action(group, action_new);
-
- action_open = geany_menu_button_action_new(
- "Open", NULL,
- _("Open an existing file"),
- _("Open a recent file"),
- GTK_STOCK_OPEN);
- g_signal_connect(action_open, "button-clicked", G_CALLBACK(on_toolbutton_open_clicked), NULL);
- gtk_action_group_add_action(group, action_open);
-
- action_build = geany_menu_button_action_new(
- "Build", NULL,
- _("Build the current file"),
- _("Choose more build actions"),
- GEANY_STOCK_BUILD);
- g_signal_connect(action_build, "button-clicked",
- G_CALLBACK(build_toolbutton_build_clicked), NULL);
- gtk_action_group_add_action(group, action_build);
-
- action_searchentry = geany_entry_action_new(
- "SearchEntry", _("Search Field"), _("Find the entered text in the current file"), FALSE);
- g_signal_connect(action_searchentry, "entry-activate",
- G_CALLBACK(on_toolbar_search_entry_activate), GINT_TO_POINTER(FALSE));
- g_signal_connect(action_searchentry, "entry-activate-backward",
- G_CALLBACK(on_toolbar_search_entry_activate), GINT_TO_POINTER(TRUE));
- g_signal_connect(action_searchentry, "entry-changed",
- G_CALLBACK(on_toolbar_search_entry_changed), NULL);
- gtk_action_group_add_action(group, action_searchentry);
-
- action_gotoentry = geany_entry_action_new(
- "GotoEntry", _("Goto Field"), _("Jump to the entered line number"), TRUE);
- g_signal_connect(action_gotoentry, "entry-activate",
- G_CALLBACK(on_toolbutton_goto_entry_activate), NULL);
- gtk_action_group_add_action(group, action_gotoentry);
-
- gtk_ui_manager_insert_action_group(uim, group, 0);
-
- toolbar = toolbar_reload(NULL);
-#if GTK_CHECK_VERSION(3, 0, 0)
- gtk_style_context_add_class(gtk_widget_get_style_context(toolbar), "primary-toolbar");
-#endif
-
- gtk_settings = gtk_widget_get_settings(GTK_WIDGET(toolbar));
- if (gtk_settings != NULL)
- {
- g_signal_connect(gtk_settings, "notify::gtk-toolbar-style",
- G_CALLBACK(toolbar_notify_style_cb), NULL);
+ vtb->uim = gtk_ui_manager_new();
+
+ vtb->group_actions = gtk_action_group_new("MainToolbar");
+ gtk_action_group_set_translation_domain(vtb->group_actions, GETTEXT_PACKAGE);
+ GtkActionEntry *actions = NULL;
+ GSList *gl;
+ gint nn = 0;
+ foreach_slist(gl, vtb->list_of_actions) {
+ GtkActionEntry *action = gl->data;
+ actions = g_renew(GtkActionEntry, actions, nn+1);
+ actions[nn] = *action;
+ nn++;
}
-
- return toolbar;
-}
-
-
-void toolbar_update_ui(void)
-{
- static GtkWidget *hbox_menubar = NULL;
- static GtkWidget *menubar = NULL;
- GtkWidget *menubar_toolbar_separator = NULL;
- GtkWidget *parent;
- GtkToolItem *first_item;
-
- if (menubar == NULL)
- { /* cache widget pointers */
- hbox_menubar = ui_lookup_widget(main_widgets.window, "hbox_menubar");
- menubar = ui_lookup_widget(main_widgets.window, "menubar1");
+ gtk_action_group_add_actions(vtb->group_actions, actions, nn, user_data);
+ gtk_ui_manager_insert_action_group(vtb->uim, vtb->group_actions, 0);
+
+ vtb->group_toggles = gtk_action_group_new("UIItems");
+ gtk_action_group_set_translation_domain(vtb->group_toggles, GETTEXT_PACKAGE);
+ GtkToggleActionEntry *toggle_actions = NULL;
+ nn = 0;
+ foreach_slist(gl, vtb->list_of_toggles) {
+ GtkToggleActionEntry *action = gl->data;
+ toggle_actions = g_renew(GtkToggleActionEntry, toggle_actions, nn+1);
+ toggle_actions[nn] = *action;
+ nn++;
}
- /* the separator between the menubar and the toolbar */
- first_item = gtk_toolbar_get_nth_item(GTK_TOOLBAR(main_widgets.toolbar), 0);
- if (first_item != NULL && GTK_IS_SEPARATOR_TOOL_ITEM(first_item))
- {
- gtk_widget_destroy(GTK_WIDGET(first_item));
+ gtk_action_group_add_toggle_actions(vtb->group_toggles, toggle_actions, nn, user_data);
+ gtk_ui_manager_insert_action_group(vtb->uim, vtb->group_toggles, 0);
+
+ vtb->group_tools = gtk_action_group_new("ToolItems");
+ gtk_action_group_set_translation_domain(vtb->group_tools, GETTEXT_PACKAGE);
+
+ GtkRadioActionEntry *tool_actions = NULL;
+ nn = 0;
+ foreach_slist(gl, vtb->list_of_tools) {
+ GtkRadioActionEntry *action = gl->data;
+ tool_actions = g_renew(GtkRadioActionEntry, tool_actions, nn+1);
+ tool_actions[nn] = *action;
+ tool_actions[nn].value = nn;
+ nn++;
}
-
- parent = gtk_widget_get_parent(main_widgets.toolbar);
-
- if (toolbar_prefs.append_to_menu)
- {
- if (parent != NULL)
- {
- if (parent != hbox_menubar)
- { /* here we manually 'reparent' the toolbar, gtk_widget_reparent() doesn't
- * like to do it */
- g_object_ref(main_widgets.toolbar);
-
- gtk_container_remove(GTK_CONTAINER(parent), main_widgets.toolbar);
- gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
- gtk_box_reorder_child(GTK_BOX(hbox_menubar), main_widgets.toolbar, 1);
-
- g_object_unref(main_widgets.toolbar);
- }
- }
- else
- gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
-
- /* the separator between the menubar and the toolbar */
- menubar_toolbar_separator = GTK_WIDGET(gtk_separator_tool_item_new());
- gtk_widget_show(menubar_toolbar_separator);
- gtk_toolbar_insert(GTK_TOOLBAR(main_widgets.toolbar),
- GTK_TOOL_ITEM(menubar_toolbar_separator), 0);
+ gtk_action_group_add_radio_actions(vtb->group_tools, tool_actions, nn, 0, G_CALLBACK(tool_cb), user_data);
+ gtk_ui_manager_insert_action_group(vtb->uim, vtb->group_tools, 0);
+
+ vtb->group_modes = gtk_action_group_new("ModeItems");
+ gtk_action_group_set_translation_domain(vtb->group_modes, GETTEXT_PACKAGE);
+
+ GtkRadioActionEntry *mode_actions = NULL;
+ nn = 0;
+ foreach_slist(gl, vtb->list_of_modes) {
+ GtkRadioActionEntry *action = gl->data;
+ mode_actions = g_renew(GtkRadioActionEntry, mode_actions, nn+1);
+ mode_actions[nn] = *action;
+ mode_actions[nn].value = nn;
+ nn++;
}
- else
- {
- GtkWidget *box = ui_lookup_widget(main_widgets.window, "vbox1");
+ gtk_action_group_add_radio_actions(vtb->group_modes, mode_actions, nn, 0, G_CALLBACK(tool_cb), user_data);
+ gtk_ui_manager_insert_action_group(vtb->uim, vtb->group_modes, 0);
- if (parent != NULL)
- {
- if (parent != box)
- {
- g_object_ref(main_widgets.toolbar);
+ toolbar_reload(vtb, NULL, parent, vbox, hbox, reload_cb, user_data);
- gtk_container_remove(GTK_CONTAINER(parent), main_widgets.toolbar);
- gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
- gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
+#if GTK_CHECK_VERSION(3, 0, 0)
+ gtk_style_context_add_class(gtk_widget_get_style_context(vtb->widget), "primary-toolbar");
+#endif
- g_object_unref(main_widgets.toolbar);
- }
- }
- else
- {
- gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
- gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
- }
+ GtkSettings *gtk_settings = gtk_widget_get_settings(vtb->widget);
+ if (gtk_settings != NULL)
+ {
+ g_signal_connect(gtk_settings, "notify::gtk-toolbar-style",
+ G_CALLBACK(toolbar_notify_style_cb), vtb->widget);
}
- /* we need to adjust the packing flags for the menubar to expand it if it is alone in the
- * hbox and not expand it if the toolbar is appended */
- gtk_box_set_child_packing(GTK_BOX(hbox_menubar), menubar,
- ! (toolbar_prefs.visible && toolbar_prefs.append_to_menu), TRUE, 0, GTK_PACK_START);
-}
+ extra_widget_data.vtb = vtb;
+ extra_widget_data.parent = parent;
+ extra_widget_data.vbox = vbox;
+ extra_widget_data.reload_cb = reload_cb;
+ extra_widget_data.user_data = user_data;
+}
-/* Returns the position for adding new toolbar items. The returned position can be used
- * to add new toolbar items with @c gtk_toolbar_insert(). The toolbar object can be accessed
- * with @a geany->main_widgets->toolbar.
- * The position is always the last one before the Quit button or the very last position if the
- * Quit button is not the last toolbar item.
+/**
+ * toolbar_action_set_sensitive:
*
- * @return The position for new toolbar items.
+ * Set sensitivity of a particular action
*/
-gint toolbar_get_insert_position(void)
+void toolbar_action_set_sensitive (VikToolbar *vtb, const gchar *name, gboolean sensitive)
{
- GtkWidget *quit = toolbar_get_widget_by_name("Quit");
- gint quit_pos = -1, pos;
-
- if (quit != NULL)
- quit_pos = gtk_toolbar_get_item_index(GTK_TOOLBAR(main_widgets.toolbar), GTK_TOOL_ITEM(quit));
-
- pos = gtk_toolbar_get_n_items(GTK_TOOLBAR(main_widgets.toolbar));
- if (quit_pos == (pos - 1))
- {
- /* if the toolbar item before the quit button is a separator, insert new items before */
- if (GTK_IS_SEPARATOR_TOOL_ITEM(gtk_toolbar_get_nth_item(
- GTK_TOOLBAR(main_widgets.toolbar), quit_pos - 1)))
- {
- return quit_pos - 1;
- }
- /* else return the position of the quit button to insert new items before */
- return quit_pos;
- }
-
- return pos;
+ g_return_if_fail(VIK_IS_TOOLBAR(vtb));
+ g_return_if_fail(name != NULL);
+ // Try all groups
+ GtkAction *action = get_action ( vtb, name );
+ if ( action )
+ g_object_set ( action, "sensitive", sensitive, NULL);
}
-
-void toolbar_finalize(void)
+/**
+ * vik_toolbar_finalize:
+ *
+ * Memory cleanups upon toolbar destruction
+ */
+void vik_toolbar_finalize ( VikToolbar *vtb )
{
- GeanyMenubuttonAction *open_action = GEANY_MENU_BUTTON_ACTION(toolbar_get_action_by_name("Open"));
- g_object_unref(geany_menu_button_action_get_menu(open_action));
- geany_menu_button_action_set_menu(open_action, NULL);
+ g_hash_table_remove ( signal_data, vtb );
/* unref'ing the GtkUIManager object will destroy all its widgets unless they were ref'ed */
- g_object_unref(uim);
- g_object_unref(group);
-
- g_slist_free(plugin_items);
-}
-
-
-void toolbar_show_hide(void)
-{
- ignore_callback = TRUE;
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- ui_lookup_widget(main_widgets.window, "menu_show_toolbar1")), toolbar_prefs.visible);
- ui_widget_show_hide(main_widgets.toolbar, toolbar_prefs.visible);
- ignore_callback = FALSE;
-}
-
-
-/* sets the icon style of the toolbar */
-static void toolbar_set_icon_style(void)
-{
- gint icon_style;
-
- icon_style = toolbar_prefs.icon_style;
-
- if (toolbar_prefs.use_gtk_default_style)
- icon_style = ui_get_gtk_settings_integer("gtk-toolbar-style", toolbar_prefs.icon_style);
-
- gtk_toolbar_set_style(GTK_TOOLBAR(main_widgets.toolbar), icon_style);
-}
-
-
-/* sets the icon size of the toolbar */
-static void toolbar_set_icon_size(void)
-{
- gint icon_size;
-
- icon_size = toolbar_prefs.icon_size;
-
- if (toolbar_prefs.use_gtk_default_icon)
- icon_size = ui_get_gtk_settings_integer("gtk-toolbar-icon-size", toolbar_prefs.icon_size);
-
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(main_widgets.toolbar), icon_size);
-}
-
-
-void toolbar_apply_settings(void)
-{
- toolbar_set_icon_style();
- toolbar_set_icon_size();
+ g_object_unref(vtb->uim);
+ g_object_unref(vtb->group_actions);
+ g_object_unref(vtb->group_tools);
+ g_object_unref(vtb->group_toggles);
+ g_object_unref(vtb->group_modes);
+
+ g_slist_free(vtb->list_of_actions);
+ g_slist_free(vtb->list_of_tools);
+ g_slist_free(vtb->list_of_toggles);
+ g_slist_free(vtb->list_of_modes);
}
GtkTreeViewDropPosition last_drag_pos;
GtkWidget *drag_source;
+
+ config_t config;
} TBEditorWidget;
static const GtkTargetEntry tb_editor_dnd_targets[] =
{
- { "GEANY_TB_EDITOR_ROW", 0, 0 }
+ { "VIKING_TB_EDITOR_ROW", 0, 0 }
};
static const gint tb_editor_dnd_targets_len = G_N_ELEMENTS(tb_editor_dnd_targets);
GSList **actions = data;
/* This is very basic parsing, stripped down any error checking, requires a valid UI markup. */
- if (utils_str_equal(element_name, "separator"))
+ if (!g_strcmp0(element_name, "separator"))
*actions = g_slist_append(*actions, g_strdup(TB_EDITOR_SEPARATOR));
for (i = 0; attribute_names[i] != NULL; i++)
{
- if (utils_str_equal(attribute_names[i], "action"))
+ if (!g_strcmp0(attribute_names[i], "action"))
{
*actions = g_slist_append(*actions, g_strdup(attribute_values[i]));
}
}
-static void tb_editor_set_item_values(const gchar *name, GtkListStore *store, GtkTreeIter *iter)
+static void tb_editor_set_item_values(VikToolbar *vtb, const gchar *name, GtkListStore *store, GtkTreeIter *iter)
{
gchar *icon = NULL;
gchar *label = NULL;
gchar *label_clean = NULL;
- GtkAction *action;
- action = gtk_action_group_get_action(group, name);
- if (action == NULL)
- {
- if (utils_str_equal(name, TB_EDITOR_SEPARATOR))
+ // Tries all action groups
+ GtkAction *action = get_action ( vtb, name );
+
+ if (action == NULL) {
+ if (!g_strcmp0(name, TB_EDITOR_SEPARATOR))
label_clean = g_strdup(TB_EDITOR_SEPARATOR_LABEL);
else
return;
}
- else
- {
+ if (action != NULL) {
g_object_get(action, "icon-name", &icon, NULL);
if (icon == NULL)
g_object_get(action, "stock-id", &icon, NULL);
g_object_get(action, "label", &label, NULL);
if (label != NULL)
- label_clean = utils_str_remove_chars(g_strdup(label), "_");
+ label_clean = util_str_remove_chars(g_strdup(label), "_");
}
gtk_list_store_set(store, iter,
if (gtk_list_store_remove(tbw->store_used, &iter_used))
gtk_tree_selection_select_iter(selection_used, &iter_used);
- if (! utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
+ if (g_strcmp0(action_name, TB_EDITOR_SEPARATOR))
{
gtk_list_store_append(tbw->store_available, &iter_new);
- tb_editor_set_item_values(action_name, tbw->store_available, &iter_new);
+ tb_editor_set_item_values(tbw->config.vtb, action_name, tbw->store_available, &iter_new);
tb_editor_scroll_to_iter(tbw->tree_available, &iter_new);
}
{
gtk_tree_model_get(model_available, &iter_available,
TB_EDITOR_COL_ACTION, &action_name, -1);
- if (! utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
+ if (g_strcmp0(action_name, TB_EDITOR_SEPARATOR))
{
if (gtk_list_store_remove(tbw->store_available, &iter_available))
gtk_tree_selection_select_iter(selection_available, &iter_available);
else
gtk_list_store_append(tbw->store_used, &iter_new);
- tb_editor_set_item_values(action_name, tbw->store_used, &iter_new);
+ tb_editor_set_item_values(tbw->config.vtb, action_name, tbw->store_used, &iter_new);
tb_editor_scroll_to_iter(tbw->tree_used, &iter_new);
g_free(action_name);
static gboolean tb_editor_drag_motion_cb(GtkWidget *widget, GdkDragContext *drag_context,
- gint x, gint y, guint ltime, TBEditorWidget *tbw)
+ gint x, gint y, guint ltime, TBEditorWidget *tbw)
{
if (tbw->last_drag_path != NULL)
gtk_tree_path_free(tbw->last_drag_path);
static void tb_editor_drag_data_get_cb(GtkWidget *widget, GdkDragContext *context,
- GtkSelectionData *data, guint info, guint ltime,
- TBEditorWidget *tbw)
+ GtkSelectionData *data, guint info, guint ltime,
+ TBEditorWidget *tbw)
{
GtkTreeIter iter;
GtkTreeSelection *selection;
gchar *text = NULL;
text = (gchar*) gtk_selection_data_get_data(data);
- is_sep = utils_str_equal(text, TB_EDITOR_SEPARATOR);
+ is_sep = !g_strcmp0(text, TB_EDITOR_SEPARATOR);
/* If the source of the action is equal to the target, we do just re-order and so need
* to delete the separator to get it moved, not just copied. */
if (is_sep && widget == tbw->drag_source)
else
gtk_list_store_append(store, &iter);
- tb_editor_set_item_values(text, store, &iter);
+ tb_editor_set_item_values(tbw->config.vtb, text, store, &iter);
tb_editor_scroll_to_iter(tree, &iter);
}
if (tree != tbw->tree_used || ! is_sep)
static gboolean tb_editor_foreach_used(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
+ GtkTreeIter *iter, gpointer data)
{
gchar *action_name;
gtk_tree_model_get(model, iter, TB_EDITOR_COL_ACTION, &action_name, -1);
- if (utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
+ if (!g_strcmp0(action_name, TB_EDITOR_SEPARATOR))
g_string_append_printf(data, "\t\t<separator/>\n");
else if (G_LIKELY(!EMPTY(action_name)))
g_string_append_printf(data, "\t\t<toolitem action='%s' />\n", action_name);
{
/* <ui> must be the first tag, otherwise gtk_ui_manager_add_ui_from_string() will fail. */
const gchar *template = "<ui>\n<!--\n\
-This is Geany's toolbar UI definition.\nThe DTD can be found at \n\
+This is Viking's toolbar UI definition.\nThe DTD can be found at \n\
http://library.gnome.org/devel/gtk/stable/GtkUIManager.html#GtkUIManager.description.\n\n\
-You can re-order all items and freely add and remove available actions.\n\
-You cannot add new actions which are not listed in the documentation.\n\
-Everything you add or change must be inside the /ui/toolbar/ path.\n\n\
-For changes to take effect, you need to restart Geany. Alternatively you can use the toolbar\n\
-editor in Geany.\n\n\
-A list of available actions can be found in the documentation included with Geany or\n\
-at http://www.geany.org/manual/current/index.html#customizing-the-toolbar.\n-->\n\
-\t<toolbar name='GeanyToolbar'>\n";
- gchar *filename;
+Generally one should use the toolbar editor in Viking rather than editing this file.\n\n\
+For manual changes to this file to take effect, you need to restart Viking.\n-->\n\
+\t<toolbar name='MainToolbar'>\n";
GString *str = g_string_new(template);
gtk_tree_model_foreach(GTK_TREE_MODEL(tbw->store_used), tb_editor_foreach_used, str);
- g_string_append(str, "\n\t</toolbar>\n</ui>\n");
+ g_string_append(str, "\t</toolbar>\n</ui>\n");
- toolbar_reload(str->str);
+ toolbar_reload(tbw->config.vtb,
+ str->str,
+ tbw->config.parent,
+ tbw->config.vbox,
+ tbw->config.hbox,
+ tbw->config.reload_cb,
+ tbw->config.user_data);
- filename = g_build_filename(app->configdir, "ui_toolbar.xml", NULL);
- utils_write_file(filename, str->str);
+ // ATM always save the toolbar when changed
+ gchar *filename = g_build_filename(a_get_viking_dir (), "ui_toolbar.xml", NULL);
+ GError *error = NULL;
+ if (! g_file_set_contents(filename, str->str, -1, &error)) {
+ g_warning ("%s: could not write to file %s (%s)", __FUNCTION__, filename, error->message);
+ g_error_free(error);
+ }
g_free(filename);
g_string_free(str, TRUE);
}
-static TBEditorWidget *tb_editor_create_dialog(GtkWindow *parent)
+static TBEditorWidget *tb_editor_create_dialog(VikToolbar *vtb, GtkWindow *parent, GtkWidget *toolbar, GtkWidget *vbox, GtkWidget *menu_hbox, ReloadCB reload_cb, gpointer user_data)
{
- GtkWidget *dialog, *vbox, *hbox, *vbox_buttons, *button_add, *button_remove;
+ GtkWidget *dialog, *hbox, *vbox_buttons, *button_add, *button_remove;
GtkWidget *swin_available, *swin_used, *tree_available, *tree_used, *label;
GtkCellRenderer *text_renderer, *icon_renderer;
GtkTreeViewColumn *column;
- TBEditorWidget *tbw = g_new(TBEditorWidget, 1);
- if (parent == NULL)
- parent = GTK_WINDOW(main_widgets.window);
+ if (parent == NULL) {
+ g_warning ( "No parent" );
+ return NULL;
+ }
+
+ TBEditorWidget *tbw = g_new(TBEditorWidget, 1);
dialog = gtk_dialog_new_with_buttons(_("Customize Toolbar"),
- parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
- vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
- gtk_box_set_spacing(GTK_BOX(vbox), 6);
- gtk_widget_set_name(dialog, "GeanyDialog");
+ GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+ gtk_widget_set_name(dialog, "VikingDialog");
gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
tbw->store_used = gtk_list_store_new(TB_EDITOR_COLS_MAX,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+ tbw->config.vtb = vtb;
+ tbw->config.parent = parent;
+ tbw->config.vbox = vbox;
+ tbw->config.hbox = menu_hbox;
+ tbw->config.reload_cb = reload_cb;
+ tbw->config.user_data = user_data;
+
label = gtk_label_new(
_("Select items to be displayed on the toolbar. Items can be reordered by drag and drop."));
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_box_pack_start(GTK_BOX(hbox), vbox_buttons, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), swin_used, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 6);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
- gtk_widget_show_all(vbox);
+ gtk_widget_show_all(dialog);
g_object_unref(tbw->store_available);
g_object_unref(tbw->store_used);
return tbw;
}
-
-void toolbar_configure(GtkWindow *parent)
+/**
+ * toolbar_configure:
+ *
+ */
+void toolbar_configure (VikToolbar *vtb, GtkWidget *toolbar, GtkWindow *parent, GtkWidget *vbox, GtkWidget *hbox, ReloadCB reload_cb, gpointer user_data)
{
gchar *markup;
const gchar *name;
TBEditorWidget *tbw;
/* read the current active toolbar items */
- markup = gtk_ui_manager_get_ui(uim);
+ markup = gtk_ui_manager_get_ui(vtb->uim);
used_items = tb_editor_parse_ui(markup, -1, NULL);
g_free(markup);
/* get all available actions */
- all_items = gtk_action_group_list_actions(group);
+ all_items = gtk_action_group_list_actions(vtb->group_actions);
+ all_items = g_list_concat ( all_items, gtk_action_group_list_actions(vtb->group_toggles) );
+ all_items = g_list_concat ( all_items, gtk_action_group_list_actions(vtb->group_tools) );
+ all_items = g_list_concat ( all_items, gtk_action_group_list_actions(vtb->group_modes) );
/* create the GUI */
- tbw = tb_editor_create_dialog(parent);
+ tbw = tb_editor_create_dialog(vtb, parent, toolbar, vbox, hbox, reload_cb, user_data);
/* fill the stores */
gtk_list_store_insert_with_values(tbw->store_available, NULL, -1,
if (g_slist_find_custom(used_items, name, (GCompareFunc) strcmp) == NULL)
{
gtk_list_store_append(tbw->store_available, &iter);
- tb_editor_set_item_values(name, tbw->store_available, &iter);
+ tb_editor_set_item_values(vtb, name, tbw->store_available, &iter);
}
}
foreach_slist(sl, used_items)
{
gtk_list_store_append(tbw->store_used, &iter);
- tb_editor_set_item_values(sl->data, tbw->store_used, &iter);
+ tb_editor_set_item_values(vtb, sl->data, tbw->store_used, &iter);
}
/* select first item */
path = gtk_tree_path_new_from_string("0");