~ubuntu-branches/debian/experimental/file-roller/experimental

« back to all changes in this revision

Viewing changes to src/gth-menu-button.c

  • Committer: Package Import Robot
  • Author(s): Andreas Henriksson
  • Date: 2013-03-25 14:07:41 UTC
  • mfrom: (1.6.95)
  • Revision ID: package-import@ubuntu.com-20130325140741-fn92im56sms30zkg
Tags: 3.7.92-1
* New upstream release.
* Drop debian/patches/git_handle_cab.patch, from upstream now in release.
* Bump libgtk-3-dev build-dependency to (>= 3.6.0)
  - source uses GtkMenuButton which is new in 3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#define MENU_ID "gth-menu-button-menu-id"
27
27
 
28
28
struct _GthMenuButtonPrivate {
29
 
        guint      active : 1;
30
 
        GtkMenu   *menu;
31
29
        GtkWidget *icon_widget;
32
30
        GtkWidget *label_widget;
33
31
};
42
40
        PROP_LABEL,
43
41
        PROP_USE_UNDERLINE,
44
42
        PROP_STOCK_ID,
45
 
        PROP_ICON_NAME,
46
 
        PROP_MENU
 
43
        PROP_ICON_NAME
47
44
};
48
45
 
49
46
 
50
47
static int signals[LAST_SIGNAL];
51
48
 
52
49
 
53
 
G_DEFINE_TYPE (GthMenuButton, gth_menu_button, GTK_TYPE_TOGGLE_BUTTON)
54
 
 
55
 
 
56
 
static void
57
 
gth_menu_button_state_changed (GtkWidget    *widget,
58
 
                               GtkStateType  previous_state)
59
 
{
60
 
        GthMenuButton *self = GTH_MENU_BUTTON (widget);
61
 
 
62
 
        if (! gtk_widget_is_sensitive (widget) && (self->priv->menu != NULL))
63
 
                gtk_menu_shell_deactivate (GTK_MENU_SHELL (self->priv->menu));
64
 
}
 
50
G_DEFINE_TYPE (GthMenuButton, gth_menu_button, GTK_TYPE_MENU_BUTTON)
65
51
 
66
52
 
67
53
static void
85
71
        case PROP_ICON_NAME:
86
72
                gth_menu_button_set_icon_name (self, g_value_get_string (value));
87
73
                break;
88
 
        case PROP_MENU:
89
 
                gth_menu_button_set_menu (self, g_value_get_object (value));
90
 
                break;
91
74
        default:
92
75
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
93
76
                break;
116
99
        case PROP_ICON_NAME:
117
100
                g_value_set_string (value, gth_menu_button_get_icon_name (self));
118
101
                break;
119
 
        case PROP_MENU:
120
 
                g_value_set_object (value, self->priv->menu);
121
 
                break;
122
102
        default:
123
103
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124
104
                break;
126
106
}
127
107
 
128
108
 
129
 
/* Callback for the "deactivate" signal on the pop-up menu.
130
 
 * This is used so that we unset the state of the toggle button
131
 
 * when the pop-up menu disappears.
132
 
 */
133
 
static int
134
 
menu_deactivate_cb (GtkMenuShell  *menu_shell,
135
 
                    GthMenuButton *self)
136
 
{
137
 
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self), FALSE);
138
 
        return TRUE;
139
 
}
140
 
 
141
 
 
142
 
static void
143
 
menu_position_func (GtkMenu       *menu,
144
 
                    int           *x,
145
 
                    int           *y,
146
 
                    gboolean      *push_in,
147
 
                    GthMenuButton *self)
148
 
{
149
 
        GtkWidget             *widget = GTK_WIDGET (self);
150
 
        GtkRequisition         menu_req;
151
 
        GtkTextDirection       direction;
152
 
        cairo_rectangle_int_t  monitor;
153
 
        int                    monitor_num;
154
 
        GdkScreen             *screen;
155
 
        GtkAllocation          allocation;
156
 
 
157
 
        gtk_widget_get_preferred_size (GTK_WIDGET (self->priv->menu), &menu_req, NULL);
158
 
 
159
 
        direction = gtk_widget_get_direction (widget);
160
 
 
161
 
        screen = gtk_widget_get_screen (GTK_WIDGET (menu));
162
 
        monitor_num = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (widget));
163
 
        if (monitor_num < 0)
164
 
                monitor_num = 0;
165
 
        gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
166
 
        gtk_widget_get_allocation (widget, &allocation);
167
 
 
168
 
        gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
169
 
        *x += allocation.x;
170
 
        *y += allocation.y;
171
 
 
172
 
        if (direction == GTK_TEXT_DIR_LTR)
173
 
                *x += MAX (allocation.width - menu_req.width, 0);
174
 
        else if (menu_req.width > allocation.width)
175
 
                *x -= menu_req.width - allocation.width;
176
 
 
177
 
        if ((*y + allocation.height + menu_req.height) <= monitor.y + monitor.height)
178
 
                *y += allocation.height;
179
 
        else if ((*y - menu_req.height) >= monitor.y)
180
 
                *y -= menu_req.height;
181
 
        else if (monitor.y + monitor.height - (*y + allocation.height) > *y)
182
 
                *y += allocation.height;
183
 
        else
184
 
                *y -= menu_req.height;
185
 
 
186
 
        *push_in = FALSE;
187
 
}
188
 
 
189
 
 
190
 
static void
191
 
popup_menu_under_button (GthMenuButton  *self,
192
 
                         GdkEventButton *event)
193
 
{
194
 
        g_signal_emit (self, signals[SHOW_MENU], 0);
195
 
 
196
 
        if (self->priv->menu == NULL)
197
 
                return;
198
 
 
199
 
        if (gtk_menu_get_attach_widget (self->priv->menu) != NULL)
200
 
                gtk_menu_detach (self->priv->menu);
201
 
        gtk_menu_popup (self->priv->menu, NULL, NULL,
202
 
                        (GtkMenuPositionFunc) menu_position_func,
203
 
                        self,
204
 
                        event ? event->button : 0,
205
 
                        event ? event->time : gtk_get_current_event_time ());
206
 
}
207
 
 
208
 
 
209
 
static gboolean
210
 
toggle_button_toggled_cb (GtkToggleButton *togglebutton,
211
 
                          gpointer         user_data)
212
 
{
213
 
        GthMenuButton *self = user_data;
214
 
        gboolean       toggle_active = gtk_toggle_button_get_active (togglebutton);
215
 
 
216
 
        if (self->priv->menu == NULL)
217
 
                return FALSE;
218
 
 
219
 
        if (self->priv->active != toggle_active) {
220
 
                self->priv->active = toggle_active;
221
 
                g_object_notify (G_OBJECT (self), "active");
222
 
 
223
 
                if (self->priv->active && ! gtk_widget_get_visible (GTK_WIDGET (self->priv->menu))) {
224
 
                        /* we get here only when the menu is activated by a key
225
 
                         * press, so that we can select the first menu item */
226
 
                        popup_menu_under_button (self, NULL);
227
 
                        gtk_menu_shell_select_first (GTK_MENU_SHELL (self->priv->menu), FALSE);
228
 
                }
229
 
        }
230
 
 
231
 
        return FALSE;
232
 
}
233
 
 
234
 
 
235
109
static gboolean
236
110
toggle_button_press_event_cb (GtkWidget      *widget,
237
111
                              GdkEventButton *event,
239
113
{
240
114
        GthMenuButton *self = user_data;
241
115
 
242
 
        if ((event->button == 1) && (self->priv->menu != NULL))  {
243
 
                popup_menu_under_button (self, event);
244
 
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
116
        if (event->button == 1)
 
117
                g_signal_emit (self, signals[SHOW_MENU], 0);
245
118
 
246
 
                return TRUE;
247
 
        }
248
 
        else
249
 
                return FALSE;
 
119
        return FALSE;
250
120
}
251
121
 
252
122
 
253
123
static void
254
124
gth_menu_button_class_init (GthMenuButtonClass *klass)
255
125
{
256
 
        GObjectClass   *object_class;
257
 
        GtkWidgetClass *widget_class;
 
126
        GObjectClass *object_class;
258
127
 
259
128
        g_type_class_add_private (klass, sizeof (GthMenuButtonPrivate));
260
129
 
262
131
        object_class->set_property = gth_menu_button_set_property;
263
132
        object_class->get_property = gth_menu_button_get_property;
264
133
 
265
 
        widget_class = (GtkWidgetClass *) klass;
266
 
        widget_class->state_changed = gth_menu_button_state_changed;
267
 
 
268
134
        /* signals */
269
135
 
270
136
        /**
319
185
                                                              "The name of the themed icon displayed on the item",
320
186
                                                              NULL,
321
187
                                                              G_PARAM_READABLE | G_PARAM_WRITABLE));
322
 
        g_object_class_install_property (object_class,
323
 
                                         PROP_MENU,
324
 
                                         g_param_spec_object ("menu",
325
 
                                                              "Menu",
326
 
                                                              "The dropdown menu",
327
 
                                                              GTK_TYPE_MENU,
328
 
                                                              G_PARAM_READABLE | G_PARAM_WRITABLE));
329
188
}
330
189
 
331
190
 
341
200
        GtkWidget   *box;
342
201
 
343
202
        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_MENU_BUTTON, GthMenuButtonPrivate);
344
 
        self->priv->menu = NULL;
345
 
        self->priv->active = FALSE;
346
203
 
347
204
        gtk_widget_style_get (GTK_WIDGET (self),
348
205
                              "image-spacing", &image_spacing,
389
246
        /* signals */
390
247
 
391
248
        g_signal_connect (self,
392
 
                          "toggled",
393
 
                          G_CALLBACK (toggle_button_toggled_cb),
394
 
                          self);
395
 
        g_signal_connect (self,
396
249
                          "button-press-event",
397
250
                          G_CALLBACK (toggle_button_press_event_cb),
398
251
                          self);
527
380
        g_return_if_fail (GTH_IS_MENU_BUTTON (self));
528
381
        g_return_if_fail (GTK_IS_MENU (menu) || menu == NULL);
529
382
 
530
 
        if (self->priv->menu != GTK_MENU (menu)) {
531
 
                if ((self->priv->menu != NULL) && gtk_widget_get_visible (GTK_WIDGET (self->priv->menu)))
532
 
                        gtk_menu_shell_deactivate (GTK_MENU_SHELL (self->priv->menu));
533
 
 
534
 
                self->priv->menu = GTK_MENU (menu);
535
 
 
536
 
                if (self->priv->menu != NULL) {
537
 
                        g_object_add_weak_pointer (G_OBJECT (self->priv->menu), (gpointer *) &self->priv->menu);
538
 
 
539
 
                        gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
540
 
                        g_signal_connect (self->priv->menu,
541
 
                                          "deactivate",
542
 
                                          G_CALLBACK (menu_deactivate_cb),
543
 
                                          self);
544
 
                }
545
 
                else
546
 
                        gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
547
 
        }
548
 
 
549
 
        g_object_notify (G_OBJECT (self), "menu");
 
383
        g_object_set (self, "menu", menu, NULL);
550
384
}
551
385
 
552
386
 
553
387
GtkWidget *
554
388
gth_menu_button_get_menu (GthMenuButton *self)
555
389
{
 
390
        GtkWidget *menu;
 
391
 
556
392
        g_return_val_if_fail (GTH_IS_MENU_BUTTON (self), NULL);
557
393
 
558
 
        return GTK_WIDGET (self->priv->menu);
 
394
        g_object_get (self, "menu", &menu, NULL);
 
395
 
 
396
        return menu;
559
397
}