summaryrefslogtreecommitdiff
path: root/src/caja-navigation-action.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/caja-navigation-action.c')
-rw-r--r--src/caja-navigation-action.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/src/caja-navigation-action.c b/src/caja-navigation-action.c
new file mode 100644
index 00000000..93a43435
--- /dev/null
+++ b/src/caja-navigation-action.c
@@ -0,0 +1,381 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * Caja
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based on ephy-navigation-action.h from Epiphany
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ * Marco Pesenti Gritti
+ *
+ */
+
+#include <config.h>
+
+#include "caja-navigation-action.h"
+#include "caja-navigation-window.h"
+#include "caja-window-private.h"
+#include "caja-navigation-window-slot.h"
+#include <gtk/gtk.h>
+#include <eel/eel-gtk-extensions.h>
+
+static void caja_navigation_action_init (CajaNavigationAction *action);
+static void caja_navigation_action_class_init (CajaNavigationActionClass *class);
+
+static GObjectClass *parent_class = NULL;
+
+#define CAJA_NAVIGATION_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), CAJA_TYPE_NAVIGATION_ACTION, CajaNavigationActionPrivate))
+
+struct CajaNavigationActionPrivate
+{
+ CajaNavigationWindow *window;
+ CajaNavigationDirection direction;
+ char *arrow_tooltip;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ARROW_TOOLTIP,
+ PROP_DIRECTION,
+ PROP_WINDOW
+};
+
+GType
+caja_navigation_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0)
+ {
+ const GTypeInfo type_info =
+ {
+ sizeof (CajaNavigationActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) caja_navigation_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (CajaNavigationAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) caja_navigation_action_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_ACTION,
+ "CajaNavigationAction",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+static gboolean
+should_open_in_new_tab (void)
+{
+ /* FIXME this is duplicated */
+ GdkEvent *event;
+
+ event = gtk_get_current_event ();
+ if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE)
+ {
+ return event->button.button == 2;
+ }
+
+ gdk_event_free (event);
+
+ return FALSE;
+}
+
+static void
+activate_back_or_forward_menu_item (GtkMenuItem *menu_item,
+ CajaNavigationWindow *window,
+ gboolean back)
+{
+ int index;
+
+ g_assert (GTK_IS_MENU_ITEM (menu_item));
+ g_assert (CAJA_IS_NAVIGATION_WINDOW (window));
+
+ index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "user_data"));
+
+ caja_navigation_window_back_or_forward (window, back, index, should_open_in_new_tab ());
+}
+
+static void
+activate_back_menu_item_callback (GtkMenuItem *menu_item, CajaNavigationWindow *window)
+{
+ activate_back_or_forward_menu_item (menu_item, window, TRUE);
+}
+
+static void
+activate_forward_menu_item_callback (GtkMenuItem *menu_item, CajaNavigationWindow *window)
+{
+ activate_back_or_forward_menu_item (menu_item, window, FALSE);
+}
+
+static void
+fill_menu (CajaNavigationWindow *window,
+ GtkWidget *menu,
+ gboolean back)
+{
+ CajaNavigationWindowSlot *slot;
+ GtkWidget *menu_item;
+ int index;
+ GList *list;
+
+ g_assert (CAJA_IS_NAVIGATION_WINDOW (window));
+
+ slot = CAJA_NAVIGATION_WINDOW_SLOT (CAJA_WINDOW (window)->details->active_pane->active_slot);
+
+ list = back ? slot->back_list : slot->forward_list;
+ index = 0;
+ while (list != NULL)
+ {
+ menu_item = caja_bookmark_menu_item_new (CAJA_BOOKMARK (list->data));
+ g_object_set_data (G_OBJECT (menu_item), "user_data", GINT_TO_POINTER (index));
+ gtk_widget_show (GTK_WIDGET (menu_item));
+ g_signal_connect_object (menu_item, "activate",
+ back
+ ? G_CALLBACK (activate_back_menu_item_callback)
+ : G_CALLBACK (activate_forward_menu_item_callback),
+ window, 0);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ list = g_list_next (list);
+ ++index;
+ }
+}
+
+static void
+show_menu_callback (GtkMenuToolButton *button,
+ CajaNavigationAction *action)
+{
+ CajaNavigationActionPrivate *p;
+ CajaNavigationWindow *window;
+ GtkWidget *menu;
+ GList *children;
+ GList *li;
+
+ p = action->priv;
+ window = action->priv->window;
+
+ menu = gtk_menu_tool_button_get_menu (button);
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ for (li = children; li; li = li->next)
+ {
+ gtk_container_remove (GTK_CONTAINER (menu), li->data);
+ }
+ g_list_free (children);
+
+ switch (p->direction)
+ {
+ case CAJA_NAVIGATION_DIRECTION_FORWARD:
+ fill_menu (window, menu, FALSE);
+ break;
+ case CAJA_NAVIGATION_DIRECTION_BACK:
+ fill_menu (window, menu, TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static gboolean
+proxy_button_press_event_cb (GtkButton *button,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ if (event->button == 2)
+ {
+ g_signal_emit_by_name (button, "pressed", 0);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+proxy_button_release_event_cb (GtkButton *button,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ if (event->button == 2)
+ {
+ g_signal_emit_by_name (button, "released", 0);
+ }
+
+ return FALSE;
+}
+
+static void
+connect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+ if (GTK_IS_MENU_TOOL_BUTTON (proxy))
+ {
+ CajaNavigationAction *naction = CAJA_NAVIGATION_ACTION (action);
+ GtkMenuToolButton *button = GTK_MENU_TOOL_BUTTON (proxy);
+ GtkWidget *menu;
+ GtkWidget *child;
+
+ /* set an empty menu, so the arrow button becomes sensitive */
+ menu = gtk_menu_new ();
+ gtk_menu_tool_button_set_menu (button, menu);
+
+ gtk_menu_tool_button_set_arrow_tooltip_text (button,
+ naction->priv->arrow_tooltip);
+
+ g_signal_connect (proxy, "show-menu",
+ G_CALLBACK (show_menu_callback), action);
+
+ /* Make sure that middle click works. Note that there is some code duplication
+ * between here and caja-window-menus.c */
+ child = eel_gtk_menu_tool_button_get_button (button);
+ g_signal_connect (child, "button-press-event", G_CALLBACK (proxy_button_press_event_cb), NULL);
+ g_signal_connect (child, "button-release-event", G_CALLBACK (proxy_button_release_event_cb), NULL);
+ }
+
+ (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+disconnect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+ if (GTK_IS_MENU_TOOL_BUTTON (proxy))
+ {
+ GtkWidget *child;
+
+ g_signal_handlers_disconnect_by_func (proxy, G_CALLBACK (show_menu_callback), action);
+
+ child = eel_gtk_menu_tool_button_get_button (GTK_MENU_TOOL_BUTTON (proxy));
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (proxy_button_press_event_cb), NULL);
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (proxy_button_release_event_cb), NULL);
+ }
+
+ (* GTK_ACTION_CLASS (parent_class)->disconnect_proxy) (action, proxy);
+}
+
+static void
+caja_navigation_action_finalize (GObject *object)
+{
+ CajaNavigationAction *action = CAJA_NAVIGATION_ACTION (object);
+
+ g_free (action->priv->arrow_tooltip);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+caja_navigation_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CajaNavigationAction *nav;
+
+ nav = CAJA_NAVIGATION_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_ARROW_TOOLTIP:
+ g_free (nav->priv->arrow_tooltip);
+ nav->priv->arrow_tooltip = g_value_dup_string (value);
+ break;
+ case PROP_DIRECTION:
+ nav->priv->direction = g_value_get_int (value);
+ break;
+ case PROP_WINDOW:
+ nav->priv->window = CAJA_NAVIGATION_WINDOW (g_value_get_object (value));
+ break;
+ }
+}
+
+static void
+caja_navigation_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CajaNavigationAction *nav;
+
+ nav = CAJA_NAVIGATION_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_ARROW_TOOLTIP:
+ g_value_set_string (value, nav->priv->arrow_tooltip);
+ break;
+ case PROP_DIRECTION:
+ g_value_set_int (value, nav->priv->direction);
+ break;
+ case PROP_WINDOW:
+ g_value_set_object (value, nav->priv->window);
+ break;
+ }
+}
+
+static void
+caja_navigation_action_class_init (CajaNavigationActionClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkActionClass *action_class = GTK_ACTION_CLASS (class);
+
+ object_class->finalize = caja_navigation_action_finalize;
+ object_class->set_property = caja_navigation_action_set_property;
+ object_class->get_property = caja_navigation_action_get_property;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ action_class->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
+ action_class->connect_proxy = connect_proxy;
+ action_class->disconnect_proxy = disconnect_proxy;
+
+ g_object_class_install_property (object_class,
+ PROP_ARROW_TOOLTIP,
+ g_param_spec_string ("arrow-tooltip",
+ "Arrow Tooltip",
+ "Arrow Tooltip",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_DIRECTION,
+ g_param_spec_int ("direction",
+ "Direction",
+ "Direction",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_WINDOW,
+ g_param_spec_object ("window",
+ "Window",
+ "The navigation window",
+ G_TYPE_OBJECT,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (object_class, sizeof(CajaNavigationActionPrivate));
+}
+
+static void
+caja_navigation_action_init (CajaNavigationAction *action)
+{
+ action->priv = CAJA_NAVIGATION_ACTION_GET_PRIVATE (action);
+}