~ubuntu-branches/ubuntu/utopic/gtk+2.0/utopic

« back to all changes in this revision

Viewing changes to .pc/043_ubuntu_menu_proxy.patch/gtk/gtkmenuitem.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2013-06-07 17:15:49 UTC
  • Revision ID: package-import@ubuntu.com-20130607171549-mxb2rt9jscf01sfb
Tags: 2.24.18-0ubuntu2
* debian/patches/043_ubuntu_menu_proxy.patch,
  debian/patches/072_indicator_menu_update.patch,
  debian/libgtk2.0-0.symbols:
  - drop old menu patches, we deprecate appmenu-gtk in favor of the new
    unity-gtk-module code
* debian/patches/gtk-shell-shows-menubar.patch:
  -list gtk-shell-shows-menubar setting, that's required to have 
   the local menubars hidding under unity in favor of the unity ones, 
   thanks William Hua for the work on those changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* GTK - The GIMP Toolkit
2
 
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 */
19
 
 
20
 
/*
21
 
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22
 
 * file for a list of people on the GTK+ Team.  See the ChangeLog
23
 
 * files for a list of changes.  These files are distributed with
24
 
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25
 
 */
26
 
 
27
 
#define GTK_MENU_INTERNALS
28
 
 
29
 
#include "config.h"
30
 
#include <string.h>
31
 
 
32
 
#include "gtkaccellabel.h"
33
 
#include "gtkmain.h"
34
 
#include "gtkmarshalers.h"
35
 
#include "gtkmenu.h"
36
 
#include "gtkmenubar.h"
37
 
#include "gtkseparatormenuitem.h"
38
 
#include "gtkprivate.h"
39
 
#include "gtkbuildable.h"
40
 
#include "gtkactivatable.h"
41
 
#include "gtkintl.h"
42
 
#include "gtkalias.h"
43
 
 
44
 
 
45
 
typedef struct {
46
 
  GtkAction *action;
47
 
  gboolean   use_action_appearance;
48
 
} GtkMenuItemPrivate;
49
 
 
50
 
enum {
51
 
  ACTIVATE,
52
 
  ACTIVATE_ITEM,
53
 
  TOGGLE_SIZE_REQUEST,
54
 
  TOGGLE_SIZE_ALLOCATE,
55
 
  LAST_SIGNAL
56
 
};
57
 
 
58
 
enum {
59
 
  PROP_0,
60
 
  PROP_RIGHT_JUSTIFIED,
61
 
  PROP_SUBMENU,
62
 
  PROP_ACCEL_PATH,
63
 
  PROP_LABEL,
64
 
  PROP_USE_UNDERLINE,
65
 
 
66
 
  /* activatable properties */
67
 
  PROP_ACTIVATABLE_RELATED_ACTION,
68
 
  PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
69
 
};
70
 
 
71
 
 
72
 
static void gtk_menu_item_dispose        (GObject          *object);
73
 
static void gtk_menu_item_set_property   (GObject          *object,
74
 
                                          guint             prop_id,
75
 
                                          const GValue     *value,
76
 
                                          GParamSpec       *pspec);
77
 
static void gtk_menu_item_get_property   (GObject          *object,
78
 
                                          guint             prop_id,
79
 
                                          GValue           *value,
80
 
                                          GParamSpec       *pspec);
81
 
static void gtk_menu_item_destroy        (GtkObject        *object);
82
 
static void gtk_menu_item_size_request   (GtkWidget        *widget,
83
 
                                          GtkRequisition   *requisition);
84
 
static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
85
 
                                          GtkAllocation    *allocation);
86
 
static void gtk_menu_item_realize        (GtkWidget        *widget);
87
 
static void gtk_menu_item_unrealize      (GtkWidget        *widget);
88
 
static void gtk_menu_item_map            (GtkWidget        *widget);
89
 
static void gtk_menu_item_unmap          (GtkWidget        *widget);
90
 
static void gtk_menu_item_paint          (GtkWidget        *widget,
91
 
                                          GdkRectangle     *area);
92
 
static gint gtk_menu_item_expose         (GtkWidget        *widget,
93
 
                                          GdkEventExpose   *event);
94
 
static void gtk_menu_item_parent_set     (GtkWidget        *widget,
95
 
                                          GtkWidget        *previous_parent);
96
 
 
97
 
 
98
 
static void gtk_real_menu_item_select               (GtkItem     *item);
99
 
static void gtk_real_menu_item_deselect             (GtkItem     *item);
100
 
static void gtk_real_menu_item_activate             (GtkMenuItem *item);
101
 
static void gtk_real_menu_item_activate_item        (GtkMenuItem *item);
102
 
static void gtk_real_menu_item_toggle_size_request  (GtkMenuItem *menu_item,
103
 
                                                     gint        *requisition);
104
 
static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
105
 
                                                     gint         allocation);
106
 
static gboolean gtk_menu_item_mnemonic_activate     (GtkWidget   *widget,
107
 
                                                     gboolean     group_cycling);
108
 
 
109
 
static void gtk_menu_item_ensure_label   (GtkMenuItem      *menu_item);
110
 
static gint gtk_menu_item_popup_timeout  (gpointer          data);
111
 
static void gtk_menu_item_position_menu  (GtkMenu          *menu,
112
 
                                          gint             *x,
113
 
                                          gint             *y,
114
 
                                          gboolean         *push_in,
115
 
                                          gpointer          user_data);
116
 
static void gtk_menu_item_show_all       (GtkWidget        *widget);
117
 
static void gtk_menu_item_hide_all       (GtkWidget        *widget);
118
 
static void gtk_menu_item_forall         (GtkContainer    *container,
119
 
                                          gboolean         include_internals,
120
 
                                          GtkCallback      callback,
121
 
                                          gpointer         callback_data);
122
 
static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
123
 
                                                  guint      signal_id);
124
 
 
125
 
static void gtk_real_menu_item_set_label (GtkMenuItem     *menu_item,
126
 
                                          const gchar     *label);
127
 
static const gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
128
 
 
129
 
 
130
 
static void gtk_menu_item_buildable_interface_init (GtkBuildableIface   *iface);
131
 
static void gtk_menu_item_buildable_add_child      (GtkBuildable        *buildable,
132
 
                                                    GtkBuilder          *builder,
133
 
                                                    GObject             *child,
134
 
                                                    const gchar         *type);
135
 
static void gtk_menu_item_buildable_custom_finished(GtkBuildable        *buildable,
136
 
                                                    GtkBuilder          *builder,
137
 
                                                    GObject             *child,
138
 
                                                    const gchar         *tagname,
139
 
                                                    gpointer             user_data);
140
 
 
141
 
static void gtk_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
142
 
static void gtk_menu_item_update                     (GtkActivatable       *activatable,
143
 
                                                      GtkAction            *action,
144
 
                                                      const gchar          *property_name);
145
 
static void gtk_menu_item_sync_action_properties     (GtkActivatable       *activatable,
146
 
                                                      GtkAction            *action);
147
 
static void gtk_menu_item_set_related_action         (GtkMenuItem          *menu_item, 
148
 
                                                      GtkAction            *action);
149
 
static void gtk_menu_item_set_use_action_appearance  (GtkMenuItem          *menu_item, 
150
 
                                                      gboolean              use_appearance);
151
 
 
152
 
 
153
 
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
154
 
 
155
 
static GtkBuildableIface *parent_buildable_iface;
156
 
 
157
 
G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
158
 
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
159
 
                                                gtk_menu_item_buildable_interface_init)
160
 
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
161
 
                                                gtk_menu_item_activatable_interface_init))
162
 
 
163
 
#define GET_PRIVATE(object)  \
164
 
  (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
165
 
 
166
 
static void
167
 
gtk_menu_item_class_init (GtkMenuItemClass *klass)
168
 
{
169
 
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
170
 
  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
171
 
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
172
 
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
173
 
  GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
174
 
 
175
 
  gobject_class->dispose      = gtk_menu_item_dispose;
176
 
  gobject_class->set_property = gtk_menu_item_set_property;
177
 
  gobject_class->get_property = gtk_menu_item_get_property;
178
 
 
179
 
  object_class->destroy = gtk_menu_item_destroy;
180
 
 
181
 
  widget_class->size_request = gtk_menu_item_size_request;
182
 
  widget_class->size_allocate = gtk_menu_item_size_allocate;
183
 
  widget_class->expose_event = gtk_menu_item_expose;
184
 
  widget_class->realize = gtk_menu_item_realize;
185
 
  widget_class->unrealize = gtk_menu_item_unrealize;
186
 
  widget_class->map = gtk_menu_item_map;
187
 
  widget_class->unmap = gtk_menu_item_unmap;
188
 
  widget_class->show_all = gtk_menu_item_show_all;
189
 
  widget_class->hide_all = gtk_menu_item_hide_all;
190
 
  widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
191
 
  widget_class->parent_set = gtk_menu_item_parent_set;
192
 
  widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
193
 
  
194
 
  container_class->forall = gtk_menu_item_forall;
195
 
 
196
 
  item_class->select      = gtk_real_menu_item_select;
197
 
  item_class->deselect    = gtk_real_menu_item_deselect;
198
 
 
199
 
  klass->activate             = gtk_real_menu_item_activate;
200
 
  klass->activate_item        = gtk_real_menu_item_activate_item;
201
 
  klass->toggle_size_request  = gtk_real_menu_item_toggle_size_request;
202
 
  klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
203
 
  klass->set_label            = gtk_real_menu_item_set_label;
204
 
  klass->get_label            = gtk_real_menu_item_get_label;
205
 
 
206
 
  klass->hide_on_activate = TRUE;
207
 
 
208
 
  menu_item_signals[ACTIVATE] =
209
 
    g_signal_new (I_("activate"),
210
 
                  G_OBJECT_CLASS_TYPE (gobject_class),
211
 
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
212
 
                  G_STRUCT_OFFSET (GtkMenuItemClass, activate),
213
 
                  NULL, NULL,
214
 
                  _gtk_marshal_VOID__VOID,
215
 
                  G_TYPE_NONE, 0);
216
 
  widget_class->activate_signal = menu_item_signals[ACTIVATE];
217
 
 
218
 
  menu_item_signals[ACTIVATE_ITEM] =
219
 
    g_signal_new (I_("activate-item"),
220
 
                  G_OBJECT_CLASS_TYPE (gobject_class),
221
 
                  G_SIGNAL_RUN_FIRST,
222
 
                  G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
223
 
                  NULL, NULL,
224
 
                  _gtk_marshal_VOID__VOID,
225
 
                  G_TYPE_NONE, 0);
226
 
 
227
 
  menu_item_signals[TOGGLE_SIZE_REQUEST] =
228
 
    g_signal_new (I_("toggle-size-request"),
229
 
                  G_OBJECT_CLASS_TYPE (gobject_class),
230
 
                  G_SIGNAL_RUN_FIRST,
231
 
                  G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
232
 
                  NULL, NULL,
233
 
                  _gtk_marshal_VOID__POINTER,
234
 
                  G_TYPE_NONE, 1,
235
 
                  G_TYPE_POINTER);
236
 
 
237
 
  menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
238
 
    g_signal_new (I_("toggle-size-allocate"),
239
 
                  G_OBJECT_CLASS_TYPE (gobject_class),
240
 
                  G_SIGNAL_RUN_FIRST,
241
 
                  G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
242
 
                  NULL, NULL,
243
 
                  _gtk_marshal_VOID__INT,
244
 
                  G_TYPE_NONE, 1,
245
 
                  G_TYPE_INT);
246
 
 
247
 
  /**
248
 
   * GtkMenuItem:right-justified:
249
 
   *
250
 
   * Sets whether the menu item appears justified at the right side of a menu bar.
251
 
   *
252
 
   * Since: 2.14
253
 
   **/
254
 
  g_object_class_install_property (gobject_class,
255
 
                                   PROP_RIGHT_JUSTIFIED,
256
 
                                   g_param_spec_boolean ("right-justified",
257
 
                                                         P_("Right Justified"),
258
 
                                                         P_("Sets whether the menu item appears justified at the right side of a menu bar"),
259
 
                                                         FALSE,
260
 
                                                         GTK_PARAM_READWRITE));
261
 
 
262
 
  /**
263
 
   * GtkMenuItem:submenu:
264
 
   *
265
 
   * The submenu attached to the menu item, or NULL if it has none.
266
 
   *
267
 
   * Since: 2.12
268
 
   **/
269
 
  g_object_class_install_property (gobject_class,
270
 
                                   PROP_SUBMENU,
271
 
                                   g_param_spec_object ("submenu",
272
 
                                                        P_("Submenu"),
273
 
                                                        P_("The submenu attached to the menu item, or NULL if it has none"),
274
 
                                                        GTK_TYPE_MENU,
275
 
                                                        GTK_PARAM_READWRITE));
276
 
  
277
 
 
278
 
  /**
279
 
   * GtkMenuItem:accel-path:
280
 
   *
281
 
   * Sets the accelerator path of the menu item, through which runtime
282
 
   * changes of the menu item's accelerator caused by the user can be
283
 
   * identified and saved to persistant storage.
284
 
   *
285
 
   * Since: 2.14
286
 
   **/
287
 
  g_object_class_install_property (gobject_class,
288
 
                                   PROP_ACCEL_PATH,
289
 
                                   g_param_spec_string ("accel-path",
290
 
                                                        P_("Accel Path"),
291
 
                                                        P_("Sets the accelerator path of the menu item"),
292
 
                                                        NULL,
293
 
                                                        GTK_PARAM_READWRITE));
294
 
 
295
 
  /**
296
 
   * GtkMenuItem:label:
297
 
   *
298
 
   * The text for the child label.
299
 
   *
300
 
   * Since: 2.16
301
 
   **/
302
 
  g_object_class_install_property (gobject_class,
303
 
                                   PROP_LABEL,
304
 
                                   g_param_spec_string ("label",
305
 
                                                        P_("Label"),
306
 
                                                        P_("The text for the child label"),
307
 
                                                        "",
308
 
                                                        GTK_PARAM_READWRITE));
309
 
 
310
 
  /**
311
 
   * GtkMenuItem:use-underline:
312
 
   *
313
 
   * %TRUE if underlines in the text indicate mnemonics  
314
 
   *
315
 
   * Since: 2.16
316
 
   **/
317
 
  g_object_class_install_property (gobject_class,
318
 
                                   PROP_USE_UNDERLINE,
319
 
                                   g_param_spec_boolean ("use-underline",
320
 
                                                         P_("Use underline"),
321
 
                                                         P_("If set, an underline in the text indicates "
322
 
                                                            "the next character should be used for the "
323
 
                                                            "mnemonic accelerator key"),
324
 
                                                         FALSE,
325
 
                                                         GTK_PARAM_READWRITE));
326
 
 
327
 
  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
328
 
  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
329
 
 
330
 
  gtk_widget_class_install_style_property_parser (widget_class,
331
 
                                                  g_param_spec_enum ("selected-shadow-type",
332
 
                                                                     "Selected Shadow Type",
333
 
                                                                     "Shadow type when item is selected",
334
 
                                                                     GTK_TYPE_SHADOW_TYPE,
335
 
                                                                     GTK_SHADOW_NONE,
336
 
                                                                     GTK_PARAM_READABLE),
337
 
                                                  gtk_rc_property_parse_enum);
338
 
 
339
 
  gtk_widget_class_install_style_property (widget_class,
340
 
                                           g_param_spec_int ("horizontal-padding",
341
 
                                                             "Horizontal Padding",
342
 
                                                             "Padding to left and right of the menu item",
343
 
                                                             0,
344
 
                                                             G_MAXINT,
345
 
                                                             3,
346
 
                                                             GTK_PARAM_READABLE));
347
 
 
348
 
  gtk_widget_class_install_style_property (widget_class,
349
 
                                           g_param_spec_int ("toggle-spacing",
350
 
                                                             "Icon Spacing",
351
 
                                                             "Space between icon and label",
352
 
                                                             0,
353
 
                                                             G_MAXINT,
354
 
                                                             5,
355
 
                                                             GTK_PARAM_READABLE));
356
 
 
357
 
  gtk_widget_class_install_style_property (widget_class,
358
 
                                           g_param_spec_int ("arrow-spacing",
359
 
                                                             "Arrow Spacing",
360
 
                                                             "Space between label and arrow",
361
 
                                                             0,
362
 
                                                             G_MAXINT,
363
 
                                                             10,
364
 
                                                             GTK_PARAM_READABLE));
365
 
 
366
 
  gtk_widget_class_install_style_property (widget_class,
367
 
                                           g_param_spec_float ("arrow-scaling",
368
 
                                                               P_("Arrow Scaling"),
369
 
                                                               P_("Amount of space used up by arrow, relative to the menu item's font size"),
370
 
                                                               0.0, 2.0, 0.8,
371
 
                                                               GTK_PARAM_READABLE));
372
 
 
373
 
  /**
374
 
   * GtkMenuItem:width-chars:
375
 
   *
376
 
   * The minimum desired width of the menu item in characters.
377
 
   *
378
 
   * Since: 2.14
379
 
   **/
380
 
  gtk_widget_class_install_style_property (widget_class,
381
 
                                           g_param_spec_int ("width-chars",
382
 
                                                             P_("Width in Characters"),
383
 
                                                             P_("The minimum desired width of the menu item in characters"),
384
 
                                                             0, G_MAXINT, 12,
385
 
                                                             GTK_PARAM_READABLE));
386
 
 
387
 
  g_type_class_add_private (object_class, sizeof (GtkMenuItemPrivate));
388
 
}
389
 
 
390
 
static void
391
 
gtk_menu_item_init (GtkMenuItem *menu_item)
392
 
{
393
 
  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
394
 
 
395
 
  gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
396
 
 
397
 
  priv->action = NULL;
398
 
  priv->use_action_appearance = TRUE;
399
 
  
400
 
  menu_item->submenu = NULL;
401
 
  menu_item->toggle_size = 0;
402
 
  menu_item->accelerator_width = 0;
403
 
  menu_item->show_submenu_indicator = FALSE;
404
 
  if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL)
405
 
    menu_item->submenu_direction = GTK_DIRECTION_LEFT;
406
 
  else
407
 
    menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
408
 
  menu_item->submenu_placement = GTK_TOP_BOTTOM;
409
 
  menu_item->right_justify = FALSE;
410
 
 
411
 
  menu_item->timer = 0;
412
 
}
413
 
 
414
 
GtkWidget*
415
 
gtk_menu_item_new (void)
416
 
{
417
 
  return g_object_new (GTK_TYPE_MENU_ITEM, NULL);
418
 
}
419
 
 
420
 
GtkWidget*
421
 
gtk_menu_item_new_with_label (const gchar *label)
422
 
{
423
 
  return g_object_new (GTK_TYPE_MENU_ITEM, 
424
 
                       "label", label,
425
 
                       NULL);
426
 
}
427
 
 
428
 
 
429
 
/**
430
 
 * gtk_menu_item_new_with_mnemonic:
431
 
 * @label: The text of the button, with an underscore in front of the
432
 
 *         mnemonic character
433
 
 * @returns: a new #GtkMenuItem
434
 
 *
435
 
 * Creates a new #GtkMenuItem containing a label. The label
436
 
 * will be created using gtk_label_new_with_mnemonic(), so underscores
437
 
 * in @label indicate the mnemonic for the menu item.
438
 
 **/
439
 
GtkWidget*
440
 
gtk_menu_item_new_with_mnemonic (const gchar *label)
441
 
{
442
 
  return g_object_new (GTK_TYPE_MENU_ITEM, 
443
 
                       "use-underline", TRUE,
444
 
                       "label", label,
445
 
                       NULL);
446
 
}
447
 
 
448
 
static void
449
 
gtk_menu_item_dispose (GObject *object)
450
 
{
451
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
452
 
  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
453
 
 
454
 
  if (priv->action)
455
 
    {
456
 
      gtk_action_disconnect_accelerator (priv->action);
457
 
      gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
458
 
      
459
 
      priv->action = NULL;
460
 
    }
461
 
  G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
462
 
}
463
 
 
464
 
static void 
465
 
gtk_menu_item_set_property (GObject      *object,
466
 
                            guint         prop_id,
467
 
                            const GValue *value,
468
 
                            GParamSpec   *pspec)
469
 
{
470
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
471
 
  
472
 
  switch (prop_id)
473
 
    {
474
 
    case PROP_RIGHT_JUSTIFIED:
475
 
      gtk_menu_item_set_right_justified (menu_item, g_value_get_boolean (value));
476
 
      break;
477
 
    case PROP_SUBMENU:
478
 
      gtk_menu_item_set_submenu (menu_item, g_value_get_object (value));
479
 
      break;
480
 
    case PROP_ACCEL_PATH:
481
 
      gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
482
 
      break;
483
 
    case PROP_LABEL:
484
 
      gtk_menu_item_set_label (menu_item, g_value_get_string (value));
485
 
      break;
486
 
    case PROP_USE_UNDERLINE:
487
 
      gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
488
 
      break;
489
 
    case PROP_ACTIVATABLE_RELATED_ACTION:
490
 
      gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
491
 
      break;
492
 
    case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
493
 
      gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
494
 
      break;
495
 
    default:
496
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
497
 
      break;
498
 
    }
499
 
}
500
 
 
501
 
static void 
502
 
gtk_menu_item_get_property (GObject    *object,
503
 
                            guint       prop_id,
504
 
                            GValue     *value,
505
 
                            GParamSpec *pspec)
506
 
{
507
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
508
 
  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
509
 
  
510
 
  switch (prop_id)
511
 
    {
512
 
    case PROP_RIGHT_JUSTIFIED:
513
 
      g_value_set_boolean (value, gtk_menu_item_get_right_justified (menu_item));
514
 
      break;
515
 
    case PROP_SUBMENU:
516
 
      g_value_set_object (value, gtk_menu_item_get_submenu (menu_item));
517
 
      break;
518
 
    case PROP_ACCEL_PATH:
519
 
      g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
520
 
      break;
521
 
    case PROP_LABEL:
522
 
      g_value_set_string (value, gtk_menu_item_get_label (menu_item));
523
 
      break;
524
 
    case PROP_USE_UNDERLINE:
525
 
      g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
526
 
      break;
527
 
    case PROP_ACTIVATABLE_RELATED_ACTION:
528
 
      g_value_set_object (value, priv->action);
529
 
      break;
530
 
    case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
531
 
      g_value_set_boolean (value, priv->use_action_appearance);
532
 
      break;
533
 
    default:
534
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
535
 
      break;
536
 
    }
537
 
}
538
 
 
539
 
static void
540
 
gtk_menu_item_destroy (GtkObject *object)
541
 
{
542
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
543
 
 
544
 
  if (menu_item->submenu)
545
 
    gtk_widget_destroy (menu_item->submenu);
546
 
 
547
 
  GTK_OBJECT_CLASS (gtk_menu_item_parent_class)->destroy (object);
548
 
}
549
 
 
550
 
static void
551
 
gtk_menu_item_detacher (GtkWidget *widget,
552
 
                        GtkMenu   *menu)
553
 
{
554
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
555
 
 
556
 
  g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
557
 
 
558
 
  menu_item->submenu = NULL;
559
 
}
560
 
 
561
 
static void
562
 
gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
563
 
{
564
 
  parent_buildable_iface = g_type_interface_peek_parent (iface);
565
 
  iface->add_child = gtk_menu_item_buildable_add_child;
566
 
  iface->custom_finished = gtk_menu_item_buildable_custom_finished;
567
 
}
568
 
 
569
 
static void 
570
 
gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
571
 
                                   GtkBuilder   *builder,
572
 
                                   GObject      *child,
573
 
                                   const gchar  *type)
574
 
{
575
 
  if (type && strcmp (type, "submenu") == 0)
576
 
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
577
 
                                   GTK_WIDGET (child));
578
 
  else
579
 
    parent_buildable_iface->add_child (buildable, builder, child, type);
580
 
}
581
 
 
582
 
 
583
 
static void 
584
 
gtk_menu_item_buildable_custom_finished (GtkBuildable        *buildable,
585
 
                                         GtkBuilder          *builder,
586
 
                                         GObject             *child,
587
 
                                         const gchar         *tagname,
588
 
                                         gpointer             user_data)
589
 
{
590
 
  GtkWidget *toplevel;
591
 
 
592
 
  if (strcmp (tagname, "accelerator") == 0)
593
 
    {
594
 
      GtkMenuShell *menu_shell = (GtkMenuShell *) GTK_WIDGET (buildable)->parent;
595
 
      GtkWidget *attach;
596
 
 
597
 
      if (menu_shell)
598
 
        {
599
 
          while (GTK_IS_MENU (menu_shell) &&
600
 
                 (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
601
 
            menu_shell = (GtkMenuShell *)attach->parent;
602
 
          
603
 
          toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
604
 
        }
605
 
      else
606
 
        {
607
 
          /* Fall back to something ... */
608
 
          toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable));
609
 
 
610
 
          g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.",
611
 
                     gtk_buildable_get_name (buildable));
612
 
        }
613
 
 
614
 
      /* Feed the correct toplevel to the GtkWidget accelerator parsing code */
615
 
      _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
616
 
    }
617
 
  else
618
 
    parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data);
619
 
}
620
 
 
621
 
 
622
 
static void
623
 
gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
624
 
{
625
 
  iface->update = gtk_menu_item_update;
626
 
  iface->sync_action_properties = gtk_menu_item_sync_action_properties;
627
 
}
628
 
 
629
 
static void
630
 
activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
631
 
{
632
 
  GtkWidget *child = GTK_BIN (menu_item)->child;
633
 
 
634
 
  if (GTK_IS_LABEL (child))
635
 
    {
636
 
      const gchar *label;
637
 
 
638
 
      label = gtk_action_get_label (action);
639
 
      gtk_menu_item_set_label (menu_item, label);
640
 
    }
641
 
}
642
 
 
643
 
gboolean _gtk_menu_is_empty (GtkWidget *menu);
644
 
 
645
 
static void
646
 
gtk_menu_item_update (GtkActivatable *activatable,
647
 
                      GtkAction      *action,
648
 
                      const gchar    *property_name)
649
 
{
650
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
651
 
  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
652
 
 
653
 
  if (strcmp (property_name, "visible") == 0)
654
 
    _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item), 
655
 
                                   _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
656
 
  else if (strcmp (property_name, "sensitive") == 0)
657
 
    gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
658
 
  else if (priv->use_action_appearance)
659
 
    {
660
 
      if (strcmp (property_name, "label") == 0)
661
 
        activatable_update_label (menu_item, action);
662
 
    }
663
 
}
664
 
 
665
 
static void
666
 
gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
667
 
                                      GtkAction      *action)
668
 
{
669
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
670
 
  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
671
 
 
672
 
  if (!priv->use_action_appearance || !action)
673
 
    {
674
 
      GtkWidget *label = GTK_BIN (menu_item)->child;
675
 
 
676
 
      label = GTK_BIN (menu_item)->child;
677
 
 
678
 
      if (GTK_IS_ACCEL_LABEL (label))
679
 
        gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (menu_item));
680
 
    }
681
 
 
682
 
  if (!action)
683
 
    return;
684
 
 
685
 
  _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
686
 
                                 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
687
 
 
688
 
  gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
689
 
 
690
 
  if (priv->use_action_appearance)
691
 
    {
692
 
      GtkWidget *label = GTK_BIN (menu_item)->child;
693
 
 
694
 
      /* make sure label is a label */
695
 
      if (label && !GTK_IS_LABEL (label))
696
 
        {
697
 
          gtk_container_remove (GTK_CONTAINER (menu_item), label);
698
 
          label = NULL;
699
 
        }
700
 
 
701
 
      gtk_menu_item_ensure_label (menu_item);
702
 
      gtk_menu_item_set_use_underline (menu_item, TRUE);
703
 
 
704
 
      label = GTK_BIN (menu_item)->child;
705
 
 
706
 
      if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
707
 
        {
708
 
          gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), NULL);
709
 
          gtk_accel_label_set_accel_closure (GTK_ACCEL_LABEL (label),
710
 
                                             gtk_action_get_accel_closure (action));
711
 
        }
712
 
 
713
 
      activatable_update_label (menu_item, action);
714
 
    }
715
 
}
716
 
 
717
 
static void
718
 
gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
719
 
                                  GtkAction   *action)
720
 
{
721
 
    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
722
 
 
723
 
    if (priv->action == action)
724
 
      return;
725
 
 
726
 
    if (priv->action)
727
 
      {
728
 
        gtk_action_disconnect_accelerator (priv->action);
729
 
      }
730
 
 
731
 
    if (action)
732
 
      {
733
 
        const gchar *accel_path;
734
 
        
735
 
        accel_path = gtk_action_get_accel_path (action);
736
 
        if (accel_path)
737
 
          {
738
 
            gtk_action_connect_accelerator (action);
739
 
            gtk_menu_item_set_accel_path (menu_item, accel_path);
740
 
          }
741
 
      }
742
 
 
743
 
    gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
744
 
 
745
 
    priv->action = action;
746
 
}
747
 
 
748
 
static void
749
 
gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
750
 
                                         gboolean     use_appearance)
751
 
{
752
 
    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
753
 
 
754
 
    if (priv->use_action_appearance != use_appearance)
755
 
      {
756
 
        priv->use_action_appearance = use_appearance;
757
 
 
758
 
        gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (menu_item), priv->action);
759
 
      }
760
 
}
761
 
 
762
 
 
763
 
/**
764
 
 * gtk_menu_item_set_submenu:
765
 
 * @menu_item: a #GtkMenuItem
766
 
 * @submenu: (allow-none): the submenu, or %NULL
767
 
 *
768
 
 * Sets or replaces the menu item's submenu, or removes it when a %NULL
769
 
 * submenu is passed.
770
 
 **/
771
 
void
772
 
gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
773
 
                           GtkWidget   *submenu)
774
 
{
775
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
776
 
  g_return_if_fail (submenu == NULL || GTK_IS_MENU (submenu));
777
 
  
778
 
  if (menu_item->submenu != submenu)
779
 
    {
780
 
      if (menu_item->submenu)
781
 
        gtk_menu_detach (GTK_MENU (menu_item->submenu));
782
 
 
783
 
      if (submenu)
784
 
        {
785
 
          menu_item->submenu = submenu;
786
 
          gtk_menu_attach_to_widget (GTK_MENU (submenu),
787
 
                                     GTK_WIDGET (menu_item),
788
 
                                     gtk_menu_item_detacher);
789
 
        }
790
 
 
791
 
      if (GTK_WIDGET (menu_item)->parent)
792
 
        gtk_widget_queue_resize (GTK_WIDGET (menu_item));
793
 
 
794
 
      g_object_notify (G_OBJECT (menu_item), "submenu");
795
 
    }
796
 
}
797
 
 
798
 
/**
799
 
 * gtk_menu_item_get_submenu:
800
 
 * @menu_item: a #GtkMenuItem
801
 
 *
802
 
 * Gets the submenu underneath this menu item, if any.
803
 
 * See gtk_menu_item_set_submenu().
804
 
 *
805
 
 * Return value: (transfer none): submenu for this menu item, or %NULL if none.
806
 
 **/
807
 
GtkWidget *
808
 
gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
809
 
{
810
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
811
 
 
812
 
  return menu_item->submenu;
813
 
}
814
 
 
815
 
/**
816
 
 * gtk_menu_item_remove_submenu:
817
 
 * @menu_item: a #GtkMenuItem
818
 
 *
819
 
 * Removes the widget's submenu.
820
 
 *
821
 
 * Deprecated: 2.12: gtk_menu_item_remove_submenu() is deprecated and
822
 
 *                   should not be used in newly written code. Use
823
 
 *                   gtk_menu_item_set_submenu() instead.
824
 
 **/
825
 
void
826
 
gtk_menu_item_remove_submenu (GtkMenuItem *menu_item)
827
 
{
828
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
829
 
 
830
 
  gtk_menu_item_set_submenu (menu_item, NULL);
831
 
}
832
 
 
833
 
void _gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
834
 
                                   GtkSubmenuPlacement  placement);
835
 
 
836
 
void
837
 
_gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
838
 
                             GtkSubmenuPlacement  placement)
839
 
{
840
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
841
 
 
842
 
  menu_item->submenu_placement = placement;
843
 
}
844
 
 
845
 
void
846
 
gtk_menu_item_select (GtkMenuItem *menu_item)
847
 
{
848
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
849
 
 
850
 
  gtk_item_select (GTK_ITEM (menu_item));
851
 
 
852
 
  /* Enable themeing of the parent menu item depending on whether
853
 
   * something is selected in its submenu
854
 
   */
855
 
  if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
856
 
    {
857
 
      GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
858
 
 
859
 
      if (menu->parent_menu_item)
860
 
        gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
861
 
    }
862
 
}
863
 
 
864
 
void
865
 
gtk_menu_item_deselect (GtkMenuItem *menu_item)
866
 
{
867
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
868
 
 
869
 
  gtk_item_deselect (GTK_ITEM (menu_item));
870
 
 
871
 
  /* Enable themeing of the parent menu item depending on whether
872
 
   * something is selected in its submenu
873
 
   */
874
 
  if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
875
 
    {
876
 
      GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
877
 
 
878
 
      if (menu->parent_menu_item)
879
 
        gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
880
 
    }
881
 
}
882
 
 
883
 
void
884
 
gtk_menu_item_activate (GtkMenuItem *menu_item)
885
 
{
886
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
887
 
 
888
 
  g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
889
 
}
890
 
 
891
 
void
892
 
gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
893
 
                                   gint        *requisition)
894
 
{
895
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
896
 
 
897
 
  g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
898
 
}
899
 
 
900
 
void
901
 
gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
902
 
                                    gint         allocation)
903
 
{
904
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
905
 
 
906
 
  g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
907
 
}
908
 
 
909
 
static void
910
 
gtk_menu_item_accel_width_foreach (GtkWidget *widget,
911
 
                                   gpointer data)
912
 
{
913
 
  guint *width = data;
914
 
 
915
 
  if (GTK_IS_ACCEL_LABEL (widget))
916
 
    {
917
 
      guint w;
918
 
 
919
 
      w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
920
 
      *width = MAX (*width, w);
921
 
    }
922
 
  else if (GTK_IS_CONTAINER (widget))
923
 
    gtk_container_foreach (GTK_CONTAINER (widget),
924
 
                           gtk_menu_item_accel_width_foreach,
925
 
                           data);
926
 
}
927
 
 
928
 
static gint
929
 
get_minimum_width (GtkWidget *widget)
930
 
{
931
 
  PangoContext *context;
932
 
  PangoFontMetrics *metrics;
933
 
  gint width;
934
 
  gint width_chars;
935
 
 
936
 
  context = gtk_widget_get_pango_context (widget);
937
 
  metrics = pango_context_get_metrics (context,
938
 
                                       widget->style->font_desc,
939
 
                                       pango_context_get_language (context));
940
 
 
941
 
  width = pango_font_metrics_get_approximate_char_width (metrics);
942
 
 
943
 
  pango_font_metrics_unref (metrics);
944
 
 
945
 
  gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
946
 
 
947
 
  return PANGO_PIXELS (width_chars * width);
948
 
}
949
 
 
950
 
static void
951
 
gtk_menu_item_size_request (GtkWidget      *widget,
952
 
                            GtkRequisition *requisition)
953
 
{
954
 
  GtkMenuItem *menu_item;
955
 
  GtkBin *bin;
956
 
  guint accel_width;
957
 
  guint horizontal_padding;
958
 
  GtkPackDirection pack_dir;
959
 
  GtkPackDirection child_pack_dir;
960
 
 
961
 
  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
962
 
  g_return_if_fail (requisition != NULL);
963
 
 
964
 
  gtk_widget_style_get (widget,
965
 
                        "horizontal-padding", &horizontal_padding,
966
 
                        NULL);
967
 
  
968
 
  bin = GTK_BIN (widget);
969
 
  menu_item = GTK_MENU_ITEM (widget);
970
 
 
971
 
  if (GTK_IS_MENU_BAR (widget->parent))
972
 
    {
973
 
      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
974
 
      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
975
 
    }
976
 
  else
977
 
    {
978
 
      pack_dir = GTK_PACK_DIRECTION_LTR;
979
 
      child_pack_dir = GTK_PACK_DIRECTION_LTR;
980
 
    }
981
 
 
982
 
  requisition->width = (GTK_CONTAINER (widget)->border_width +
983
 
                        widget->style->xthickness) * 2;
984
 
  requisition->height = (GTK_CONTAINER (widget)->border_width +
985
 
                         widget->style->ythickness) * 2;
986
 
 
987
 
  if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
988
 
      (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
989
 
    requisition->width += 2 * horizontal_padding;
990
 
  else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
991
 
      (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
992
 
    requisition->height += 2 * horizontal_padding;
993
 
 
994
 
  if (bin->child && gtk_widget_get_visible (bin->child))
995
 
    {
996
 
      GtkRequisition child_requisition;
997
 
      
998
 
      gtk_widget_size_request (bin->child, &child_requisition);
999
 
 
1000
 
      requisition->width += child_requisition.width;
1001
 
      requisition->height += child_requisition.height;
1002
 
 
1003
 
      if (menu_item->submenu && menu_item->show_submenu_indicator)
1004
 
        {
1005
 
          guint arrow_spacing;
1006
 
          
1007
 
          gtk_widget_style_get (widget,
1008
 
                                "arrow-spacing", &arrow_spacing,
1009
 
                                NULL);
1010
 
 
1011
 
          requisition->width += child_requisition.height;
1012
 
          requisition->width += arrow_spacing;
1013
 
 
1014
 
          requisition->width = MAX (requisition->width, get_minimum_width (widget));
1015
 
        }
1016
 
    }
1017
 
  else /* separator item */
1018
 
    {
1019
 
      gboolean wide_separators;
1020
 
      gint     separator_height;
1021
 
 
1022
 
      gtk_widget_style_get (widget,
1023
 
                            "wide-separators",  &wide_separators,
1024
 
                            "separator-height", &separator_height,
1025
 
                            NULL);
1026
 
 
1027
 
      if (wide_separators)
1028
 
        requisition->height += separator_height + widget->style->ythickness;
1029
 
      else
1030
 
        requisition->height += widget->style->ythickness * 2;
1031
 
    }
1032
 
 
1033
 
  accel_width = 0;
1034
 
  gtk_container_foreach (GTK_CONTAINER (menu_item),
1035
 
                         gtk_menu_item_accel_width_foreach,
1036
 
                         &accel_width);
1037
 
  menu_item->accelerator_width = accel_width;
1038
 
}
1039
 
 
1040
 
static void
1041
 
gtk_menu_item_size_allocate (GtkWidget     *widget,
1042
 
                             GtkAllocation *allocation)
1043
 
{
1044
 
  GtkMenuItem *menu_item;
1045
 
  GtkBin *bin;
1046
 
  GtkAllocation child_allocation;
1047
 
  GtkTextDirection direction;
1048
 
  GtkPackDirection pack_dir;
1049
 
  GtkPackDirection child_pack_dir;
1050
 
 
1051
 
  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1052
 
  g_return_if_fail (allocation != NULL);
1053
 
 
1054
 
  menu_item = GTK_MENU_ITEM (widget);
1055
 
  bin = GTK_BIN (widget);
1056
 
  
1057
 
  direction = gtk_widget_get_direction (widget);
1058
 
 
1059
 
  if (GTK_IS_MENU_BAR (widget->parent))
1060
 
    {
1061
 
      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
1062
 
      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
1063
 
    }
1064
 
  else
1065
 
    {
1066
 
      pack_dir = GTK_PACK_DIRECTION_LTR;
1067
 
      child_pack_dir = GTK_PACK_DIRECTION_LTR;
1068
 
    }
1069
 
    
1070
 
  widget->allocation = *allocation;
1071
 
 
1072
 
  if (bin->child)
1073
 
    {
1074
 
      GtkRequisition child_requisition;
1075
 
      guint horizontal_padding;
1076
 
 
1077
 
      gtk_widget_style_get (widget,
1078
 
                            "horizontal-padding", &horizontal_padding,
1079
 
                            NULL);
1080
 
 
1081
 
      child_allocation.x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
1082
 
      child_allocation.y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness;
1083
 
 
1084
 
      if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
1085
 
          (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
1086
 
        child_allocation.x += horizontal_padding;
1087
 
      else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
1088
 
               (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
1089
 
        child_allocation.y += horizontal_padding;
1090
 
      
1091
 
      child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
1092
 
      child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
1093
 
 
1094
 
      if (child_pack_dir == GTK_PACK_DIRECTION_LTR ||
1095
 
          child_pack_dir == GTK_PACK_DIRECTION_RTL)
1096
 
        {
1097
 
          if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL))
1098
 
            child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
1099
 
          child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
1100
 
        }
1101
 
      else
1102
 
        {
1103
 
          if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT))
1104
 
            child_allocation.y += GTK_MENU_ITEM (widget)->toggle_size;
1105
 
          child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size;
1106
 
        }
1107
 
 
1108
 
      child_allocation.x += widget->allocation.x;
1109
 
      child_allocation.y += widget->allocation.y;
1110
 
 
1111
 
      gtk_widget_get_child_requisition (bin->child, &child_requisition);
1112
 
      if (menu_item->submenu && menu_item->show_submenu_indicator) 
1113
 
        {
1114
 
          if (direction == GTK_TEXT_DIR_RTL)
1115
 
            child_allocation.x += child_requisition.height;
1116
 
          child_allocation.width -= child_requisition.height;
1117
 
        }
1118
 
      
1119
 
      if (child_allocation.width < 1)
1120
 
        child_allocation.width = 1;
1121
 
 
1122
 
      gtk_widget_size_allocate (bin->child, &child_allocation);
1123
 
    }
1124
 
 
1125
 
  if (gtk_widget_get_realized (widget))
1126
 
    gdk_window_move_resize (menu_item->event_window,
1127
 
                            allocation->x, allocation->y,
1128
 
                            allocation->width, allocation->height);
1129
 
 
1130
 
  if (menu_item->submenu)
1131
 
    gtk_menu_reposition (GTK_MENU (menu_item->submenu));
1132
 
}
1133
 
 
1134
 
static void
1135
 
gtk_menu_item_realize (GtkWidget *widget)
1136
 
{
1137
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1138
 
  GdkWindowAttr attributes;
1139
 
  gint attributes_mask;
1140
 
 
1141
 
  gtk_widget_set_realized (widget, TRUE);
1142
 
 
1143
 
  widget->window = gtk_widget_get_parent_window (widget);
1144
 
  g_object_ref (widget->window);
1145
 
  
1146
 
  attributes.x = widget->allocation.x;
1147
 
  attributes.y = widget->allocation.y;
1148
 
  attributes.width = widget->allocation.width;
1149
 
  attributes.height = widget->allocation.height;
1150
 
  attributes.window_type = GDK_WINDOW_CHILD;
1151
 
  attributes.wclass = GDK_INPUT_ONLY;
1152
 
  attributes.event_mask = (gtk_widget_get_events (widget) |
1153
 
                           GDK_BUTTON_PRESS_MASK |
1154
 
                           GDK_BUTTON_RELEASE_MASK |
1155
 
                           GDK_ENTER_NOTIFY_MASK |
1156
 
                           GDK_LEAVE_NOTIFY_MASK |
1157
 
                           GDK_POINTER_MOTION_MASK);
1158
 
 
1159
 
  attributes_mask = GDK_WA_X | GDK_WA_Y;
1160
 
  menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1161
 
  gdk_window_set_user_data (menu_item->event_window, widget);
1162
 
 
1163
 
  widget->style = gtk_style_attach (widget->style, widget->window);
1164
 
}
1165
 
 
1166
 
static void
1167
 
gtk_menu_item_unrealize (GtkWidget *widget)
1168
 
{
1169
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1170
 
 
1171
 
  gdk_window_set_user_data (menu_item->event_window, NULL);
1172
 
  gdk_window_destroy (menu_item->event_window);
1173
 
  menu_item->event_window = NULL;
1174
 
 
1175
 
  GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
1176
 
}
1177
 
 
1178
 
static void
1179
 
gtk_menu_item_map (GtkWidget *widget)
1180
 
{
1181
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1182
 
  
1183
 
  GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->map (widget);
1184
 
 
1185
 
  gdk_window_show (menu_item->event_window);
1186
 
}
1187
 
 
1188
 
static void
1189
 
gtk_menu_item_unmap (GtkWidget *widget)
1190
 
{
1191
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1192
 
    
1193
 
  gdk_window_hide (menu_item->event_window);
1194
 
 
1195
 
  GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
1196
 
}
1197
 
 
1198
 
static void
1199
 
gtk_menu_item_paint (GtkWidget    *widget,
1200
 
                     GdkRectangle *area)
1201
 
{
1202
 
  GtkMenuItem *menu_item;
1203
 
  GtkStateType state_type;
1204
 
  GtkShadowType shadow_type, selected_shadow_type;
1205
 
  gint width, height;
1206
 
  gint x, y;
1207
 
  gint border_width = GTK_CONTAINER (widget)->border_width;
1208
 
 
1209
 
  if (gtk_widget_is_drawable (widget))
1210
 
    {
1211
 
      menu_item = GTK_MENU_ITEM (widget);
1212
 
 
1213
 
      state_type = widget->state;
1214
 
      
1215
 
      x = widget->allocation.x + border_width;
1216
 
      y = widget->allocation.y + border_width;
1217
 
      width = widget->allocation.width - border_width * 2;
1218
 
      height = widget->allocation.height - border_width * 2;
1219
 
      
1220
 
      if ((state_type == GTK_STATE_PRELIGHT) &&
1221
 
          (GTK_BIN (menu_item)->child))
1222
 
        {
1223
 
          gtk_widget_style_get (widget,
1224
 
                                "selected-shadow-type", &selected_shadow_type,
1225
 
                                NULL);
1226
 
          gtk_paint_box (widget->style,
1227
 
                         widget->window,
1228
 
                         GTK_STATE_PRELIGHT,
1229
 
                         selected_shadow_type,
1230
 
                         area, widget, "menuitem",
1231
 
                         x, y, width, height);
1232
 
        }
1233
 
  
1234
 
      if (menu_item->submenu && menu_item->show_submenu_indicator)
1235
 
        {
1236
 
          gint arrow_x, arrow_y;
1237
 
          gint arrow_size;
1238
 
          gint arrow_extent;
1239
 
          guint horizontal_padding;
1240
 
          gfloat arrow_scaling;
1241
 
          GtkTextDirection direction;
1242
 
          GtkArrowType arrow_type;
1243
 
          PangoContext *context;
1244
 
          PangoFontMetrics *metrics;
1245
 
 
1246
 
          direction = gtk_widget_get_direction (widget);
1247
 
      
1248
 
          gtk_widget_style_get (widget,
1249
 
                                "horizontal-padding", &horizontal_padding,
1250
 
                                "arrow-scaling", &arrow_scaling,
1251
 
                                NULL);
1252
 
          
1253
 
          context = gtk_widget_get_pango_context (GTK_BIN (menu_item)->child);
1254
 
          metrics = pango_context_get_metrics (context, 
1255
 
                                               GTK_WIDGET (GTK_BIN (menu_item)->child)->style->font_desc,
1256
 
                                               pango_context_get_language (context));
1257
 
 
1258
 
          arrow_size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
1259
 
                                      pango_font_metrics_get_descent (metrics)));
1260
 
 
1261
 
          pango_font_metrics_unref (metrics);
1262
 
 
1263
 
          arrow_extent = arrow_size * arrow_scaling;
1264
 
 
1265
 
          shadow_type = GTK_SHADOW_OUT;
1266
 
          if (state_type == GTK_STATE_PRELIGHT)
1267
 
            shadow_type = GTK_SHADOW_IN;
1268
 
 
1269
 
          if (direction == GTK_TEXT_DIR_LTR)
1270
 
            {
1271
 
              arrow_x = x + width - horizontal_padding - arrow_extent;
1272
 
              arrow_type = GTK_ARROW_RIGHT;
1273
 
            }
1274
 
          else
1275
 
            {
1276
 
              arrow_x = x + horizontal_padding;
1277
 
              arrow_type = GTK_ARROW_LEFT;
1278
 
            }
1279
 
 
1280
 
          arrow_y = y + (height - arrow_extent) / 2;
1281
 
 
1282
 
          gtk_paint_arrow (widget->style, widget->window,
1283
 
                           state_type, shadow_type, 
1284
 
                           area, widget, "menuitem", 
1285
 
                           arrow_type, TRUE,
1286
 
                           arrow_x, arrow_y,
1287
 
                           arrow_extent, arrow_extent);
1288
 
        }
1289
 
      else if (!GTK_BIN (menu_item)->child)
1290
 
        {
1291
 
          gboolean wide_separators;
1292
 
          gint     separator_height;
1293
 
          guint    horizontal_padding;
1294
 
 
1295
 
          gtk_widget_style_get (widget,
1296
 
                                "wide-separators",    &wide_separators,
1297
 
                                "separator-height",   &separator_height,
1298
 
                                "horizontal-padding", &horizontal_padding,
1299
 
                                NULL);
1300
 
 
1301
 
          if (wide_separators)
1302
 
            gtk_paint_box (widget->style, widget->window,
1303
 
                           GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
1304
 
                           area, widget, "hseparator",
1305
 
                           widget->allocation.x + horizontal_padding + widget->style->xthickness,
1306
 
                           widget->allocation.y + (widget->allocation.height -
1307
 
                                                   separator_height -
1308
 
                                                   widget->style->ythickness) / 2,
1309
 
                           widget->allocation.width -
1310
 
                           2 * (horizontal_padding + widget->style->xthickness),
1311
 
                           separator_height);
1312
 
          else
1313
 
            gtk_paint_hline (widget->style, widget->window,
1314
 
                             GTK_STATE_NORMAL, area, widget, "menuitem",
1315
 
                             widget->allocation.x + horizontal_padding + widget->style->xthickness,
1316
 
                             widget->allocation.x + widget->allocation.width - horizontal_padding - widget->style->xthickness - 1,
1317
 
                             widget->allocation.y + (widget->allocation.height -
1318
 
                                                     widget->style->ythickness) / 2);
1319
 
        }
1320
 
    }
1321
 
}
1322
 
 
1323
 
static gint
1324
 
gtk_menu_item_expose (GtkWidget      *widget,
1325
 
                      GdkEventExpose *event)
1326
 
{
1327
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
1328
 
  g_return_val_if_fail (event != NULL, FALSE);
1329
 
 
1330
 
  if (gtk_widget_is_drawable (widget))
1331
 
    {
1332
 
      gtk_menu_item_paint (widget, &event->area);
1333
 
 
1334
 
      GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->expose_event (widget, event);
1335
 
    }
1336
 
 
1337
 
  return FALSE;
1338
 
}
1339
 
 
1340
 
static void
1341
 
gtk_real_menu_item_select (GtkItem *item)
1342
 
{
1343
 
  GtkMenuItem *menu_item;
1344
 
  gboolean touchscreen_mode;
1345
 
 
1346
 
  g_return_if_fail (GTK_IS_MENU_ITEM (item));
1347
 
 
1348
 
  menu_item = GTK_MENU_ITEM (item);
1349
 
 
1350
 
  g_object_get (gtk_widget_get_settings (GTK_WIDGET (item)),
1351
 
                "gtk-touchscreen-mode", &touchscreen_mode,
1352
 
                NULL);
1353
 
 
1354
 
  if (!touchscreen_mode &&
1355
 
      menu_item->submenu &&
1356
 
      (!gtk_widget_get_mapped (menu_item->submenu) ||
1357
 
       GTK_MENU (menu_item->submenu)->tearoff_active))
1358
 
    {
1359
 
      _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1360
 
    }
1361
 
 
1362
 
  gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
1363
 
  gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1364
 
}
1365
 
 
1366
 
static void
1367
 
gtk_real_menu_item_deselect (GtkItem *item)
1368
 
{
1369
 
  GtkMenuItem *menu_item;
1370
 
 
1371
 
  g_return_if_fail (GTK_IS_MENU_ITEM (item));
1372
 
 
1373
 
  menu_item = GTK_MENU_ITEM (item);
1374
 
 
1375
 
  if (menu_item->submenu)
1376
 
    _gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
1377
 
 
1378
 
  gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
1379
 
  gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1380
 
}
1381
 
 
1382
 
static gboolean
1383
 
gtk_menu_item_mnemonic_activate (GtkWidget *widget,
1384
 
                                 gboolean   group_cycling)
1385
 
{
1386
 
  if (GTK_IS_MENU_SHELL (widget->parent))
1387
 
    _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (widget->parent), TRUE);
1388
 
 
1389
 
  if (group_cycling &&
1390
 
      widget->parent &&
1391
 
      GTK_IS_MENU_SHELL (widget->parent) &&
1392
 
      GTK_MENU_SHELL (widget->parent)->active)
1393
 
    {
1394
 
      gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent),
1395
 
                                  widget);
1396
 
    }
1397
 
  else
1398
 
    g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
1399
 
  
1400
 
  return TRUE;
1401
 
}
1402
 
 
1403
 
static void 
1404
 
gtk_real_menu_item_activate (GtkMenuItem *menu_item)
1405
 
{
1406
 
  GtkMenuItemPrivate *priv;
1407
 
 
1408
 
  priv = GET_PRIVATE (menu_item);
1409
 
 
1410
 
  if (priv->action)
1411
 
    gtk_action_activate (priv->action);
1412
 
}
1413
 
 
1414
 
 
1415
 
static void
1416
 
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
1417
 
{
1418
 
  GtkMenuItemPrivate *priv;
1419
 
  GtkWidget *widget;
1420
 
 
1421
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1422
 
 
1423
 
  priv   = GET_PRIVATE (menu_item);
1424
 
  widget = GTK_WIDGET (menu_item);
1425
 
  
1426
 
  if (widget->parent &&
1427
 
      GTK_IS_MENU_SHELL (widget->parent))
1428
 
    {
1429
 
      if (menu_item->submenu == NULL)
1430
 
        gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget->parent),
1431
 
                                      widget, TRUE);
1432
 
      else
1433
 
        {
1434
 
          GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget->parent);
1435
 
 
1436
 
          _gtk_menu_shell_activate (menu_shell);
1437
 
 
1438
 
          gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent), widget);
1439
 
          _gtk_menu_item_popup_submenu (widget, FALSE);
1440
 
 
1441
 
          gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
1442
 
        }
1443
 
    }
1444
 
}
1445
 
 
1446
 
static void
1447
 
gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1448
 
                                        gint        *requisition)
1449
 
{
1450
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1451
 
 
1452
 
  *requisition = 0;
1453
 
}
1454
 
 
1455
 
static void
1456
 
gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1457
 
                                         gint         allocation)
1458
 
{
1459
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1460
 
 
1461
 
  menu_item->toggle_size = allocation;
1462
 
}
1463
 
 
1464
 
static void
1465
 
gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
1466
 
                              const gchar *label)
1467
 
{
1468
 
  gtk_menu_item_ensure_label (menu_item);
1469
 
 
1470
 
  if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1471
 
    {
1472
 
      gtk_label_set_label (GTK_LABEL (GTK_BIN (menu_item)->child), label ? label : "");
1473
 
      
1474
 
      g_object_notify (G_OBJECT (menu_item), "label");
1475
 
    }
1476
 
}
1477
 
 
1478
 
static const gchar *
1479
 
gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
1480
 
{
1481
 
  gtk_menu_item_ensure_label (menu_item);
1482
 
 
1483
 
  if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1484
 
    return gtk_label_get_label (GTK_LABEL (GTK_BIN (menu_item)->child));
1485
 
 
1486
 
  return NULL;
1487
 
}
1488
 
 
1489
 
static void
1490
 
free_timeval (GTimeVal *val)
1491
 
{
1492
 
  g_slice_free (GTimeVal, val);
1493
 
}
1494
 
 
1495
 
static void
1496
 
gtk_menu_item_real_popup_submenu (GtkWidget *widget,
1497
 
                                  gboolean   remember_exact_time)
1498
 
{
1499
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1500
 
 
1501
 
  if (gtk_widget_is_sensitive (menu_item->submenu) && widget->parent)
1502
 
    {
1503
 
      gboolean take_focus;
1504
 
      GtkMenuPositionFunc menu_position_func;
1505
 
 
1506
 
      take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (widget->parent));
1507
 
      gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (menu_item->submenu),
1508
 
                                     take_focus);
1509
 
 
1510
 
      if (remember_exact_time)
1511
 
        {
1512
 
          GTimeVal *popup_time = g_slice_new0 (GTimeVal);
1513
 
 
1514
 
          g_get_current_time (popup_time);
1515
 
 
1516
 
          g_object_set_data_full (G_OBJECT (menu_item->submenu),
1517
 
                                  "gtk-menu-exact-popup-time", popup_time,
1518
 
                                  (GDestroyNotify) free_timeval);
1519
 
        }
1520
 
      else
1521
 
        {
1522
 
          g_object_set_data (G_OBJECT (menu_item->submenu),
1523
 
                             "gtk-menu-exact-popup-time", NULL);
1524
 
        }
1525
 
 
1526
 
      /* gtk_menu_item_position_menu positions the submenu from the
1527
 
       * menuitems position. If the menuitem doesn't have a window,
1528
 
       * that doesn't work. In that case we use the default
1529
 
       * positioning function instead which places the submenu at the
1530
 
       * mouse cursor.
1531
 
       */
1532
 
      if (widget->window)
1533
 
        menu_position_func = gtk_menu_item_position_menu;
1534
 
      else
1535
 
        menu_position_func = NULL;
1536
 
 
1537
 
      gtk_menu_popup (GTK_MENU (menu_item->submenu),
1538
 
                      widget->parent,
1539
 
                      widget,
1540
 
                      menu_position_func,
1541
 
                      menu_item,
1542
 
                      GTK_MENU_SHELL (widget->parent)->button,
1543
 
                      0);
1544
 
    }
1545
 
 
1546
 
  /* Enable themeing of the parent menu item depending on whether
1547
 
   * its submenu is shown or not.
1548
 
   */
1549
 
  gtk_widget_queue_draw (widget);
1550
 
}
1551
 
 
1552
 
static gint
1553
 
gtk_menu_item_popup_timeout (gpointer data)
1554
 
{
1555
 
  GtkMenuItem *menu_item;
1556
 
  GtkWidget *parent;
1557
 
  
1558
 
  menu_item = GTK_MENU_ITEM (data);
1559
 
 
1560
 
  parent = GTK_WIDGET (menu_item)->parent;
1561
 
 
1562
 
  if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active) || 
1563
 
      (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off))
1564
 
    {
1565
 
      gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1566
 
      if (menu_item->timer_from_keypress && menu_item->submenu)
1567
 
        GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
1568
 
    }
1569
 
 
1570
 
  menu_item->timer = 0;
1571
 
 
1572
 
  return FALSE;  
1573
 
}
1574
 
 
1575
 
static gint
1576
 
get_popup_delay (GtkWidget *widget)
1577
 
{
1578
 
  if (GTK_IS_MENU_SHELL (widget->parent))
1579
 
    {
1580
 
      return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (widget->parent));
1581
 
    }
1582
 
  else
1583
 
    {
1584
 
      gint popup_delay;
1585
 
 
1586
 
      g_object_get (gtk_widget_get_settings (widget),
1587
 
                    "gtk-menu-popup-delay", &popup_delay,
1588
 
                    NULL);
1589
 
 
1590
 
      return popup_delay;
1591
 
    }
1592
 
}
1593
 
 
1594
 
void
1595
 
_gtk_menu_item_popup_submenu (GtkWidget *widget,
1596
 
                              gboolean   with_delay)
1597
 
{
1598
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1599
 
 
1600
 
  if (menu_item->timer)
1601
 
    {
1602
 
      g_source_remove (menu_item->timer);
1603
 
      menu_item->timer = 0;
1604
 
      with_delay = FALSE;
1605
 
    }
1606
 
 
1607
 
  if (with_delay)
1608
 
    {
1609
 
      gint popup_delay = get_popup_delay (widget);
1610
 
 
1611
 
      if (popup_delay > 0)
1612
 
        {
1613
 
          GdkEvent *event = gtk_get_current_event ();
1614
 
 
1615
 
          menu_item->timer = gdk_threads_add_timeout (popup_delay,
1616
 
                                                      gtk_menu_item_popup_timeout,
1617
 
                                                      menu_item);
1618
 
 
1619
 
          if (event &&
1620
 
              event->type != GDK_BUTTON_PRESS &&
1621
 
              event->type != GDK_ENTER_NOTIFY)
1622
 
            menu_item->timer_from_keypress = TRUE;
1623
 
          else
1624
 
            menu_item->timer_from_keypress = FALSE;
1625
 
 
1626
 
          if (event)
1627
 
            gdk_event_free (event);
1628
 
 
1629
 
          return;
1630
 
        }
1631
 
    }
1632
 
 
1633
 
  gtk_menu_item_real_popup_submenu (widget, FALSE);
1634
 
}
1635
 
 
1636
 
void
1637
 
_gtk_menu_item_popdown_submenu (GtkWidget *widget)
1638
 
{
1639
 
  GtkMenuItem *menu_item;
1640
 
 
1641
 
  menu_item = GTK_MENU_ITEM (widget);
1642
 
 
1643
 
  if (menu_item->submenu)
1644
 
    {
1645
 
      g_object_set_data (G_OBJECT (menu_item->submenu),
1646
 
                         "gtk-menu-exact-popup-time", NULL);
1647
 
 
1648
 
      if (menu_item->timer)
1649
 
        {
1650
 
          g_source_remove (menu_item->timer);
1651
 
          menu_item->timer = 0;
1652
 
        }
1653
 
      else
1654
 
        gtk_menu_popdown (GTK_MENU (menu_item->submenu));
1655
 
 
1656
 
      gtk_widget_queue_draw (widget);
1657
 
    }
1658
 
}
1659
 
 
1660
 
static void
1661
 
get_offsets (GtkMenu *menu,
1662
 
             gint    *horizontal_offset,
1663
 
             gint    *vertical_offset)
1664
 
{
1665
 
  gint vertical_padding;
1666
 
  gint horizontal_padding;
1667
 
  
1668
 
  gtk_widget_style_get (GTK_WIDGET (menu),
1669
 
                        "horizontal-offset", horizontal_offset,
1670
 
                        "vertical-offset", vertical_offset,
1671
 
                        "horizontal-padding", &horizontal_padding,
1672
 
                        "vertical-padding", &vertical_padding,
1673
 
                        NULL);
1674
 
 
1675
 
  *vertical_offset -= GTK_WIDGET (menu)->style->ythickness;
1676
 
  *vertical_offset -= vertical_padding;
1677
 
  *horizontal_offset += horizontal_padding;
1678
 
}
1679
 
 
1680
 
static void
1681
 
gtk_menu_item_position_menu (GtkMenu  *menu,
1682
 
                             gint     *x,
1683
 
                             gint     *y,
1684
 
                             gboolean *push_in,
1685
 
                             gpointer  user_data)
1686
 
{
1687
 
  GtkMenuItem *menu_item;
1688
 
  GtkWidget *widget;
1689
 
  GtkMenuItem *parent_menu_item;
1690
 
  GdkScreen *screen;
1691
 
  gint twidth, theight;
1692
 
  gint tx, ty;
1693
 
  GtkTextDirection direction;
1694
 
  GdkRectangle monitor;
1695
 
  gint monitor_num;
1696
 
  gint horizontal_offset;
1697
 
  gint vertical_offset;
1698
 
  gint parent_xthickness;
1699
 
  gint available_left, available_right;
1700
 
 
1701
 
  g_return_if_fail (menu != NULL);
1702
 
  g_return_if_fail (x != NULL);
1703
 
  g_return_if_fail (y != NULL);
1704
 
 
1705
 
  menu_item = GTK_MENU_ITEM (user_data);
1706
 
  widget = GTK_WIDGET (user_data);
1707
 
 
1708
 
  if (push_in)
1709
 
    *push_in = FALSE;
1710
 
 
1711
 
  direction = gtk_widget_get_direction (widget);
1712
 
 
1713
 
  twidth = GTK_WIDGET (menu)->requisition.width;
1714
 
  theight = GTK_WIDGET (menu)->requisition.height;
1715
 
 
1716
 
  screen = gtk_widget_get_screen (GTK_WIDGET (menu));
1717
 
  monitor_num = gdk_screen_get_monitor_at_window (screen, menu_item->event_window);
1718
 
  if (monitor_num < 0)
1719
 
    monitor_num = 0;
1720
 
  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1721
 
 
1722
 
  if (!gdk_window_get_origin (widget->window, &tx, &ty))
1723
 
    {
1724
 
      g_warning ("Menu not on screen");
1725
 
      return;
1726
 
    }
1727
 
 
1728
 
  tx += widget->allocation.x;
1729
 
  ty += widget->allocation.y;
1730
 
 
1731
 
  get_offsets (menu, &horizontal_offset, &vertical_offset);
1732
 
 
1733
 
  available_left = tx - monitor.x;
1734
 
  available_right = monitor.x + monitor.width - (tx + widget->allocation.width);
1735
 
 
1736
 
  if (GTK_IS_MENU_BAR (widget->parent))
1737
 
    {
1738
 
      menu_item->from_menubar = TRUE;
1739
 
    }
1740
 
  else if (GTK_IS_MENU (widget->parent))
1741
 
    {
1742
 
      if (GTK_MENU (widget->parent)->parent_menu_item)
1743
 
        menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item)->from_menubar;
1744
 
      else
1745
 
        menu_item->from_menubar = FALSE;
1746
 
    }
1747
 
  else
1748
 
    {
1749
 
      menu_item->from_menubar = FALSE;
1750
 
    }
1751
 
  
1752
 
  switch (menu_item->submenu_placement)
1753
 
    {
1754
 
    case GTK_TOP_BOTTOM:
1755
 
      if (direction == GTK_TEXT_DIR_LTR)
1756
 
        menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1757
 
      else 
1758
 
        {
1759
 
          menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1760
 
          tx += widget->allocation.width - twidth;
1761
 
        }
1762
 
      if ((ty + widget->allocation.height + theight) <= monitor.y + monitor.height)
1763
 
        ty += widget->allocation.height;
1764
 
      else if ((ty - theight) >= monitor.y)
1765
 
        ty -= theight;
1766
 
      else if (monitor.y + monitor.height - (ty + widget->allocation.height) > ty)
1767
 
        ty += widget->allocation.height;
1768
 
      else
1769
 
        ty -= theight;
1770
 
      break;
1771
 
 
1772
 
    case GTK_LEFT_RIGHT:
1773
 
      if (GTK_IS_MENU (widget->parent))
1774
 
        parent_menu_item = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item);
1775
 
      else
1776
 
        parent_menu_item = NULL;
1777
 
      
1778
 
      parent_xthickness = widget->parent->style->xthickness;
1779
 
 
1780
 
      if (parent_menu_item && !GTK_MENU (widget->parent)->torn_off)
1781
 
        {
1782
 
          menu_item->submenu_direction = parent_menu_item->submenu_direction;
1783
 
        }
1784
 
      else
1785
 
        {
1786
 
          if (direction == GTK_TEXT_DIR_LTR)
1787
 
            menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1788
 
          else
1789
 
            menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1790
 
        }
1791
 
 
1792
 
      switch (menu_item->submenu_direction)
1793
 
        {
1794
 
        case GTK_DIRECTION_LEFT:
1795
 
          if (tx - twidth - parent_xthickness - horizontal_offset >= monitor.x ||
1796
 
              available_left >= available_right)
1797
 
            tx -= twidth + parent_xthickness + horizontal_offset;
1798
 
          else
1799
 
            {
1800
 
              menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1801
 
              tx += widget->allocation.width + parent_xthickness + horizontal_offset;
1802
 
            }
1803
 
          break;
1804
 
 
1805
 
        case GTK_DIRECTION_RIGHT:
1806
 
          if (tx + widget->allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
1807
 
              available_right >= available_left)
1808
 
            tx += widget->allocation.width + parent_xthickness + horizontal_offset;
1809
 
          else
1810
 
            {
1811
 
              menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1812
 
              tx -= twidth + parent_xthickness + horizontal_offset;
1813
 
            }
1814
 
          break;
1815
 
        }
1816
 
 
1817
 
      ty += vertical_offset;
1818
 
      
1819
 
      /* If the height of the menu doesn't fit we move it upward. */
1820
 
      ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight));
1821
 
      break;
1822
 
    }
1823
 
 
1824
 
  /* If we have negative, tx, here it is because we can't get
1825
 
   * the menu all the way on screen. Favor the left portion.
1826
 
   */
1827
 
  *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth));
1828
 
  *y = ty;
1829
 
 
1830
 
  gtk_menu_set_monitor (menu, monitor_num);
1831
 
 
1832
 
  if (!gtk_widget_get_visible (menu->toplevel))
1833
 
    {
1834
 
      gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar?
1835
 
                                GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
1836
 
    }
1837
 
}
1838
 
 
1839
 
/**
1840
 
 * gtk_menu_item_set_right_justified:
1841
 
 * @menu_item: a #GtkMenuItem.
1842
 
 * @right_justified: if %TRUE the menu item will appear at the 
1843
 
 *   far right if added to a menu bar.
1844
 
 * 
1845
 
 * Sets whether the menu item appears justified at the right
1846
 
 * side of a menu bar. This was traditionally done for "Help" menu
1847
 
 * items, but is now considered a bad idea. (If the widget
1848
 
 * layout is reversed for a right-to-left language like Hebrew
1849
 
 * or Arabic, right-justified-menu-items appear at the left.)
1850
 
 **/
1851
 
void
1852
 
gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
1853
 
                                   gboolean     right_justified)
1854
 
{
1855
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1856
 
 
1857
 
  right_justified = right_justified != FALSE;
1858
 
 
1859
 
  if (right_justified != menu_item->right_justify)
1860
 
    {
1861
 
      menu_item->right_justify = right_justified;
1862
 
      gtk_widget_queue_resize (GTK_WIDGET (menu_item));
1863
 
    }
1864
 
}
1865
 
 
1866
 
/**
1867
 
 * gtk_menu_item_get_right_justified:
1868
 
 * @menu_item: a #GtkMenuItem
1869
 
 * 
1870
 
 * Gets whether the menu item appears justified at the right
1871
 
 * side of the menu bar.
1872
 
 * 
1873
 
 * Return value: %TRUE if the menu item will appear at the
1874
 
 *   far right if added to a menu bar.
1875
 
 **/
1876
 
gboolean
1877
 
gtk_menu_item_get_right_justified (GtkMenuItem *menu_item)
1878
 
{
1879
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
1880
 
  
1881
 
  return menu_item->right_justify;
1882
 
}
1883
 
 
1884
 
 
1885
 
static void
1886
 
gtk_menu_item_show_all (GtkWidget *widget)
1887
 
{
1888
 
  GtkMenuItem *menu_item;
1889
 
 
1890
 
  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1891
 
 
1892
 
  menu_item = GTK_MENU_ITEM (widget);
1893
 
 
1894
 
  /* show children including submenu */
1895
 
  if (menu_item->submenu)
1896
 
    gtk_widget_show_all (menu_item->submenu);
1897
 
  gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_show_all, NULL);
1898
 
 
1899
 
  gtk_widget_show (widget);
1900
 
}
1901
 
 
1902
 
static void
1903
 
gtk_menu_item_hide_all (GtkWidget *widget)
1904
 
{
1905
 
  GtkMenuItem *menu_item;
1906
 
 
1907
 
  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1908
 
 
1909
 
  gtk_widget_hide (widget);
1910
 
 
1911
 
  menu_item = GTK_MENU_ITEM (widget);
1912
 
 
1913
 
  /* hide children including submenu */
1914
 
  gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_hide_all, NULL);
1915
 
  if (menu_item->submenu)
1916
 
    gtk_widget_hide_all (menu_item->submenu);
1917
 
}
1918
 
 
1919
 
static gboolean
1920
 
gtk_menu_item_can_activate_accel (GtkWidget *widget,
1921
 
                                  guint      signal_id)
1922
 
{
1923
 
  /* Chain to the parent GtkMenu for further checks */
1924
 
  return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
1925
 
          widget->parent && gtk_widget_can_activate_accel (widget->parent, signal_id));
1926
 
}
1927
 
 
1928
 
static void
1929
 
gtk_menu_item_accel_name_foreach (GtkWidget *widget,
1930
 
                                  gpointer data)
1931
 
{
1932
 
  const gchar **path_p = data;
1933
 
 
1934
 
  if (!*path_p)
1935
 
    {
1936
 
      if (GTK_IS_LABEL (widget))
1937
 
        {
1938
 
          *path_p = gtk_label_get_text (GTK_LABEL (widget));
1939
 
          if (*path_p && (*path_p)[0] == 0)
1940
 
            *path_p = NULL;
1941
 
        }
1942
 
      else if (GTK_IS_CONTAINER (widget))
1943
 
        gtk_container_foreach (GTK_CONTAINER (widget),
1944
 
                               gtk_menu_item_accel_name_foreach,
1945
 
                               data);
1946
 
    }
1947
 
}
1948
 
 
1949
 
static void
1950
 
gtk_menu_item_parent_set (GtkWidget *widget,
1951
 
                          GtkWidget *previous_parent)
1952
 
{
1953
 
  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1954
 
  GtkMenu *menu = GTK_IS_MENU (widget->parent) ? GTK_MENU (widget->parent) : NULL;
1955
 
 
1956
 
  if (menu)
1957
 
    _gtk_menu_item_refresh_accel_path (menu_item,
1958
 
                                       menu->accel_path,
1959
 
                                       menu->accel_group,
1960
 
                                       TRUE);
1961
 
 
1962
 
  if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
1963
 
    GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
1964
 
}
1965
 
 
1966
 
void
1967
 
_gtk_menu_item_refresh_accel_path (GtkMenuItem   *menu_item,
1968
 
                                   const gchar   *prefix,
1969
 
                                   GtkAccelGroup *accel_group,
1970
 
                                   gboolean       group_changed)
1971
 
{
1972
 
  const gchar *path;
1973
 
  GtkWidget *widget;
1974
 
 
1975
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1976
 
  g_return_if_fail (!accel_group || GTK_IS_ACCEL_GROUP (accel_group));
1977
 
 
1978
 
  widget = GTK_WIDGET (menu_item);
1979
 
 
1980
 
  if (!accel_group)
1981
 
    {
1982
 
      gtk_widget_set_accel_path (widget, NULL, NULL);
1983
 
      return;
1984
 
    }
1985
 
 
1986
 
  path = _gtk_widget_get_accel_path (widget, NULL);
1987
 
  if (!path)                                    /* no active accel_path yet */
1988
 
    {
1989
 
      path = menu_item->accel_path;
1990
 
      if (!path && prefix)
1991
 
        {
1992
 
          const gchar *postfix = NULL;
1993
 
          gchar *new_path;
1994
 
 
1995
 
          /* try to construct one from label text */
1996
 
          gtk_container_foreach (GTK_CONTAINER (menu_item),
1997
 
                                 gtk_menu_item_accel_name_foreach,
1998
 
                                 &postfix);
1999
 
          if (postfix)
2000
 
            {
2001
 
              new_path = g_strconcat (prefix, "/", postfix, NULL);
2002
 
              path = menu_item->accel_path = (char*)g_intern_string (new_path);
2003
 
              g_free (new_path);
2004
 
            }
2005
 
        }
2006
 
      if (path)
2007
 
        gtk_widget_set_accel_path (widget, path, accel_group);
2008
 
    }
2009
 
  else if (group_changed)                       /* reinstall accelerators */
2010
 
    gtk_widget_set_accel_path (widget, path, accel_group);
2011
 
}
2012
 
 
2013
 
/**
2014
 
 * gtk_menu_item_set_accel_path
2015
 
 * @menu_item:  a valid #GtkMenuItem
2016
 
 * @accel_path: (allow-none): accelerator path, corresponding to this menu item's
2017
 
 *              functionality, or %NULL to unset the current path.
2018
 
 *
2019
 
 * Set the accelerator path on @menu_item, through which runtime changes of the
2020
 
 * menu item's accelerator caused by the user can be identified and saved to
2021
 
 * persistant storage (see gtk_accel_map_save() on this).
2022
 
 * To setup a default accelerator for this menu item, call
2023
 
 * gtk_accel_map_add_entry() with the same @accel_path.
2024
 
 * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
2025
 
 * and gtk_menu_set_accel_path() for a more convenient variant of this function.
2026
 
 *
2027
 
 * This function is basically a convenience wrapper that handles calling
2028
 
 * gtk_widget_set_accel_path() with the appropriate accelerator group for
2029
 
 * the menu item.
2030
 
 *
2031
 
 * Note that you do need to set an accelerator on the parent menu with
2032
 
 * gtk_menu_set_accel_group() for this to work.
2033
 
 *
2034
 
 * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
2035
 
 * pass a static string, you can save some memory by interning it first with 
2036
 
 * g_intern_static_string().
2037
 
 */
2038
 
void
2039
 
gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
2040
 
                              const gchar *accel_path)
2041
 
{
2042
 
  GtkWidget *widget;
2043
 
 
2044
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2045
 
  g_return_if_fail (accel_path == NULL ||
2046
 
                    (accel_path[0] == '<' && strchr (accel_path, '/')));
2047
 
 
2048
 
  widget = GTK_WIDGET (menu_item);
2049
 
 
2050
 
  /* store new path */
2051
 
  menu_item->accel_path = (char*)g_intern_string (accel_path);
2052
 
 
2053
 
  /* forget accelerators associated with old path */
2054
 
  gtk_widget_set_accel_path (widget, NULL, NULL);
2055
 
 
2056
 
  /* install accelerators associated with new path */
2057
 
  if (GTK_IS_MENU (widget->parent))
2058
 
    {
2059
 
      GtkMenu *menu = GTK_MENU (widget->parent);
2060
 
 
2061
 
      if (menu->accel_group)
2062
 
        _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
2063
 
                                           NULL,
2064
 
                                           menu->accel_group,
2065
 
                                           FALSE);
2066
 
    }
2067
 
}
2068
 
 
2069
 
/**
2070
 
 * gtk_menu_item_get_accel_path
2071
 
 * @menu_item:  a valid #GtkMenuItem
2072
 
 *
2073
 
 * Retrieve the accelerator path that was previously set on @menu_item.
2074
 
 *
2075
 
 * See gtk_menu_item_set_accel_path() for details.
2076
 
 *
2077
 
 * Returns: the accelerator path corresponding to this menu item's
2078
 
 *              functionality, or %NULL if not set
2079
 
 *
2080
 
 * Since: 2.14
2081
 
 */
2082
 
const gchar *
2083
 
gtk_menu_item_get_accel_path (GtkMenuItem *menu_item)
2084
 
{
2085
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2086
 
 
2087
 
  return menu_item->accel_path;
2088
 
}
2089
 
 
2090
 
static void
2091
 
gtk_menu_item_forall (GtkContainer *container,
2092
 
                      gboolean      include_internals,
2093
 
                      GtkCallback   callback,
2094
 
                      gpointer      callback_data)
2095
 
{
2096
 
  GtkBin *bin;
2097
 
 
2098
 
  g_return_if_fail (GTK_IS_MENU_ITEM (container));
2099
 
  g_return_if_fail (callback != NULL);
2100
 
 
2101
 
  bin = GTK_BIN (container);
2102
 
 
2103
 
  if (bin->child)
2104
 
    callback (bin->child, callback_data);
2105
 
}
2106
 
 
2107
 
gboolean
2108
 
_gtk_menu_item_is_selectable (GtkWidget *menu_item)
2109
 
{
2110
 
  if ((!GTK_BIN (menu_item)->child &&
2111
 
       G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
2112
 
      GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
2113
 
      !gtk_widget_is_sensitive (menu_item) ||
2114
 
      !gtk_widget_get_visible (menu_item))
2115
 
    return FALSE;
2116
 
 
2117
 
  return TRUE;
2118
 
}
2119
 
 
2120
 
static void
2121
 
gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
2122
 
{
2123
 
  GtkWidget *accel_label;
2124
 
 
2125
 
  if (!GTK_BIN (menu_item)->child)
2126
 
    {
2127
 
      accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
2128
 
      gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
2129
 
 
2130
 
      gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
2131
 
      gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), 
2132
 
                                        GTK_WIDGET (menu_item));
2133
 
      gtk_widget_show (accel_label);
2134
 
    }
2135
 
}
2136
 
 
2137
 
/**
2138
 
 * gtk_menu_item_set_label:
2139
 
 * @menu_item: a #GtkMenuItem
2140
 
 * @label: the text you want to set
2141
 
 *
2142
 
 * Sets @text on the @menu_item label
2143
 
 *
2144
 
 * Since: 2.16
2145
 
 **/
2146
 
void
2147
 
gtk_menu_item_set_label (GtkMenuItem *menu_item,
2148
 
                         const gchar *label)
2149
 
{
2150
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2151
 
 
2152
 
  GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
2153
 
}
2154
 
 
2155
 
/**
2156
 
 * gtk_menu_item_get_label:
2157
 
 * @menu_item: a #GtkMenuItem
2158
 
 *
2159
 
 * Sets @text on the @menu_item label
2160
 
 *
2161
 
 * Returns: The text in the @menu_item label. This is the internal
2162
 
 *   string used by the label, and must not be modified.
2163
 
 *
2164
 
 * Since: 2.16
2165
 
 **/
2166
 
const gchar *
2167
 
gtk_menu_item_get_label (GtkMenuItem *menu_item)
2168
 
{
2169
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2170
 
 
2171
 
  return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
2172
 
}
2173
 
 
2174
 
/**
2175
 
 * gtk_menu_item_set_use_underline:
2176
 
 * @menu_item: a #GtkMenuItem
2177
 
 * @setting: %TRUE if underlines in the text indicate mnemonics  
2178
 
 *
2179
 
 * If true, an underline in the text indicates the next character should be
2180
 
 * used for the mnemonic accelerator key.
2181
 
 *
2182
 
 * Since: 2.16
2183
 
 **/
2184
 
void
2185
 
gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
2186
 
                                 gboolean     setting)
2187
 
{
2188
 
  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2189
 
 
2190
 
  gtk_menu_item_ensure_label (menu_item);
2191
 
 
2192
 
  if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
2193
 
    {
2194
 
      gtk_label_set_use_underline (GTK_LABEL (GTK_BIN (menu_item)->child), setting);
2195
 
 
2196
 
      g_object_notify (G_OBJECT (menu_item), "use-underline");
2197
 
    }
2198
 
}
2199
 
 
2200
 
/**
2201
 
 * gtk_menu_item_get_use_underline:
2202
 
 * @menu_item: a #GtkMenuItem
2203
 
 *
2204
 
 * Checks if an underline in the text indicates the next character should be
2205
 
 * used for the mnemonic accelerator key.
2206
 
 *
2207
 
 * Return value: %TRUE if an embedded underline in the label indicates
2208
 
 *               the mnemonic accelerator key.
2209
 
 *
2210
 
 * Since: 2.16
2211
 
 **/
2212
 
gboolean
2213
 
gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
2214
 
{
2215
 
  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2216
 
 
2217
 
  gtk_menu_item_ensure_label (menu_item);
2218
 
  
2219
 
  if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
2220
 
    return gtk_label_get_use_underline (GTK_LABEL (GTK_BIN (menu_item)->child));
2221
 
 
2222
 
  return FALSE;
2223
 
}
2224
 
 
2225
 
 
2226
 
 
2227
 
#define __GTK_MENU_ITEM_C__
2228
 
#include "gtkaliasdef.c"