diff options
Diffstat (limited to 'src/caja-navigation-action.c')
-rw-r--r-- | src/caja-navigation-action.c | 381 |
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); +} |