2 * Copyright (C) 2003, 2004 Marco Pesenti Gritti
3 * Copyright (C) 2003, 2004 Christian Persch
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "ev-navigation-action-widget.h"
23 #include <glib/gi18n.h>
26 static void ev_navigation_action_widget_init (EvNavigationActionWidget *action_widget);
27 static void ev_navigation_action_widget_class_init (EvNavigationActionWidgetClass *action_widget);
28 static void ev_navigation_action_widget_toggled (GtkToggleToolButton *toggle);
29 static gboolean ev_navigation_action_widget_button_press_event (GtkWidget *widget,
30 GdkEventButton *event);
32 G_DEFINE_TYPE (EvNavigationActionWidget, ev_navigation_action_widget, GTK_TYPE_TOGGLE_TOOL_BUTTON)
40 static gint signals[LAST_SIGNAL];
43 ev_navigation_action_widget_init (EvNavigationActionWidget *action_widget)
49 ev_navigation_action_widget_class_init (EvNavigationActionWidgetClass *klass)
51 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
52 GtkToggleToolButtonClass *toggle_tool_button_class = GTK_TOGGLE_TOOL_BUTTON_CLASS (klass);
54 widget_class->button_press_event = ev_navigation_action_widget_button_press_event;
55 toggle_tool_button_class->toggled = ev_navigation_action_widget_toggled;
59 g_signal_new ("show-menu",
60 G_OBJECT_CLASS_TYPE (klass),
62 G_STRUCT_OFFSET (EvNavigationActionWidgetClass, show_menu),
64 g_cclosure_marshal_VOID__VOID,
69 menu_deactivate_cb (GtkMenuShell *menu_shell,
70 EvNavigationActionWidget *widget)
72 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (widget), FALSE);
77 menu_detacher (GtkWidget *widget,
80 EvNavigationActionWidget *button = EV_NAVIGATION_ACTION_WIDGET (widget);
81 g_return_if_fail (button->menu == menu);
86 ev_navigation_action_widget_set_menu(EvNavigationActionWidget *button, GtkWidget *menu)
89 if (button->menu == GTK_MENU (menu))
92 if (button->menu && GTK_WIDGET_VISIBLE (button->menu))
93 gtk_menu_shell_deactivate (GTK_MENU_SHELL (button->menu));
96 g_signal_handlers_disconnect_by_func (button->menu,
99 gtk_menu_detach (button->menu);
102 button->menu = GTK_MENU (menu);
105 gtk_menu_attach_to_widget (button->menu, GTK_WIDGET (button),
107 g_signal_connect (button->menu, "deactivate",
108 G_CALLBACK (menu_deactivate_cb), button);
113 menu_position_func (GtkMenu *menu,
117 EvNavigationActionWidget *button)
119 GtkWidget *widget = GTK_WIDGET (button);
120 GtkRequisition menu_req;
121 GtkTextDirection direction;
122 GdkRectangle monitor;
126 gtk_widget_size_request (GTK_WIDGET (button->menu), &menu_req);
127 direction = gtk_widget_get_direction (widget);
128 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
130 monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
133 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
135 gdk_window_get_origin (widget->window, x, y);
136 *x += widget->allocation.x;
137 *y += widget->allocation.y;
139 if (direction == GTK_TEXT_DIR_LTR)
140 *x += MAX (widget->allocation.width - menu_req.width, 0);
141 else if (menu_req.width > widget->allocation.width)
142 *x -= menu_req.width - widget->allocation.width;
144 if ((*y + widget->allocation.height + menu_req.height) <= monitor.y + monitor.height)
145 *y += widget->allocation.height;
146 else if ((*y - menu_req.height) >= monitor.y)
147 *y -= menu_req.height;
148 else if (monitor.y + monitor.height - (*y + widget->allocation.height) > *y)
149 *y += widget->allocation.height;
151 *y -= menu_req.height;
157 popup_menu_under_arrow (EvNavigationActionWidget *button,
158 GdkEventButton *event)
163 g_signal_emit (button, signals[SHOW_MENU], 0);
165 gtk_menu_popup (button->menu, NULL, NULL,
166 (GtkMenuPositionFunc) menu_position_func,
168 event ? event->button : 0,
169 event ? event->time : gtk_get_current_event_time ());
173 ev_navigation_action_widget_toggled (GtkToggleToolButton *toggle)
175 EvNavigationActionWidget *button = EV_NAVIGATION_ACTION_WIDGET (toggle);
179 if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (button)) &&
180 !GTK_WIDGET_VISIBLE (button->menu)) {
181 /* we get here only when the menu is activated by a key
182 * press, so that we can select the first menu item */
183 popup_menu_under_arrow (button, NULL);
184 gtk_menu_shell_select_first (GTK_MENU_SHELL (button->menu), FALSE);
189 ev_navigation_action_widget_button_press_event (GtkWidget *widget,
190 GdkEventButton *event)
192 EvNavigationActionWidget *button = EV_NAVIGATION_ACTION_WIDGET (widget);
193 if (event->button == 1) {
194 popup_menu_under_arrow (button, event);
195 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (button), TRUE);