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
35 typedef void (*GtkToolbarSignal1) (GtkObject *object,
39 static void gtk_toolbar_marshal_signal_1 (GtkObject *object,
45 static void gtk_toolbar_class_init (GtkToolbarClass *class);
46 static void gtk_toolbar_init (GtkToolbar *toolbar);
47 static void gtk_toolbar_destroy (GtkObject *object);
48 static void gtk_toolbar_map (GtkWidget *widget);
49 static void gtk_toolbar_unmap (GtkWidget *widget);
50 static void gtk_toolbar_draw (GtkWidget *widget,
52 static gint gtk_toolbar_expose (GtkWidget *widget,
53 GdkEventExpose *event);
54 static void gtk_toolbar_size_request (GtkWidget *widget,
55 GtkRequisition *requisition);
56 static void gtk_toolbar_size_allocate (GtkWidget *widget,
57 GtkAllocation *allocation);
58 static void gtk_toolbar_add (GtkContainer *container,
60 static void gtk_toolbar_remove (GtkContainer *container,
62 static void gtk_toolbar_foreach (GtkContainer *container,
64 gpointer callback_data);
65 static void gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
66 GtkOrientation orientation);
67 static void gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
68 GtkToolbarStyle style);
71 static GtkContainerClass *parent_class;
73 static gint toolbar_signals[LAST_SIGNAL] = { 0 };
77 gtk_toolbar_get_type (void)
79 static guint toolbar_type = 0;
83 GtkTypeInfo toolbar_info =
87 sizeof (GtkToolbarClass),
88 (GtkClassInitFunc) gtk_toolbar_class_init,
89 (GtkObjectInitFunc) gtk_toolbar_init,
94 toolbar_type = gtk_type_unique (gtk_container_get_type (), &toolbar_info);
101 gtk_toolbar_class_init (GtkToolbarClass *class)
103 GtkObjectClass *object_class;
104 GtkWidgetClass *widget_class;
105 GtkContainerClass *container_class;
107 object_class = (GtkObjectClass *) class;
108 widget_class = (GtkWidgetClass *) class;
109 container_class = (GtkContainerClass *) class;
111 parent_class = gtk_type_class (gtk_container_get_type ());
113 toolbar_signals[ORIENTATION_CHANGED] =
114 gtk_signal_new ("orientation_changed",
117 GTK_SIGNAL_OFFSET (GtkToolbarClass, orientation_changed),
118 gtk_toolbar_marshal_signal_1,
121 toolbar_signals[STYLE_CHANGED] =
122 gtk_signal_new ("style_changed",
125 GTK_SIGNAL_OFFSET (GtkToolbarClass, style_changed),
126 gtk_toolbar_marshal_signal_1,
130 gtk_object_class_add_signals (object_class, toolbar_signals, LAST_SIGNAL);
132 object_class->destroy = gtk_toolbar_destroy;
134 widget_class->map = gtk_toolbar_map;
135 widget_class->unmap = gtk_toolbar_unmap;
136 widget_class->draw = gtk_toolbar_draw;
137 widget_class->expose_event = gtk_toolbar_expose;
138 widget_class->size_request = gtk_toolbar_size_request;
139 widget_class->size_allocate = gtk_toolbar_size_allocate;
141 container_class->add = gtk_toolbar_add;
142 container_class->remove = gtk_toolbar_remove;
143 container_class->foreach = gtk_toolbar_foreach;
144 container_class->focus = NULL;
146 class->orientation_changed = gtk_real_toolbar_orientation_changed;
147 class->style_changed = gtk_real_toolbar_style_changed;
151 gtk_toolbar_init (GtkToolbar *toolbar)
153 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
154 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
156 toolbar->num_children = 0;
157 toolbar->children = NULL;
158 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
159 toolbar->style = GTK_TOOLBAR_ICONS;
160 toolbar->space_size = DEFAULT_SPACE_SIZE;
161 toolbar->tooltips = gtk_tooltips_new ();
162 toolbar->button_maxw = 0;
163 toolbar->button_maxh = 0;
167 gtk_toolbar_new (GtkOrientation orientation,
168 GtkToolbarStyle style)
172 toolbar = gtk_type_new (gtk_toolbar_get_type ());
174 toolbar->orientation = orientation;
175 toolbar->style = style;
177 return GTK_WIDGET (toolbar);
181 gtk_toolbar_destroy (GtkObject *object)
185 GtkToolbarChild *child;
187 g_return_if_fail (object != NULL);
188 g_return_if_fail (GTK_IS_TOOLBAR (object));
190 toolbar = GTK_TOOLBAR (object);
192 gtk_object_unref (GTK_OBJECT (toolbar->tooltips));
194 for (children = toolbar->children; children; children = children->next)
196 child = children->data;
198 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
200 child->widget->parent = NULL;
201 gtk_object_unref (GTK_OBJECT (child->widget));
202 gtk_widget_destroy (child->widget);
208 g_list_free (toolbar->children);
210 if (GTK_OBJECT_CLASS (parent_class)->destroy)
211 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
215 gtk_toolbar_map (GtkWidget *widget)
219 GtkToolbarChild *child;
221 g_return_if_fail (widget != NULL);
222 g_return_if_fail (GTK_IS_TOOLBAR (widget));
224 toolbar = GTK_TOOLBAR (widget);
225 GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
227 for (children = toolbar->children; children; children = children->next)
229 child = children->data;
231 if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
232 && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
233 gtk_widget_map (child->widget);
238 gtk_toolbar_unmap (GtkWidget *widget)
242 GtkToolbarChild *child;
244 g_return_if_fail (widget != NULL);
245 g_return_if_fail (GTK_IS_TOOLBAR (widget));
247 toolbar = GTK_TOOLBAR (widget);
248 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
250 for (children = toolbar->children; children; children = children->next)
252 child = children->data;
254 if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
255 && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
256 gtk_widget_unmap (child->widget);
261 gtk_toolbar_draw (GtkWidget *widget,
266 GtkToolbarChild *child;
267 GdkRectangle child_area;
269 g_return_if_fail (widget != NULL);
270 g_return_if_fail (GTK_IS_TOOLBAR (widget));
272 if (GTK_WIDGET_DRAWABLE (widget))
274 toolbar = GTK_TOOLBAR (widget);
276 for (children = toolbar->children; children; children = children->next)
278 child = children->data;
280 if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
281 && gtk_widget_intersect (child->widget, area, &child_area))
282 gtk_widget_draw (child->widget, &child_area);
288 gtk_toolbar_expose (GtkWidget *widget,
289 GdkEventExpose *event)
293 GtkToolbarChild *child;
294 GdkEventExpose child_event;
296 g_return_val_if_fail (widget != NULL, FALSE);
297 g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
298 g_return_val_if_fail (event != NULL, FALSE);
300 if (GTK_WIDGET_DRAWABLE (widget))
302 toolbar = GTK_TOOLBAR (widget);
304 child_event = *event;
306 for (children = toolbar->children; children; children = children->next)
308 child = children->data;
310 if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
311 && GTK_WIDGET_NO_WINDOW (child->widget)
312 && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
313 gtk_widget_event (child->widget, (GdkEvent *) &child_event);
321 gtk_toolbar_size_request (GtkWidget *widget,
322 GtkRequisition *requisition)
326 GtkToolbarChild *child;
328 gint button_maxw, button_maxh;
329 gint widget_maxw, widget_maxh;
331 g_return_if_fail (widget != NULL);
332 g_return_if_fail (GTK_IS_TOOLBAR (widget));
333 g_return_if_fail (requisition != NULL);
335 toolbar = GTK_TOOLBAR (widget);
337 requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
338 requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
345 for (children = toolbar->children; children; children = children->next)
347 child = children->data;
351 case GTK_TOOLBAR_CHILD_SPACE:
352 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
353 requisition->width += toolbar->space_size;
355 requisition->height += toolbar->space_size;
359 case GTK_TOOLBAR_CHILD_BUTTON:
360 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);
371 case GTK_TOOLBAR_CHILD_WIDGET:
372 if (GTK_WIDGET_VISIBLE (child->widget))
374 gtk_widget_size_request (child->widget, &child->widget->requisition);
376 widget_maxw = MAX (widget_maxw, child->widget->requisition.width);
377 widget_maxh = MAX (widget_maxh, child->widget->requisition.height);
379 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
380 requisition->width += child->widget->requisition.width;
382 requisition->height += child->widget->requisition.height;
388 g_assert_not_reached ();
392 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
394 requisition->width += nbuttons * button_maxw;
395 requisition->height += MAX (button_maxh, widget_maxh);
399 requisition->width += MAX (button_maxw, widget_maxw);
400 requisition->height += nbuttons * button_maxh;
403 toolbar->button_maxw = button_maxw;
404 toolbar->button_maxh = button_maxh;
408 gtk_toolbar_size_allocate (GtkWidget *widget,
409 GtkAllocation *allocation)
413 GtkToolbarChild *child;
417 g_return_if_fail (widget != NULL);
418 g_return_if_fail (GTK_IS_TOOLBAR (widget));
419 g_return_if_fail (allocation != NULL);
421 toolbar = GTK_TOOLBAR (widget);
422 widget->allocation = *allocation;
424 border_width = GTK_CONTAINER (toolbar)->border_width;
426 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
427 alloc.x = allocation->x + border_width;
429 alloc.y = allocation->y + border_width;
431 for (children = toolbar->children; children; children = children->next)
433 child = children->data;
437 case GTK_TOOLBAR_CHILD_SPACE:
438 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
439 alloc.x += toolbar->space_size;
441 alloc.y += toolbar->space_size;
445 case GTK_TOOLBAR_CHILD_BUTTON:
446 alloc.width = toolbar->button_maxw;
447 alloc.height = toolbar->button_maxh;
449 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
450 alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
452 alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
454 gtk_widget_size_allocate (child->widget, &alloc);
456 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
457 alloc.x += toolbar->button_maxw;
459 alloc.y += toolbar->button_maxh;
463 case GTK_TOOLBAR_CHILD_WIDGET:
464 alloc.width = child->widget->requisition.width;
465 alloc.height = child->widget->requisition.height;
467 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
468 alloc.y = allocation->y + (allocation->height - child->widget->requisition.height) / 2;
470 alloc.x = allocation->x + (allocation->width - 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), widget, NULL);
499 gtk_toolbar_remove (GtkContainer *container,
504 GtkToolbarChild *child;
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)
514 child = children->data;
516 if ((child->type != GTK_TOOLBAR_CHILD_SPACE) && (child->widget == widget))
518 gtk_widget_unparent (widget);
520 toolbar->children = g_list_remove_link (toolbar->children, children);
522 g_list_free (children);
523 toolbar->num_children--;
525 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
526 gtk_widget_queue_resize (GTK_WIDGET (container));
534 gtk_toolbar_foreach (GtkContainer *container,
535 GtkCallback callback,
536 gpointer callback_data)
540 GtkToolbarChild *child;
542 g_return_if_fail (container != NULL);
543 g_return_if_fail (GTK_IS_TOOLBAR (container));
544 g_return_if_fail (callback != NULL);
546 toolbar = GTK_TOOLBAR (container);
548 for (children = toolbar->children; children; children = children->next)
550 child = children->data;
552 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
553 (*callback) (child->widget, callback_data);
558 gtk_toolbar_append_item (GtkToolbar *toolbar,
560 const char *tooltip_text,
562 GtkSignalFunc callback,
565 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
566 callback, user_data, toolbar->num_children);
570 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
572 const char *tooltip_text,
574 GtkSignalFunc callback,
577 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
578 callback, user_data, 0);
582 gtk_toolbar_insert_item (GtkToolbar *toolbar,
584 const char *tooltip_text,
586 GtkSignalFunc callback,
590 GtkToolbarChild *child;
593 g_return_val_if_fail (toolbar != NULL, NULL);
594 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
596 child = g_new (GtkToolbarChild, 1);
598 child->type = GTK_TOOLBAR_CHILD_BUTTON;
599 child->widget = gtk_button_new ();
602 gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
603 callback, user_data);
606 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
609 child->label = gtk_label_new (text);
614 child->icon = GTK_WIDGET (icon);
618 vbox = gtk_vbox_new (FALSE, 0);
619 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
620 gtk_widget_show (vbox);
623 gtk_box_pack_start (GTK_BOX (vbox), child->icon, FALSE, FALSE, 0);
626 gtk_box_pack_start (GTK_BOX (vbox), child->label, FALSE, FALSE, 0);
628 switch (toolbar->style)
630 case GTK_TOOLBAR_ICONS:
632 gtk_widget_show (child->icon);
635 case GTK_TOOLBAR_TEXT:
637 gtk_widget_show (child->label);
640 case GTK_TOOLBAR_BOTH:
642 gtk_widget_show (child->icon);
645 gtk_widget_show (child->label);
650 g_assert_not_reached ();
653 gtk_widget_show (child->widget);
655 toolbar->children = g_list_insert (toolbar->children, child, position);
656 toolbar->num_children++;
658 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
660 if (GTK_WIDGET_VISIBLE (toolbar))
662 if (GTK_WIDGET_REALIZED (toolbar)
663 && !GTK_WIDGET_REALIZED (child->widget))
664 gtk_widget_realize (child->widget);
666 if (GTK_WIDGET_MAPPED (toolbar)
667 && !GTK_WIDGET_MAPPED (child->widget))
668 gtk_widget_map (child->widget);
671 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
672 gtk_widget_queue_resize (child->widget);
674 return child->widget;
678 gtk_toolbar_append_space (GtkToolbar *toolbar)
680 gtk_toolbar_insert_space (toolbar, toolbar->num_children);
684 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
686 gtk_toolbar_insert_space (toolbar, 0);
690 gtk_toolbar_insert_space (GtkToolbar *toolbar,
693 GtkToolbarChild *child;
695 g_return_if_fail (toolbar != NULL);
696 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
698 child = g_new (GtkToolbarChild, 1);
699 child->type = GTK_TOOLBAR_CHILD_SPACE;
700 child->widget = NULL;
704 toolbar->children = g_list_insert (toolbar->children, child, position);
705 toolbar->num_children++;
707 if (GTK_WIDGET_VISIBLE (toolbar))
708 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
712 gtk_toolbar_append_widget (GtkToolbar *toolbar,
714 const char *tooltip_text)
716 gtk_toolbar_insert_widget (toolbar, widget, tooltip_text, toolbar->num_children);
720 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
722 const char *tooltip_text)
724 gtk_toolbar_insert_widget (toolbar, widget, tooltip_text, 0);
728 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
730 const char *tooltip_text,
733 GtkToolbarChild *child;
735 g_return_if_fail (toolbar != NULL);
736 g_return_if_fail (widget != NULL);
738 child = g_new (GtkToolbarChild, 1);
739 child->type = GTK_TOOLBAR_CHILD_WIDGET;
740 child->widget = widget;
745 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
747 toolbar->children = g_list_insert (toolbar->children, child, position);
748 toolbar->num_children++;
750 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
752 if (GTK_WIDGET_VISIBLE (toolbar))
754 if (GTK_WIDGET_REALIZED (toolbar)
755 && !GTK_WIDGET_REALIZED (child->widget))
756 gtk_widget_realize (child->widget);
758 if (GTK_WIDGET_MAPPED (toolbar)
759 && !GTK_WIDGET_MAPPED (child->widget))
760 gtk_widget_map (child->widget);
763 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
764 gtk_widget_queue_resize (child->widget);
768 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
769 GtkOrientation orientation)
771 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
775 gtk_toolbar_set_style (GtkToolbar *toolbar,
776 GtkToolbarStyle style)
778 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
782 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
785 g_return_if_fail (toolbar != NULL);
786 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
788 if (toolbar->space_size != space_size)
790 toolbar->space_size = space_size;
791 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
796 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
799 g_return_if_fail (toolbar != NULL);
800 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
803 gtk_tooltips_enable (toolbar->tooltips);
805 gtk_tooltips_disable (toolbar->tooltips);
809 gtk_toolbar_marshal_signal_1 (GtkObject *object,
814 GtkToolbarSignal1 rfunc;
816 rfunc = (GtkToolbarSignal1) func;
818 (*rfunc) (object, GTK_VALUE_ENUM (args[0]), func_data);
822 gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
823 GtkOrientation orientation)
825 g_return_if_fail (toolbar != NULL);
826 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
828 if (toolbar->orientation != orientation)
830 toolbar->orientation = orientation;
831 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
836 gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
837 GtkToolbarStyle style)
840 GtkToolbarChild *child;
842 g_return_if_fail (toolbar != NULL);
843 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
845 if (toolbar->style != style)
847 toolbar->style = style;
849 for (children = toolbar->children; children; children = children->next)
851 child = children->data;
853 if (child->type == GTK_TOOLBAR_CHILD_BUTTON)
856 case GTK_TOOLBAR_ICONS:
857 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
858 gtk_widget_show (child->icon);
860 if (child->label && GTK_WIDGET_VISIBLE (child->label))
861 gtk_widget_hide (child->label);
865 case GTK_TOOLBAR_TEXT:
866 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
867 gtk_widget_hide (child->icon);
869 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
870 gtk_widget_show (child->label);
874 case GTK_TOOLBAR_BOTH:
875 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
876 gtk_widget_show (child->icon);
878 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
879 gtk_widget_show (child->label);
884 g_assert_not_reached ();
888 gtk_widget_queue_resize (GTK_WIDGET (toolbar));