]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenubar.c
call the base class init fucntions from all parent types upon class
[~andy/gtk] / gtk / gtkmenubar.c
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 #include "gtkmain.h"
20 #include "gtkmenubar.h"
21 #include "gtkmenuitem.h"
22
23
24 #define BORDER_SPACING  2
25 #define CHILD_SPACING   3
26
27
28 static void gtk_menu_bar_class_init    (GtkMenuBarClass *klass);
29 static void gtk_menu_bar_init          (GtkMenuBar      *menu_bar);
30 static void gtk_menu_bar_size_request  (GtkWidget       *widget,
31                                         GtkRequisition  *requisition);
32 static void gtk_menu_bar_size_allocate (GtkWidget       *widget,
33                                         GtkAllocation   *allocation);
34 static void gtk_menu_bar_paint         (GtkWidget       *widget);
35 static void gtk_menu_bar_draw          (GtkWidget       *widget,
36                                         GdkRectangle    *area);
37 static gint gtk_menu_bar_expose        (GtkWidget       *widget,
38                                         GdkEventExpose  *event);
39
40
41 GtkType
42 gtk_menu_bar_get_type (void)
43 {
44   static GtkType menu_bar_type = 0;
45
46   if (!menu_bar_type)
47     {
48       GtkTypeInfo menu_bar_info =
49       {
50         "GtkMenuBar",
51         sizeof (GtkMenuBar),
52         sizeof (GtkMenuBarClass),
53         (GtkClassInitFunc) gtk_menu_bar_class_init,
54         (GtkObjectInitFunc) gtk_menu_bar_init,
55         /* reversed_1 */ NULL,
56         /* reversed_2 */ NULL,
57         (GtkClassInitFunc) NULL,
58       };
59
60       menu_bar_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_bar_info);
61     }
62
63   return menu_bar_type;
64 }
65
66 static void
67 gtk_menu_bar_class_init (GtkMenuBarClass *class)
68 {
69   GtkWidgetClass *widget_class;
70   GtkMenuShellClass *menu_shell_class;
71
72   widget_class = (GtkWidgetClass*) class;
73   menu_shell_class = (GtkMenuShellClass*) class;
74
75   widget_class->draw = gtk_menu_bar_draw;
76   widget_class->size_request = gtk_menu_bar_size_request;
77   widget_class->size_allocate = gtk_menu_bar_size_allocate;
78   widget_class->expose_event = gtk_menu_bar_expose;
79
80   menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
81 }
82
83 static void
84 gtk_menu_bar_init (GtkMenuBar *menu_bar)
85 {
86 }
87
88 GtkWidget*
89 gtk_menu_bar_new (void)
90 {
91   return GTK_WIDGET (gtk_type_new (gtk_menu_bar_get_type ()));
92 }
93
94 void
95 gtk_menu_bar_append (GtkMenuBar *menu_bar,
96                      GtkWidget  *child)
97 {
98   gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), child);
99 }
100
101 void
102 gtk_menu_bar_prepend (GtkMenuBar *menu_bar,
103                       GtkWidget  *child)
104 {
105   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu_bar), child);
106 }
107
108 void
109 gtk_menu_bar_insert (GtkMenuBar *menu_bar,
110                      GtkWidget  *child,
111                      gint        position)
112 {
113   gtk_menu_shell_insert (GTK_MENU_SHELL (menu_bar), child, position);
114 }
115
116
117 static void
118 gtk_menu_bar_size_request (GtkWidget      *widget,
119                            GtkRequisition *requisition)
120 {
121   GtkMenuBar *menu_bar;
122   GtkMenuShell *menu_shell;
123   GtkWidget *child;
124   GList *children;
125   gint nchildren;
126
127   g_return_if_fail (widget != NULL);
128   g_return_if_fail (GTK_IS_MENU_BAR (widget));
129   g_return_if_fail (requisition != NULL);
130
131   requisition->width = 0;
132   requisition->height = 0;
133
134   if (GTK_WIDGET_VISIBLE (widget))
135     {
136       menu_bar = GTK_MENU_BAR (widget);
137       menu_shell = GTK_MENU_SHELL (widget);
138
139       nchildren = 0;
140       children = menu_shell->children;
141
142       while (children)
143         {
144           child = children->data;
145           children = children->next;
146
147           if (GTK_WIDGET_VISIBLE (child))
148             {
149               GTK_MENU_ITEM (child)->show_submenu_indicator = FALSE;
150               gtk_widget_size_request (child, &child->requisition);
151
152               requisition->width += child->requisition.width;
153               requisition->height = MAX (requisition->height, child->requisition.height);
154               /* Support for the right justified help menu */
155               if ( (children == NULL) && (GTK_IS_MENU_ITEM(child))
156                    && (GTK_MENU_ITEM(child)->right_justify))
157                 {
158                   requisition->width += CHILD_SPACING;
159                 }
160
161               nchildren += 1;
162             }
163         }
164
165       requisition->width += (GTK_CONTAINER (menu_bar)->border_width +
166                              widget->style->klass->xthickness +
167                              BORDER_SPACING) * 2;
168       requisition->height += (GTK_CONTAINER (menu_bar)->border_width +
169                               widget->style->klass->ythickness +
170                               BORDER_SPACING) * 2;
171
172       if (nchildren > 0)
173         requisition->width += 2 * CHILD_SPACING * (nchildren - 1);
174     }
175 }
176
177 static void
178 gtk_menu_bar_size_allocate (GtkWidget     *widget,
179                             GtkAllocation *allocation)
180 {
181   GtkMenuBar *menu_bar;
182   GtkMenuShell *menu_shell;
183   GtkWidget *child;
184   GList *children;
185   GtkAllocation child_allocation;
186   guint offset;
187   
188   g_return_if_fail (widget != NULL);
189   g_return_if_fail (GTK_IS_MENU_BAR (widget));
190   g_return_if_fail (allocation != NULL);
191
192   menu_bar = GTK_MENU_BAR (widget);
193   menu_shell = GTK_MENU_SHELL (widget);
194
195   widget->allocation = *allocation;
196   if (GTK_WIDGET_REALIZED (widget))
197     gdk_window_move_resize (widget->window,
198                             allocation->x, allocation->y,
199                             allocation->width, allocation->height);
200
201   if (menu_shell->children)
202     {
203       child_allocation.x = (GTK_CONTAINER (menu_bar)->border_width +
204                             widget->style->klass->xthickness +
205                             BORDER_SPACING);
206       offset = child_allocation.x;      /* Window edge to menubar start */
207
208       child_allocation.y = (GTK_CONTAINER (menu_bar)->border_width +
209                             widget->style->klass->ythickness +
210                             BORDER_SPACING);
211       child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
212
213       children = menu_shell->children;
214       while (children)
215         {
216           child = children->data;
217           children = children->next;
218
219           /* Support for the right justified help menu */
220           if ( (children == NULL) && (GTK_IS_MENU_ITEM(child))
221               && (GTK_MENU_ITEM(child)->right_justify)) 
222             {
223               child_allocation.x = allocation->width -
224                   child->requisition.width - CHILD_SPACING - offset;
225             }
226           if (GTK_WIDGET_VISIBLE (child))
227             {
228               child_allocation.width = child->requisition.width;
229
230               gtk_widget_size_allocate (child, &child_allocation);
231
232               child_allocation.x += child_allocation.width + CHILD_SPACING * 2;
233             }
234         }
235     }
236 }
237
238 static void
239 gtk_menu_bar_paint (GtkWidget *widget)
240 {
241   g_return_if_fail (widget != NULL);
242   g_return_if_fail (GTK_IS_MENU_BAR (widget));
243
244   if (GTK_WIDGET_DRAWABLE (widget))
245     {
246       gtk_draw_shadow (widget->style,
247                        widget->window,
248                        GTK_STATE_NORMAL,
249                        GTK_SHADOW_OUT,
250                        0, 0,
251                        widget->allocation.width,
252                        widget->allocation.height);
253     }
254 }
255
256 static void
257 gtk_menu_bar_draw (GtkWidget    *widget,
258                    GdkRectangle *area)
259 {
260   GtkMenuShell *menu_shell;
261   GtkWidget *child;
262   GdkRectangle child_area;
263   GList *children;
264
265   g_return_if_fail (widget != NULL);
266   g_return_if_fail (GTK_IS_MENU_BAR (widget));
267   g_return_if_fail (area != NULL);
268
269   if (GTK_WIDGET_DRAWABLE (widget))
270     {
271       gtk_menu_bar_paint (widget);
272
273       menu_shell = GTK_MENU_SHELL (widget);
274
275       children = menu_shell->children;
276       while (children)
277         {
278           child = children->data;
279           children = children->next;
280
281           if (gtk_widget_intersect (child, area, &child_area))
282             gtk_widget_draw (child, &child_area);
283         }
284     }
285 }
286
287 static gint
288 gtk_menu_bar_expose (GtkWidget      *widget,
289                      GdkEventExpose *event)
290 {
291   GtkMenuShell *menu_shell;
292   GtkWidget *child;
293   GdkEventExpose child_event;
294   GList *children;
295
296   g_return_val_if_fail (widget != NULL, FALSE);
297   g_return_val_if_fail (GTK_IS_MENU_BAR (widget), FALSE);
298   g_return_val_if_fail (event != NULL, FALSE);
299
300   if (GTK_WIDGET_DRAWABLE (widget))
301     {
302       gtk_menu_bar_paint (widget);
303
304       menu_shell = GTK_MENU_SHELL (widget);
305       child_event = *event;
306
307       children = menu_shell->children;
308       while (children)
309         {
310           child = children->data;
311           children = children->next;
312
313           if (GTK_WIDGET_NO_WINDOW (child) &&
314               gtk_widget_intersect (child, &event->area, &child_event.area))
315             gtk_widget_event (child, (GdkEvent*) &child_event);
316         }
317     }
318
319   return FALSE;
320 }