source: trunk/third/gtk/gtk/gtkmenubar.c @ 14482

Revision 14482, 11.1 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14481, which included commits to RCS files with non-trunk default branches.
Line 
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 Library 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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library 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-1999.  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#include "gdk/gdkkeysyms.h"
28#include "gtkbindings.h"
29#include "gtkmain.h"
30#include "gtkmenubar.h"
31#include "gtkmenuitem.h"
32
33enum {
34  ARG_0,
35  ARG_SHADOW
36};
37
38
39#define BORDER_SPACING  0
40#define CHILD_SPACING   3
41
42
43static void gtk_menu_bar_class_init    (GtkMenuBarClass *klass);
44static void gtk_menu_bar_init          (GtkMenuBar      *menu_bar);
45static void gtk_menu_bar_set_arg       (GtkObject      *object,
46                                        GtkArg         *arg,
47                                        guint           arg_id);
48static void gtk_menu_bar_get_arg       (GtkObject      *object,
49                                        GtkArg         *arg,
50                                        guint           arg_id);
51static void gtk_menu_bar_size_request  (GtkWidget       *widget,
52                                        GtkRequisition  *requisition);
53static void gtk_menu_bar_size_allocate (GtkWidget       *widget,
54                                        GtkAllocation   *allocation);
55static void gtk_menu_bar_paint         (GtkWidget       *widget,
56                                        GdkRectangle    *area);
57static void gtk_menu_bar_draw          (GtkWidget       *widget,
58                                        GdkRectangle    *area);
59static gint gtk_menu_bar_expose        (GtkWidget       *widget,
60                                        GdkEventExpose  *event);
61
62
63GtkType
64gtk_menu_bar_get_type (void)
65{
66  static GtkType menu_bar_type = 0;
67
68  if (!menu_bar_type)
69    {
70      static const GtkTypeInfo menu_bar_info =
71      {
72        "GtkMenuBar",
73        sizeof (GtkMenuBar),
74        sizeof (GtkMenuBarClass),
75        (GtkClassInitFunc) gtk_menu_bar_class_init,
76        (GtkObjectInitFunc) gtk_menu_bar_init,
77        /* reserved_1 */ NULL,
78        /* reserved_2 */ NULL,
79        (GtkClassInitFunc) NULL,
80      };
81
82      menu_bar_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_bar_info);
83    }
84
85  return menu_bar_type;
86}
87
88static void
89gtk_menu_bar_class_init (GtkMenuBarClass *class)
90{
91  GtkObjectClass *object_class;
92  GtkWidgetClass *widget_class;
93  GtkMenuShellClass *menu_shell_class;
94
95  GtkBindingSet *binding_set;
96
97  object_class = (GtkObjectClass*) class;
98  widget_class = (GtkWidgetClass*) class;
99  menu_shell_class = (GtkMenuShellClass*) class;
100
101  gtk_object_add_arg_type ("GtkMenuBar::shadow", GTK_TYPE_SHADOW_TYPE, GTK_ARG_READWRITE, ARG_SHADOW);
102
103  object_class->set_arg = gtk_menu_bar_set_arg;
104  object_class->get_arg = gtk_menu_bar_get_arg;
105
106  widget_class->draw = gtk_menu_bar_draw;
107  widget_class->size_request = gtk_menu_bar_size_request;
108  widget_class->size_allocate = gtk_menu_bar_size_allocate;
109  widget_class->expose_event = gtk_menu_bar_expose;
110
111  menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
112
113  binding_set = gtk_binding_set_by_class (class);
114  gtk_binding_entry_add_signal (binding_set,
115                                GDK_Left, 0,
116                                "move_current", 1,
117                                GTK_TYPE_MENU_DIRECTION_TYPE,
118                                GTK_MENU_DIR_PREV);
119  gtk_binding_entry_add_signal (binding_set,
120                                GDK_Right, 0,
121                                "move_current", 1,
122                                GTK_TYPE_MENU_DIRECTION_TYPE,
123                                GTK_MENU_DIR_NEXT);
124  gtk_binding_entry_add_signal (binding_set,
125                                GDK_Up, 0,
126                                "move_current", 1,
127                                GTK_TYPE_MENU_DIRECTION_TYPE,
128                                GTK_MENU_DIR_PARENT);
129  gtk_binding_entry_add_signal (binding_set,
130                                GDK_Down, 0,
131                                "move_current", 1,
132                                GTK_TYPE_MENU_DIRECTION_TYPE,
133                                GTK_MENU_DIR_CHILD);
134}
135
136static void
137gtk_menu_bar_init (GtkMenuBar *menu_bar)
138{
139  menu_bar->shadow_type = GTK_SHADOW_OUT;
140}
141
142static void
143gtk_menu_bar_set_arg (GtkObject      *object,
144                      GtkArg         *arg,
145                      guint           arg_id)
146{
147  GtkMenuBar *menu_bar;
148
149  menu_bar = GTK_MENU_BAR (object);
150
151  switch (arg_id)
152    {
153    case ARG_SHADOW:
154      gtk_menu_bar_set_shadow_type (menu_bar, GTK_VALUE_ENUM (*arg));
155      break;
156    default:
157      break;
158    }
159}
160
161static void
162gtk_menu_bar_get_arg (GtkObject      *object,
163                      GtkArg         *arg,
164                      guint           arg_id)
165{
166  GtkMenuBar *menu_bar;
167
168  menu_bar = GTK_MENU_BAR (object);
169
170  switch (arg_id)
171    {
172    case ARG_SHADOW:
173      GTK_VALUE_ENUM (*arg) = menu_bar->shadow_type;
174      break;
175    default:
176      arg->type = GTK_TYPE_INVALID;
177      break;
178    }
179}
180 
181GtkWidget*
182gtk_menu_bar_new (void)
183{
184  return GTK_WIDGET (gtk_type_new (gtk_menu_bar_get_type ()));
185}
186
187void
188gtk_menu_bar_append (GtkMenuBar *menu_bar,
189                     GtkWidget  *child)
190{
191  gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), child);
192}
193
194void
195gtk_menu_bar_prepend (GtkMenuBar *menu_bar,
196                      GtkWidget  *child)
197{
198  gtk_menu_shell_prepend (GTK_MENU_SHELL (menu_bar), child);
199}
200
201void
202gtk_menu_bar_insert (GtkMenuBar *menu_bar,
203                     GtkWidget  *child,
204                     gint        position)
205{
206  gtk_menu_shell_insert (GTK_MENU_SHELL (menu_bar), child, position);
207}
208
209
210static void
211gtk_menu_bar_size_request (GtkWidget      *widget,
212                           GtkRequisition *requisition)
213{
214  GtkMenuBar *menu_bar;
215  GtkMenuShell *menu_shell;
216  GtkWidget *child;
217  GList *children;
218  gint nchildren;
219  GtkRequisition child_requisition;
220
221  g_return_if_fail (widget != NULL);
222  g_return_if_fail (GTK_IS_MENU_BAR (widget));
223  g_return_if_fail (requisition != NULL);
224
225  requisition->width = 0;
226  requisition->height = 0;
227
228  if (GTK_WIDGET_VISIBLE (widget))
229    {
230      menu_bar = GTK_MENU_BAR (widget);
231      menu_shell = GTK_MENU_SHELL (widget);
232
233      nchildren = 0;
234      children = menu_shell->children;
235
236      while (children)
237        {
238          child = children->data;
239          children = children->next;
240
241          if (GTK_WIDGET_VISIBLE (child))
242            {
243              GTK_MENU_ITEM (child)->show_submenu_indicator = FALSE;
244              gtk_widget_size_request (child, &child_requisition);
245
246              requisition->width += child_requisition.width;
247              requisition->height = MAX (requisition->height, child_requisition.height);
248              /* Support for the right justified help menu */
249              if ((children == NULL) && GTK_IS_MENU_ITEM(child) &&
250                  GTK_MENU_ITEM(child)->right_justify)
251                {
252                  requisition->width += CHILD_SPACING;
253                }
254
255              nchildren += 1;
256            }
257        }
258
259      requisition->width += (GTK_CONTAINER (menu_bar)->border_width +
260                             widget->style->klass->xthickness +
261                             BORDER_SPACING) * 2;
262      requisition->height += (GTK_CONTAINER (menu_bar)->border_width +
263                              widget->style->klass->ythickness +
264                              BORDER_SPACING) * 2;
265
266      if (nchildren > 0)
267        requisition->width += 2 * CHILD_SPACING * (nchildren - 1);
268    }
269}
270
271static void
272gtk_menu_bar_size_allocate (GtkWidget     *widget,
273                            GtkAllocation *allocation)
274{
275  GtkMenuBar *menu_bar;
276  GtkMenuShell *menu_shell;
277  GtkWidget *child;
278  GList *children;
279  GtkAllocation child_allocation;
280  GtkRequisition child_requisition;
281  guint offset;
282 
283  g_return_if_fail (widget != NULL);
284  g_return_if_fail (GTK_IS_MENU_BAR (widget));
285  g_return_if_fail (allocation != NULL);
286
287  menu_bar = GTK_MENU_BAR (widget);
288  menu_shell = GTK_MENU_SHELL (widget);
289
290  widget->allocation = *allocation;
291  if (GTK_WIDGET_REALIZED (widget))
292    gdk_window_move_resize (widget->window,
293                            allocation->x, allocation->y,
294                            allocation->width, allocation->height);
295
296  if (menu_shell->children)
297    {
298      child_allocation.x = (GTK_CONTAINER (menu_bar)->border_width +
299                            widget->style->klass->xthickness +
300                            BORDER_SPACING);
301      offset = child_allocation.x;      /* Window edge to menubar start */
302
303      child_allocation.y = (GTK_CONTAINER (menu_bar)->border_width +
304                            widget->style->klass->ythickness +
305                            BORDER_SPACING);
306      child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
307
308      children = menu_shell->children;
309      while (children)
310        {
311          child = children->data;
312          children = children->next;
313
314          gtk_widget_get_child_requisition (child, &child_requisition);
315         
316          /* Support for the right justified help menu */
317          if ( (children == NULL) && (GTK_IS_MENU_ITEM(child))
318              && (GTK_MENU_ITEM(child)->right_justify))
319            {
320              child_allocation.x = allocation->width -
321                  child_requisition.width - CHILD_SPACING - offset;
322            }
323          if (GTK_WIDGET_VISIBLE (child))
324            {
325              child_allocation.width = child_requisition.width;
326
327              gtk_widget_size_allocate (child, &child_allocation);
328
329              child_allocation.x += child_allocation.width + CHILD_SPACING * 2;
330            }
331        }
332    }
333}
334
335void
336gtk_menu_bar_set_shadow_type (GtkMenuBar    *menu_bar,
337                              GtkShadowType  type)
338{
339  g_return_if_fail (menu_bar != NULL);
340  g_return_if_fail (GTK_IS_MENU_BAR (menu_bar));
341
342  if ((GtkShadowType) menu_bar->shadow_type != type)
343    {
344      menu_bar->shadow_type = type;
345
346      if (GTK_WIDGET_DRAWABLE (menu_bar))
347        {
348          gtk_widget_queue_clear (GTK_WIDGET (menu_bar));
349        }
350      gtk_widget_queue_resize (GTK_WIDGET (menu_bar));
351    }
352}
353
354static void
355gtk_menu_bar_paint (GtkWidget *widget, GdkRectangle *area)
356{
357  g_return_if_fail (widget != NULL);
358  g_return_if_fail (GTK_IS_MENU_BAR (widget));
359
360  if (GTK_WIDGET_DRAWABLE (widget))
361    {
362      gtk_paint_box (widget->style,
363                     widget->window,
364                     GTK_STATE_NORMAL,
365                     GTK_MENU_BAR (widget)->shadow_type,
366                     area, widget, "menubar",
367                     0, 0,
368                     -1,-1);
369    }
370}
371
372static void
373gtk_menu_bar_draw (GtkWidget    *widget,
374                   GdkRectangle *area)
375{
376  GtkMenuShell *menu_shell;
377  GtkWidget *child;
378  GdkRectangle child_area;
379  GList *children;
380
381  g_return_if_fail (widget != NULL);
382  g_return_if_fail (GTK_IS_MENU_BAR (widget));
383  g_return_if_fail (area != NULL);
384
385  if (GTK_WIDGET_DRAWABLE (widget))
386    {
387      gtk_menu_bar_paint (widget, area);
388
389      menu_shell = GTK_MENU_SHELL (widget);
390
391      children = menu_shell->children;
392      while (children)
393        {
394          child = children->data;
395          children = children->next;
396
397          if (gtk_widget_intersect (child, area, &child_area))
398            gtk_widget_draw (child, &child_area);
399        }
400    }
401}
402
403static gint
404gtk_menu_bar_expose (GtkWidget      *widget,
405                     GdkEventExpose *event)
406{
407  GtkMenuShell *menu_shell;
408  GdkEventExpose child_event;
409  GList *children;
410  GtkWidget *child;
411
412  g_return_val_if_fail (widget != NULL, FALSE);
413  g_return_val_if_fail (GTK_IS_MENU_BAR (widget), FALSE);
414  g_return_val_if_fail (event != NULL, FALSE);
415
416  if (GTK_WIDGET_DRAWABLE (widget))
417    {
418      gtk_menu_bar_paint (widget, &event->area);
419
420      menu_shell = GTK_MENU_SHELL (widget);
421      child_event = *event;
422
423      children = menu_shell->children;
424      while (children)
425        {
426          child = children->data;
427          children = children->next;
428
429          if (GTK_WIDGET_NO_WINDOW (child) &&
430              gtk_widget_intersect (child, &event->area, &child_event.area))
431            gtk_widget_event (child, (GdkEvent*) &child_event);
432        }
433    }
434
435  return FALSE;
436}
Note: See TracBrowser for help on using the repository browser.