~ubuntu-branches/ubuntu/trusty/evince/trusty-proposed

« back to all changes in this revision

Viewing changes to shell/ev-navigation-action-widget.c

Tags: upstream-0.7.0
ImportĀ upstreamĀ versionĀ 0.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2003, 2004 Marco Pesenti Gritti
 
3
 *  Copyright (C) 2003, 2004 Christian Persch
 
4
 *
 
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)
 
8
 *  any later version.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
#include "ev-navigation-action-widget.h"
 
22
 
 
23
#include <glib/gi18n.h>
 
24
#include <string.h>
 
25
 
 
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);
 
31
 
 
32
G_DEFINE_TYPE (EvNavigationActionWidget, ev_navigation_action_widget, GTK_TYPE_TOGGLE_TOOL_BUTTON)
 
33
 
 
34
enum
 
35
{
 
36
        SHOW_MENU,
 
37
        LAST_SIGNAL
 
38
};
 
39
 
 
40
static gint signals[LAST_SIGNAL];
 
41
 
 
42
static void
 
43
ev_navigation_action_widget_init (EvNavigationActionWidget *action_widget)
 
44
{
 
45
        return;
 
46
}
 
47
 
 
48
static void
 
49
ev_navigation_action_widget_class_init (EvNavigationActionWidgetClass *klass)
 
50
{
 
51
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
52
        GtkToggleToolButtonClass *toggle_tool_button_class = GTK_TOGGLE_TOOL_BUTTON_CLASS (klass);
 
53
 
 
54
        widget_class->button_press_event = ev_navigation_action_widget_button_press_event;
 
55
        toggle_tool_button_class->toggled = ev_navigation_action_widget_toggled;
 
56
 
 
57
 
 
58
        signals[SHOW_MENU] =
 
59
                  g_signal_new ("show-menu",
 
60
                                G_OBJECT_CLASS_TYPE (klass),
 
61
                                G_SIGNAL_RUN_FIRST,
 
62
                                G_STRUCT_OFFSET (EvNavigationActionWidgetClass, show_menu),
 
63
                                NULL, NULL,
 
64
                                g_cclosure_marshal_VOID__VOID,
 
65
                                G_TYPE_NONE, 0);
 
66
}
 
67
 
 
68
static int
 
69
menu_deactivate_cb (GtkMenuShell      *menu_shell,
 
70
                    EvNavigationActionWidget *widget)
 
71
{
 
72
         gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (widget), FALSE);
 
73
         return TRUE;
 
74
}
 
75
                  
 
76
static void
 
77
menu_detacher (GtkWidget *widget,
 
78
               GtkMenu   *menu)
 
79
{
 
80
         EvNavigationActionWidget *button = EV_NAVIGATION_ACTION_WIDGET (widget);
 
81
         g_return_if_fail (button->menu == menu);
 
82
         button->menu = NULL;
 
83
}
 
84
 
 
85
void
 
86
ev_navigation_action_widget_set_menu(EvNavigationActionWidget *button, GtkWidget *menu)
 
87
{
 
88
 
 
89
      if (button->menu == GTK_MENU (menu))
 
90
                return;
 
91
        
 
92
      if (button->menu && GTK_WIDGET_VISIBLE (button->menu))
 
93
                gtk_menu_shell_deactivate (GTK_MENU_SHELL (button->menu));
 
94
 
 
95
      if (button->menu) {
 
96
                g_signal_handlers_disconnect_by_func (button->menu, 
 
97
                                                menu_deactivate_cb, 
 
98
                                                button);
 
99
                gtk_menu_detach (button->menu);
 
100
       }
 
101
 
 
102
       button->menu = GTK_MENU (menu);
 
103
 
 
104
       if (button->menu) {
 
105
                gtk_menu_attach_to_widget (button->menu, GTK_WIDGET (button),
 
106
                                           menu_detacher);
 
107
                g_signal_connect (button->menu, "deactivate",
 
108
                                  G_CALLBACK (menu_deactivate_cb), button);
 
109
        }
 
110
}
 
111
 
 
112
static void
 
113
menu_position_func (GtkMenu           *menu,
 
114
                    int               *x,
 
115
                    int               *y,
 
116
                    gboolean          *push_in,
 
117
                    EvNavigationActionWidget *button)
 
118
{
 
119
        GtkWidget *widget = GTK_WIDGET (button);
 
120
        GtkRequisition menu_req;
 
121
        GtkTextDirection direction;
 
122
        GdkRectangle monitor;
 
123
        gint monitor_num;
 
124
        GdkScreen *screen;
 
125
 
 
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));
 
129
 
 
130
        monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
 
131
        if (monitor_num < 0)
 
132
                monitor_num = 0;
 
133
        gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
 
134
 
 
135
        gdk_window_get_origin (widget->window, x, y);
 
136
        *x += widget->allocation.x;
 
137
        *y += widget->allocation.y;
 
138
 
 
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;
 
143
 
 
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;
 
150
        else
 
151
                *y -= menu_req.height; 
 
152
 
 
153
        *push_in = FALSE;
 
154
}
 
155
 
 
156
static void
 
157
popup_menu_under_arrow (EvNavigationActionWidget *button,
 
158
                        GdkEventButton    *event)
 
159
{
 
160
        if (!button->menu)
 
161
                return;
 
162
 
 
163
        g_signal_emit (button, signals[SHOW_MENU], 0);
 
164
 
 
165
        gtk_menu_popup (button->menu, NULL, NULL, 
 
166
                        (GtkMenuPositionFunc) menu_position_func,
 
167
                         button,
 
168
                         event ? event->button : 0,
 
169
                         event ? event->time : gtk_get_current_event_time ());
 
170
}
 
171
 
 
172
static void
 
173
ev_navigation_action_widget_toggled (GtkToggleToolButton *toggle)
 
174
{
 
175
        EvNavigationActionWidget *button = EV_NAVIGATION_ACTION_WIDGET (toggle);
 
176
        if (!button->menu)
 
177
                return;
 
178
 
 
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);
 
185
        }
 
186
}
 
187
 
 
188
static gboolean
 
189
ev_navigation_action_widget_button_press_event (GtkWidget *widget,
 
190
                                                GdkEventButton    *event)
 
191
{
 
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);
 
196
                 return TRUE;
 
197
        }
 
198
        return FALSE;
 
199
}