1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * GtkToolbar copyright (C) Federico Mena
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.
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.
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.
20 #include "gtkbutton.h"
23 #include "gtktoolbar.h"
26 #define DEFAULT_SPACE_SIZE 5
50 typedef void (*GtkToolbarSignal1) (GtkObject *object,
54 static void gtk_toolbar_marshal_signal_1 (GtkObject *object,
60 static void gtk_toolbar_class_init (GtkToolbarClass *class);
61 static void gtk_toolbar_init (GtkToolbar *toolbar);
62 static void gtk_toolbar_destroy (GtkObject *object);
63 static void gtk_toolbar_map (GtkWidget *widget);
64 static void gtk_toolbar_unmap (GtkWidget *widget);
65 static void gtk_toolbar_draw (GtkWidget *widget,
67 static gint gtk_toolbar_expose (GtkWidget *widget,
68 GdkEventExpose *event);
69 static void gtk_toolbar_size_request (GtkWidget *widget,
70 GtkRequisition *requisition);
71 static void gtk_toolbar_size_allocate (GtkWidget *widget,
72 GtkAllocation *allocation);
73 static void gtk_toolbar_add (GtkContainer *container,
75 static void gtk_toolbar_remove (GtkContainer *container,
77 static void gtk_toolbar_foreach (GtkContainer *container,
79 gpointer callback_data);
80 static void gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
81 GtkOrientation orientation);
82 static void gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
83 GtkToolbarStyle style);
86 static GtkContainerClass *parent_class;
88 static gint toolbar_signals[LAST_SIGNAL] = { 0 };
92 gtk_toolbar_get_type(void)
94 static guint toolbar_type = 0;
97 GtkTypeInfo toolbar_info = {
100 sizeof(GtkToolbarClass),
101 (GtkClassInitFunc) gtk_toolbar_class_init,
102 (GtkObjectInitFunc) gtk_toolbar_init,
106 toolbar_type = gtk_type_unique(gtk_container_get_type(), &toolbar_info);
113 gtk_toolbar_class_init(GtkToolbarClass *class)
115 GtkObjectClass *object_class;
116 GtkWidgetClass *widget_class;
117 GtkContainerClass *container_class;
119 object_class = (GtkObjectClass *) class;
120 widget_class = (GtkWidgetClass *) class;
121 container_class = (GtkContainerClass *) class;
123 parent_class = gtk_type_class(gtk_container_get_type());
125 toolbar_signals[ORIENTATION_CHANGED] =
126 gtk_signal_new("orientation_changed",
129 GTK_SIGNAL_OFFSET(GtkToolbarClass, orientation_changed),
130 gtk_toolbar_marshal_signal_1,
133 toolbar_signals[STYLE_CHANGED] =
134 gtk_signal_new("style_changed",
137 GTK_SIGNAL_OFFSET(GtkToolbarClass, style_changed),
138 gtk_toolbar_marshal_signal_1,
142 gtk_object_class_add_signals(object_class, toolbar_signals, LAST_SIGNAL);
144 object_class->destroy = gtk_toolbar_destroy;
146 widget_class->map = gtk_toolbar_map;
147 widget_class->unmap = gtk_toolbar_unmap;
148 widget_class->draw = gtk_toolbar_draw;
149 widget_class->expose_event = gtk_toolbar_expose;
150 widget_class->size_request = gtk_toolbar_size_request;
151 widget_class->size_allocate = gtk_toolbar_size_allocate;
153 container_class->add = gtk_toolbar_add;
154 container_class->remove = gtk_toolbar_remove;
155 container_class->foreach = gtk_toolbar_foreach;
157 class->orientation_changed = gtk_real_toolbar_orientation_changed;
158 class->style_changed = gtk_real_toolbar_style_changed;
162 gtk_toolbar_init(GtkToolbar *toolbar)
164 GTK_WIDGET_SET_FLAGS(toolbar, GTK_NO_WINDOW);
166 toolbar->num_children = 0;
167 toolbar->children = NULL;
168 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
169 toolbar->style = GTK_TOOLBAR_ICONS;
170 toolbar->space_size = DEFAULT_SPACE_SIZE;
171 toolbar->tooltips = gtk_tooltips_new();
172 toolbar->button_maxw = 0;
173 toolbar->button_maxh = 0;
177 gtk_toolbar_new(GtkOrientation orientation,
178 GtkToolbarStyle style)
182 toolbar = gtk_type_new(gtk_toolbar_get_type());
184 toolbar->orientation = orientation;
185 toolbar->style = style;
187 return GTK_WIDGET(toolbar);
192 gtk_toolbar_destroy(GtkObject *object)
198 g_return_if_fail(object != NULL);
199 g_return_if_fail(GTK_IS_TOOLBAR(object));
201 toolbar = GTK_TOOLBAR(object);
203 gtk_tooltips_unref(toolbar->tooltips);
205 for (children = toolbar->children; children; children = children->next) {
206 child = children->data;
208 if (child->type != CHILD_SPACE) {
209 child->widget->parent = NULL;
210 gtk_object_unref(GTK_OBJECT(child->widget));
211 gtk_widget_destroy(child->widget);
217 g_list_free(toolbar->children);
219 if (GTK_OBJECT_CLASS(parent_class)->destroy)
220 (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
224 gtk_toolbar_map(GtkWidget *widget)
230 g_return_if_fail(widget != NULL);
231 g_return_if_fail(GTK_IS_TOOLBAR(widget));
233 toolbar = GTK_TOOLBAR(widget);
234 GTK_WIDGET_SET_FLAGS(toolbar, GTK_MAPPED);
236 for (children = toolbar->children; children; children = children->next) {
237 child = children->data;
239 if ((child->type != CHILD_SPACE)
240 && GTK_WIDGET_VISIBLE(child->widget) && !GTK_WIDGET_MAPPED(child->widget))
241 gtk_widget_map(child->widget);
246 gtk_toolbar_unmap(GtkWidget *widget)
252 g_return_if_fail(widget != NULL);
253 g_return_if_fail(GTK_IS_TOOLBAR(widget));
255 toolbar = GTK_TOOLBAR(widget);
256 GTK_WIDGET_UNSET_FLAGS(toolbar, GTK_MAPPED);
258 for (children = toolbar->children; children; children = children->next) {
259 child = children->data;
261 if ((child->type != CHILD_SPACE)
262 && GTK_WIDGET_VISIBLE(child->widget) && GTK_WIDGET_MAPPED(child->widget))
263 gtk_widget_unmap(child->widget);
268 gtk_toolbar_draw(GtkWidget *widget,
274 GdkRectangle child_area;
276 g_return_if_fail(widget != NULL);
277 g_return_if_fail(GTK_IS_TOOLBAR(widget));
279 if (GTK_WIDGET_DRAWABLE(widget)) {
280 toolbar = GTK_TOOLBAR(widget);
282 for (children = toolbar->children; children; children = children->next) {
283 child = children->data;
285 if ((child->type != CHILD_SPACE)
286 && gtk_widget_intersect(child->widget, area, &child_area))
287 gtk_widget_draw(child->widget, &child_area);
293 gtk_toolbar_expose(GtkWidget *widget,
294 GdkEventExpose *event)
299 GdkEventExpose child_event;
301 g_return_val_if_fail(widget != NULL, FALSE);
302 g_return_val_if_fail(GTK_IS_TOOLBAR(widget), FALSE);
303 g_return_val_if_fail(event != NULL, FALSE);
305 if (GTK_WIDGET_DRAWABLE(widget)) {
306 toolbar = GTK_TOOLBAR(widget);
308 child_event = *event;
310 for (children = toolbar->children; children; children = children->next) {
311 child = children->data;
313 if ((child->type != CHILD_SPACE)
314 && GTK_WIDGET_NO_WINDOW(child->widget)
315 && gtk_widget_intersect(child->widget, &event->area, &child_event.area))
316 gtk_widget_event(child->widget, (GdkEvent *) &child_event);
324 gtk_toolbar_size_request(GtkWidget *widget,
325 GtkRequisition *requisition)
331 gint button_maxw, button_maxh;
332 gint widget_maxw, widget_maxh;
334 g_return_if_fail(widget != NULL);
335 g_return_if_fail(GTK_IS_TOOLBAR(widget));
336 g_return_if_fail(requisition != NULL);
338 toolbar = GTK_TOOLBAR(widget);
340 requisition->width = GTK_CONTAINER(toolbar)->border_width * 2;
341 requisition->height = GTK_CONTAINER(toolbar)->border_width * 2;
348 for (children = toolbar->children; children; children = children->next) {
349 child = children->data;
351 switch (child->type) {
353 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
354 requisition->width += toolbar->space_size;
356 requisition->height += toolbar->space_size;
361 if (GTK_WIDGET_VISIBLE(child->widget)) {
362 gtk_widget_size_request(child->widget, &child->widget->requisition);
365 button_maxw = MAX(button_maxw, child->widget->requisition.width);
366 button_maxh = MAX(button_maxh, child->widget->requisition.height);
372 if (GTK_WIDGET_VISIBLE(child->widget)) {
373 gtk_widget_size_request(child->widget, &child->widget->requisition);
375 widget_maxw = MAX(widget_maxw, child->widget->requisition.width);
376 widget_maxh = MAX(widget_maxh, child->widget->requisition.height);
378 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
379 requisition->width += child->widget->requisition.width;
381 requisition->height += child->widget->requisition.height;
387 g_assert_not_reached();
391 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) {
392 requisition->width += nbuttons * button_maxw;
393 requisition->height += MAX(button_maxh, widget_maxh);
395 requisition->width += MAX(button_maxw, widget_maxw);
396 requisition->height += nbuttons * button_maxh;
399 toolbar->button_maxw = button_maxw;
400 toolbar->button_maxh = button_maxh;
404 gtk_toolbar_size_allocate(GtkWidget *widget,
405 GtkAllocation *allocation)
413 g_return_if_fail(widget != NULL);
414 g_return_if_fail(GTK_IS_TOOLBAR(widget));
415 g_return_if_fail(allocation != NULL);
417 toolbar = GTK_TOOLBAR(widget);
418 widget->allocation = *allocation;
420 border_width = GTK_CONTAINER(toolbar)->border_width;
422 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
423 alloc.x = allocation->x + border_width;
425 alloc.y = allocation->y + border_width;
427 for (children = toolbar->children; children; children = children->next) {
428 child = children->data;
430 switch (child->type) {
432 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
433 alloc.x += toolbar->space_size;
435 alloc.y += toolbar->space_size;
440 alloc.width = toolbar->button_maxw;
441 alloc.height = toolbar->button_maxh;
443 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
444 alloc.y = (allocation->y
445 + (allocation->height - toolbar->button_maxh) / 2);
447 alloc.x = (allocation->x
448 + (allocation->width - toolbar->button_maxw) / 2);
450 gtk_widget_size_allocate(child->widget, &alloc);
452 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
453 alloc.x += toolbar->button_maxw;
455 alloc.y += toolbar->button_maxh;
460 alloc.width = child->widget->requisition.width;
461 alloc.height = child->widget->requisition.height;
463 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
464 alloc.y = (allocation->y
465 + (allocation->height
466 - child->widget->requisition.height) / 2);
468 alloc.x = (allocation->x
470 - child->widget->requisition.width) / 2);
472 gtk_widget_size_allocate(child->widget, &alloc);
474 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
475 alloc.x += child->widget->requisition.width;
477 alloc.y += child->widget->requisition.height;
482 g_assert_not_reached();
488 gtk_toolbar_add(GtkContainer *container,
491 g_return_if_fail(container != NULL);
492 g_return_if_fail(GTK_IS_TOOLBAR(container));
493 g_return_if_fail(widget != NULL);
495 gtk_toolbar_append_widget(GTK_TOOLBAR(container), NULL, widget);
499 gtk_toolbar_remove(GtkContainer *container,
506 g_return_if_fail(container != NULL);
507 g_return_if_fail(GTK_IS_TOOLBAR(container));
508 g_return_if_fail(widget != NULL);
510 toolbar = GTK_TOOLBAR(container);
512 for (children = toolbar->children; children; children = children->next) {
513 child = children->data;
515 if ((child->type != CHILD_SPACE) && (child->widget == widget)) {
516 gtk_widget_unparent(widget);
518 toolbar->children = g_list_remove_link(toolbar->children, children);
520 g_list_free(children);
521 toolbar->num_children--;
523 if (GTK_WIDGET_VISIBLE(widget) && GTK_WIDGET_VISIBLE(container))
524 gtk_widget_queue_resize(GTK_WIDGET(container));
532 gtk_toolbar_foreach(GtkContainer *container,
533 GtkCallback callback,
534 gpointer callback_data)
540 g_return_if_fail(container != NULL);
541 g_return_if_fail(GTK_IS_TOOLBAR(container));
542 g_return_if_fail(callback != NULL);
544 toolbar = GTK_TOOLBAR(container);
546 for (children = toolbar->children; children; children = children->next) {
547 child = children->data;
549 if (child->type != CHILD_SPACE)
550 (*callback) (child->widget, callback_data);
555 gtk_toolbar_append_item(GtkToolbar *toolbar,
557 const char *tooltip_text,
559 GtkSignalFunc callback,
562 return gtk_toolbar_insert_item(toolbar, text, tooltip_text, icon,
563 callback, user_data, toolbar->num_children);
567 gtk_toolbar_prepend_item(GtkToolbar *toolbar,
569 const char *tooltip_text,
571 GtkSignalFunc callback,
574 return gtk_toolbar_insert_item(toolbar, text, tooltip_text, icon,
575 callback, user_data, 0);
579 gtk_toolbar_insert_item(GtkToolbar *toolbar,
581 const char *tooltip_text,
583 GtkSignalFunc callback,
590 g_return_val_if_fail(toolbar != NULL, NULL);
591 g_return_val_if_fail(GTK_IS_TOOLBAR(toolbar), NULL);
593 child = g_new(Child, 1);
595 child->type = CHILD_BUTTON;
596 child->widget = gtk_button_new();
599 gtk_signal_connect(GTK_OBJECT(child->widget), "clicked",
600 callback, user_data);
603 gtk_tooltips_set_tips(toolbar->tooltips, child->widget, tooltip_text);
606 child->label = gtk_label_new(text);
611 child->icon = GTK_WIDGET(icon);
615 vbox = gtk_vbox_new(FALSE, 0);
616 gtk_container_add(GTK_CONTAINER(child->widget), vbox);
617 gtk_widget_show(vbox);
620 gtk_box_pack_start(GTK_BOX(vbox), child->icon, FALSE, FALSE, 0);
623 gtk_box_pack_start(GTK_BOX(vbox), child->label, FALSE, FALSE, 0);
625 switch (toolbar->style) {
626 case GTK_TOOLBAR_ICONS:
628 gtk_widget_show(child->icon);
631 case GTK_TOOLBAR_TEXT:
633 gtk_widget_show(child->label);
636 case GTK_TOOLBAR_BOTH:
638 gtk_widget_show(child->icon);
641 gtk_widget_show(child->label);
646 g_assert_not_reached();
649 gtk_widget_show(child->widget);
651 toolbar->children = g_list_insert(toolbar->children, child, position);
652 toolbar->num_children++;
654 gtk_widget_set_parent(child->widget, GTK_WIDGET(toolbar));
656 if (GTK_WIDGET_VISIBLE(toolbar)) {
657 if (GTK_WIDGET_REALIZED(toolbar)
658 && !GTK_WIDGET_REALIZED(child->widget))
659 gtk_widget_realize(child->widget);
661 if (GTK_WIDGET_MAPPED(toolbar)
662 && !GTK_WIDGET_MAPPED(child->widget))
663 gtk_widget_map(child->widget);
666 if (GTK_WIDGET_VISIBLE(child->widget) && GTK_WIDGET_VISIBLE(toolbar))
667 gtk_widget_queue_resize(child->widget);
669 return child->widget;
673 gtk_toolbar_append_space(GtkToolbar *toolbar)
675 gtk_toolbar_insert_space(toolbar, toolbar->num_children);
679 gtk_toolbar_prepend_space(GtkToolbar *toolbar)
681 gtk_toolbar_insert_space(toolbar, 0);
685 gtk_toolbar_insert_space(GtkToolbar *toolbar,
690 g_return_if_fail(toolbar != NULL);
691 g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
693 child = g_new(Child, 1);
694 child->type = CHILD_SPACE;
695 child->widget = NULL;
699 toolbar->children = g_list_insert(toolbar->children, child, position);
700 toolbar->num_children++;
702 if (GTK_WIDGET_VISIBLE(toolbar))
703 gtk_widget_queue_resize(GTK_WIDGET(toolbar));
707 gtk_toolbar_append_widget(GtkToolbar *toolbar,
708 const char *tooltip_text,
711 gtk_toolbar_insert_widget(toolbar, tooltip_text, widget, toolbar->num_children);
715 gtk_toolbar_prepend_widget(GtkToolbar *toolbar,
716 const char *tooltip_text,
719 gtk_toolbar_insert_widget(toolbar, tooltip_text, widget, 0);
723 gtk_toolbar_insert_widget(GtkToolbar *toolbar,
724 const char *tooltip_text,
730 g_return_if_fail(toolbar != NULL);
731 g_return_if_fail(widget != NULL);
733 child = g_new(Child, 1);
734 child->type = CHILD_WIDGET;
735 child->widget = widget;
740 gtk_tooltips_set_tips(toolbar->tooltips, child->widget, tooltip_text);
742 toolbar->children = g_list_insert(toolbar->children, child, position);
743 toolbar->num_children++;
745 gtk_widget_set_parent(child->widget, GTK_WIDGET(toolbar));
747 if (GTK_WIDGET_VISIBLE(toolbar)) {
748 if (GTK_WIDGET_REALIZED(toolbar)
749 && !GTK_WIDGET_REALIZED(child->widget))
750 gtk_widget_realize(child->widget);
752 if (GTK_WIDGET_MAPPED(toolbar)
753 && !GTK_WIDGET_MAPPED(child->widget))
754 gtk_widget_map(child->widget);
757 if (GTK_WIDGET_VISIBLE(child->widget) && GTK_WIDGET_VISIBLE(toolbar))
758 gtk_widget_queue_resize(child->widget);
762 gtk_toolbar_set_orientation(GtkToolbar *toolbar,
763 GtkOrientation orientation)
765 gtk_signal_emit(GTK_OBJECT(toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
769 gtk_toolbar_set_style(GtkToolbar *toolbar,
770 GtkToolbarStyle style)
772 gtk_signal_emit(GTK_OBJECT(toolbar), toolbar_signals[STYLE_CHANGED], style);
776 gtk_toolbar_set_space_size(GtkToolbar *toolbar,
779 g_return_if_fail(toolbar != NULL);
780 g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
782 if (toolbar->space_size != space_size) {
783 toolbar->space_size = space_size;
784 gtk_widget_queue_resize(GTK_WIDGET(toolbar));
789 gtk_toolbar_set_tooltips(GtkToolbar *toolbar,
792 g_return_if_fail(toolbar != NULL);
793 g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
796 gtk_tooltips_enable(toolbar->tooltips);
798 gtk_tooltips_disable(toolbar->tooltips);
802 gtk_toolbar_marshal_signal_1(GtkObject *object,
807 GtkToolbarSignal1 rfunc;
809 rfunc = (GtkToolbarSignal1) func;
811 (*rfunc) (object, GTK_VALUE_ENUM(args[0]), func_data);
815 gtk_real_toolbar_orientation_changed(GtkToolbar *toolbar,
816 GtkOrientation orientation)
818 g_return_if_fail(toolbar != NULL);
819 g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
821 if (toolbar->orientation != orientation) {
822 toolbar->orientation = orientation;
823 gtk_widget_queue_resize(GTK_WIDGET(toolbar));
828 gtk_real_toolbar_style_changed(GtkToolbar *toolbar,
829 GtkToolbarStyle style)
834 g_return_if_fail(toolbar != NULL);
835 g_return_if_fail(GTK_IS_TOOLBAR(toolbar));
837 if (toolbar->style != style) {
838 toolbar->style = style;
840 for (children = toolbar->children; children; children = children->next) {
841 child = children->data;
843 if (child->type == CHILD_BUTTON)
845 case GTK_TOOLBAR_ICONS:
846 if (child->icon && !GTK_WIDGET_VISIBLE(child->icon))
847 gtk_widget_show(child->icon);
849 if (child->label && GTK_WIDGET_VISIBLE(child->label))
850 gtk_widget_hide(child->label);
854 case GTK_TOOLBAR_TEXT:
855 if (child->icon && GTK_WIDGET_VISIBLE(child->icon))
856 gtk_widget_hide(child->icon);
858 if (child->label && !GTK_WIDGET_VISIBLE(child->label))
859 gtk_widget_show(child->label);
863 case GTK_TOOLBAR_BOTH:
864 if (child->icon && !GTK_WIDGET_VISIBLE(child->icon))
865 gtk_widget_show(child->icon);
867 if (child->label && !GTK_WIDGET_VISIBLE(child->label))
868 gtk_widget_show(child->label);
873 g_assert_not_reached();
877 gtk_widget_queue_resize(GTK_WIDGET(toolbar));