]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbar.c
Very basic functionality seems to be complete; I'll try compiling it
[~andy/gtk] / gtk / gtktoolbar.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * GtkToolbar copyright (C) Federico Mena
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include "gtktoolbar.h"
21
22
23 #define DEFAULT_SPACE_SIZE 5
24
25
26 typedef struct {
27         GtkWidget *button;
28         GtkWidget *icon;
29         GtkWidget *label;
30 } Child;
31
32
33 static void gtk_toolbar_class_init    (GtkToolbarClass *class);
34 static void gtk_toolbar_init          (GtkToolbar      *toolbar);
35 static void gtk_toolbar_destroy       (GtkObject       *object);
36 static void gtk_toolbar_map           (GtkWidget       *widget);
37 static void gtk_toolbar_unmap         (GtkWidget       *widget);
38 static void gtk_toolbar_draw          (GtkWidget       *widget,
39                                        GdkRectangle    *area);
40 static void gtk_toolbar_size_request  (GtkWidget       *widget,
41                                        GtkRequisition  *requisition);
42 static void gtk_toolbar_size_allocate (GtkWidget       *widget,
43                                        GtkAllocation   *allocation);
44 static void gtk_toolbar_add           (GtkContainer    *container,
45                                        GtkWidget       *widget);
46
47 static GtkContainerClass *parent_class;
48
49
50 guint
51 gtk_toolbar_get_type(void)
52 {
53         static guint toolbar_type = 0;
54
55         if (!toolbar_type) {
56                 GtkTypeInfo toolbar_info = {
57                         "GtkToolbar",
58                         sizeof(GtkToolbar),
59                         sizeof(GtkToolbarClass),
60                         (GtkClassInitFunc) gtk_toolbar_class_init,
61                         (GtkObjectInitFunc) gtk_toolbar_init,
62                         (GtkArgFunc) NULL
63                 };
64
65                 toolbar_type = gtk_type_unique(gtk_container_get_type(), &toolbar_info);
66         }
67
68         return toolbar_type;
69 }
70
71 static void
72 gtk_toolbar_class_init(GtkToolbarClass *class)
73 {
74         GtkObjectClass *object_class;
75         GtkWidgetClass *widget_class;
76         GtkContainerClass *container_class;
77
78         object_class = (GtkObjectClass *) class;
79         widget_class = (GtkWidgetClass *) class;
80         container_class = (GtkContainerClass *) class;
81
82         parent_class = gtk_type_class(gtk_container_get_type());
83
84         object_class->destroy = gtk_toolbar_destroy;
85
86         widget_class->map = gtk_toolbar_map;
87         widget_class->unmap = gtk_toolbar_unmap;
88         widget_class->draw = gtk_toolbar_draw;
89         widget_class->size_request = gtk_toolbar_size_request;
90         widget_class->size_allocate = gtk_toolbar_size_allocate;
91
92         container_class->add = gtk_toolbar_add;
93 }
94
95 static void
96 gtk_toolbar_init(GtkToolbar *toolbar)
97 {
98         GTK_WIDGET_SET_FLAGS(toolbar, GTK_NO_WINDOW);
99
100         toolbar->num_children = 0;
101         toolbar->children     = NULL;
102         toolbar->orientation  = GTK_ORIENTATION_HORIZONTAL;
103         toolbar->style        = GTK_TOOLBAR_ICONS;
104         toolbar->space_size   = DEFAULT_SPACE_SIZE;
105 }
106
107 GtkWidget *
108 gtk_toolbar_new(GtkOrientation  orientation,
109                 GtkToolbarStyle style)
110 {
111         GtkToolbar *toolbar;
112
113         toolbar = gtk_type_new(gtk_toolbar_get_type());
114
115         toolbar->orientation = orientation;
116         toolbar->style = style;
117 }
118
119
120 static void
121 gtk_toolbar_destroy(GtkObject *object)
122 {
123         GtkToolbar *toolbar;
124         GList      *children;
125         GtkWidget  *child;
126
127         g_return_if_fail(object != NULL);
128         g_return_if_fail(GTK_IS_TOOLBAR(object));
129
130         toolbar = GTK_TOOLBAR(object);
131
132         for (children = toolbar->children; children; children = children->next) {
133                 child = children->data;
134
135                 /* NULL child means it is a space in the toolbar, rather than a button */
136                 if (child) {
137                         child->button->parent = NULL;
138                         gtk_object_unref(GTK_OBJECT(child->button));
139                         gtk_widget_destroy(child->button);
140                         g_free(child);
141                 }
142         }
143
144         g_list_free(toolbar->children);
145
146         if (GTK_OBJECT_CLASS(parent_class)->destroy)
147                 (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
148 }
149
150 static void
151 gtk_toolbar_map(GtkWidget *widget)
152 {
153         GtkToolbar *toolbar;
154         GList      *children;
155         GtkWidget  *child;
156
157         g_return_if_fail(widget != NULL);
158         g_return_if_fail(GTK_IS_TOOLBAR(widget));
159
160         toolbar = GTK_TOOLBAR(widget);
161         GTK_WIDGET_SET_FLAGS(toolbar, GTK_MAPPED);
162
163         for (children = toolbar->children; children; children = children->next) {
164                 child = children->data;
165
166                 if (child && GTK_WIDGET_VISIBLE(child->button) && !GTK_WIDGET_MAPPED(child->button))
167                         gtk_widget_map(child->button);
168         }
169 }
170
171 static void
172 gtk_toolbar_unmap(GtkWidget *widget)
173 {
174         GtkToolbar *toolbar;
175         GList      *children;
176         GtkWidget  *child;
177
178         g_return_if_fail(widget != NULL);
179         g_return_if_fail(GTK_IS_TOOLBAR(widget));
180         
181         toolbar = GTK_TOOLBAR(widget);
182         GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_MAPPED);
183
184         for (children = toolbar->children; children; children = children->next) {
185                 child = children->data;
186
187                 if (child && GTK_WIDGET_VISIBLE(child->button) && GTK_WIDGET_MAPPED(child->button))
188                         gtk_widget_unmap(child->button);
189         }
190 }
191
192 static void
193 gtk_toolbar_draw(GtkWidget    *widget,
194                  GdkRectangle *area)
195 {
196         GtkToolbar   *toolbar;
197         GList        *children;
198         GtkWidget    *child;
199         GdkRectangle  child_area;
200
201         g_return_if_fail(widget != NULL);
202         g_return_if_fail(GTK_IS_TOOLBAR(widget));
203
204         if (GTK_WIDGET_DRAWABLE(widget)) {
205                 toolbar = GTK_TOOLBAR(widget);
206
207                 for (children = toolbar->children; children; children = children->next) {
208                         child = children->data;
209
210                         if (child && gtk_widget_intersect(child->button, area, &child_area))
211                                 gtk_widget_draw(child->button, &child_area);
212                 }
213         }
214 }
215
216 static void
217 gtk_toolbar_size_request(GtkWidget      *widget,
218                          GtkRequisition *requisition)
219 {
220         GtkToolbar     *toolbar;
221         GList          *children;
222         GtkWidget      *child;
223         gint            nchildren;
224
225         g_return_if_fail(widget != NULL);
226         g_return_if_fail(GTK_IS_TOOLBAR(widget));
227         g_return_if_fail(requisition != NULL);
228
229         toolbar = GTK_TOOLBAR(widget);
230
231         requisition->width = GTK_CONTAINER(toolbar)->border_width * 2;
232         requisition->height = GTK_CONTAINER(toolbar)->border_width * 2;
233         nchildren = 0;
234         toolbar->child_maxw = 0;
235         toolbar->child_maxh = 0;
236
237         for (children = toolbar->children; children; children = children->next) {
238                 child = children->data;
239
240                 if (child) {
241                         nchildren++;
242
243                         gtk_widget_size_request(child->button, &child->button->requisition);
244
245                         toolbar->child_maxw = MAX(toolbar->child_maxw, child->button->requisition->width);
246                         toolbar->child_maxh = MAX(toolbar->child_maxh, child->button->requisition->height);
247                 } else
248                         /* NULL child means it is a space in the toolbar, rather than a button */
249                         if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
250                                 requisition->width += toolbar->space_size;
251                         else
252                                 requisition->height += toolbar->space_size;
253         }
254
255         if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) {
256                 requisition->width += nchildren * toolbar->child_maxw;
257                 requisition->height += toolbar->child_maxh;
258         } else {
259                 requisition->width += toolbar->child_maxw;
260                 requisition->height += nchildren * toolbar->child_maxh;
261         }
262 }
263
264 static void
265 gtk_toolbar_size_allocate(GtkWidget     *widget,
266                           GtkAllocation *allocation)
267 {
268         GtkToolbar     *toolbar;
269         GList          *children;
270         GtkWidget      *child;
271         GtkAllocation   alloc;
272
273         g_return_if_fail(widget != NULL);
274         g_return_if_fail(GTK_IS_TOOLBAR(widget));
275         g_return_if_fail(allocation != NULL);
276
277         toolbar = GTK_TOOLBAR(widget);
278         widget->allocation = *allocation;
279
280         alloc.x      = allocation->x + GTK_CONTAINER(toolbar)->border_width;
281         alloc.y      = allocation->y + GTK_CONTAINER(toolbar)->border_width;
282         alloc.width  = toolbar->child_maxw;
283         alloc.height = toolbar->child_maxh;
284
285         for (children = toolbar->children; children; children = children->next) {
286                 child = children->data;
287
288                 if (child) {
289                         gtk_widget_size_allocate(child->button, &alloc);
290
291                         if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
292                                 alloc.x += toolbar->child_maxw;
293                         else
294                                 alloc.y += toolbar->child_maxh;
295                 } else
296                         /* NULL child means it is a space in the toolbar, rather than a button */
297                         if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
298                                 alloc.x += toolbar->space_size;
299                         else
300                                 alloc.y += toolbar->space_size;
301         }
302 }
303
304 static void
305 gtk_toolbar_add(GtkContainer *container,
306                 GtkWidget    *widget)
307 {
308         g_warning("gtk_toolbar_add: use gtk_toolbar_add_item() instead!");
309 }
310
311 void
312 gtk_toolbar_append_item(GtkToolbar      *toolbar,
313                         const char      *text,
314                         const char      *tooltip_text,
315                         GtkPixmap       *icon)
316 {
317         gtk_toolbar_insert_item(toolbar, text, tooltip_text, icon, toolbar->num_children);
318 }
319
320 void
321 gtk_toolbar_prepend_item(GtkToolbar      *toolbar,
322                          const char      *text,
323                          const char      *tooltip_text,
324                          GtkPixmap       *icon)
325 {
326         gtk_toolbar_insert_item(toolbar, text, tooltip_text, icon, 0);
327 }
328
329 void
330 gtk_toolbar_insert_item(GtkToolbar      *toolbar,
331                         const char      *text,
332                         const char      *tooltip_text,
333                         GtkPixmap       *icon,
334                         gint             position)
335 {
336         Child     *child;
337         GtkWidget *vbox;
338         GtkWidget *label;
339
340         g_return_if_fail(toolbar != NULL);
341         g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
342
343         child = g_new(Child, 1);
344
345         child->button = gtk_button_new();
346
347         if (text)
348                 child->label = gtk_label_new(text);
349         else
350                 child->label = NULL;
351         
352         child->icon = icon;
353
354         vbox = gtk_vbox_new(FALSE, 0);
355         gtk_container_add(GTK_CONTAINER(button), vbox);
356         gtk_widget_show(vbox);
357
358         if (child->icon)
359                 gtk_box_pack_start(GTK_BOX(vbox), child->icon);
360
361         if (child->label)
362                 gtk_box_pack_start(GTK_BOX(vbox), child->label);
363
364         switch (toolbar->style) {
365                 case GTK_TOOLBAR_ICONS:
366                         if (child->icon)
367                                 gtk_widget_show(child->icon);
368                         break;
369
370                 case GTK_TOOLBAR_TEXT:
371                         if (child->label)
372                                 gtk_widget_show(child->label);
373                         break;
374
375                 case GTK_TOOLBAR_BOTH:
376                         if (child->icon)
377                                 gtk_widget_show(child->icon);
378
379                         if (child->label)
380                                 gtk_widget_show(child->label);
381
382                         break;
383
384                 default:
385                         g_assert_not_reached();
386         }
387
388         gtk_widget_show(child->button);
389
390         toolbar->children = g_list_insert(toolbar->children, child, position);
391         toolbar->num_children++;
392
393         gtk_widget_set_parent(child->button, toolbar);
394
395         if (GTK_WIDGET_VISIBLE(toolbar)) {
396                 if (GTK_WIDGET_REALIZED(toolbar)
397                     && !GTK_WIDGET_REALIZED(button))
398                         gtk_widget_realize(button);
399
400                 if (GTK_WIDGET_MAPPED(toolbar)
401                     && !GTK_WIDGET_MAPPED(button))
402                         gtk_widget_map(button);
403         }
404
405         if (GTK_WIDGET_VISIBLE(button) && GTK_WIDGET_VISIBLE(toolbar))
406                 gtk_widget_queue_resize(button);
407 }
408
409 void
410 gtk_toolbar_append_space(GtkToolbar *toolbar)
411 {
412         gtk_toolbar_insert_space(toolbar, toolbar->num_children);
413 }
414
415 void
416 gtk_toolbar_prepend_space(GtkToolbar *toolbar)
417 {
418         gtk_toolbar_insert_space(toolbar, 0);
419 }
420
421 void
422 gtk_toolbar_insert_space(GtkToolbar *toolbar,
423                          gint        position)
424 {
425         g_return_if_fail(toolbar != NULL);
426         g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
427
428         /* NULL child means it is a space in the toolbar, rather than a button */
429
430         toolbar->children = g_list_insert(toolbar->children, NULL);
431
432         if (GTK_WIDGET_VISIBLE(toolbar))
433                 gtk_widget_queue_resize(GTK_WIDGET(toolbar));
434 }