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
52 typedef void (*GtkToolbarSignal1) (GtkObject *object,
56 static void gtk_toolbar_marshal_signal_1 (GtkObject *object,
62 static void gtk_toolbar_class_init (GtkToolbarClass *class);
63 static void gtk_toolbar_init (GtkToolbar *toolbar);
64 static void gtk_toolbar_destroy (GtkObject *object);
65 static void gtk_toolbar_map (GtkWidget *widget);
66 static void gtk_toolbar_unmap (GtkWidget *widget);
67 static void gtk_toolbar_draw (GtkWidget *widget,
69 static gint gtk_toolbar_expose (GtkWidget *widget,
70 GdkEventExpose *event);
71 static void gtk_toolbar_size_request (GtkWidget *widget,
72 GtkRequisition *requisition);
73 static void gtk_toolbar_size_allocate (GtkWidget *widget,
74 GtkAllocation *allocation);
75 static void gtk_toolbar_add (GtkContainer *container,
77 static void gtk_toolbar_remove (GtkContainer *container,
79 static void gtk_toolbar_foreach (GtkContainer *container,
81 gpointer callback_data);
82 static void gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
83 GtkOrientation orientation);
84 static void gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
85 GtkToolbarStyle style);
88 static GtkContainerClass *parent_class;
90 static gint toolbar_signals[LAST_SIGNAL] = { 0 };
94 gtk_toolbar_get_type (void)
96 static guint toolbar_type = 0;
100 GtkTypeInfo toolbar_info =
104 sizeof (GtkToolbarClass),
105 (GtkClassInitFunc) gtk_toolbar_class_init,
106 (GtkObjectInitFunc) gtk_toolbar_init,
110 toolbar_type = gtk_type_unique (gtk_container_get_type (), &toolbar_info);
117 gtk_toolbar_class_init (GtkToolbarClass *class)
119 GtkObjectClass *object_class;
120 GtkWidgetClass *widget_class;
121 GtkContainerClass *container_class;
123 object_class = (GtkObjectClass *) class;
124 widget_class = (GtkWidgetClass *) class;
125 container_class = (GtkContainerClass *) class;
127 parent_class = gtk_type_class (gtk_container_get_type ());
129 toolbar_signals[ORIENTATION_CHANGED] =
130 gtk_signal_new ("orientation_changed",
133 GTK_SIGNAL_OFFSET (GtkToolbarClass, orientation_changed),
134 gtk_toolbar_marshal_signal_1,
137 toolbar_signals[STYLE_CHANGED] =
138 gtk_signal_new ("style_changed",
141 GTK_SIGNAL_OFFSET (GtkToolbarClass, style_changed),
142 gtk_toolbar_marshal_signal_1,
146 gtk_object_class_add_signals (object_class, toolbar_signals, LAST_SIGNAL);
148 object_class->destroy = gtk_toolbar_destroy;
150 widget_class->map = gtk_toolbar_map;
151 widget_class->unmap = gtk_toolbar_unmap;
152 widget_class->draw = gtk_toolbar_draw;
153 widget_class->expose_event = gtk_toolbar_expose;
154 widget_class->size_request = gtk_toolbar_size_request;
155 widget_class->size_allocate = gtk_toolbar_size_allocate;
157 container_class->add = gtk_toolbar_add;
158 container_class->remove = gtk_toolbar_remove;
159 container_class->foreach = gtk_toolbar_foreach;
161 class->orientation_changed = gtk_real_toolbar_orientation_changed;
162 class->style_changed = gtk_real_toolbar_style_changed;
166 gtk_toolbar_init (GtkToolbar *toolbar)
168 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
170 toolbar->num_children = 0;
171 toolbar->children = NULL;
172 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
173 toolbar->style = GTK_TOOLBAR_ICONS;
174 toolbar->space_size = DEFAULT_SPACE_SIZE;
175 toolbar->tooltips = gtk_tooltips_new ();
176 toolbar->button_maxw = 0;
177 toolbar->button_maxh = 0;
181 gtk_toolbar_new (GtkOrientation orientation,
182 GtkToolbarStyle style)
186 toolbar = gtk_type_new (gtk_toolbar_get_type ());
188 toolbar->orientation = orientation;
189 toolbar->style = style;
191 return GTK_WIDGET (toolbar);
195 gtk_toolbar_destroy (GtkObject *object)
201 g_return_if_fail (object != NULL);
202 g_return_if_fail (GTK_IS_TOOLBAR (object));
204 toolbar = GTK_TOOLBAR (object);
206 gtk_tooltips_unref (toolbar->tooltips);
208 for (children = toolbar->children; children; children = children->next)
210 child = children->data;
212 if (child->type != CHILD_SPACE)
214 child->widget->parent = NULL;
215 gtk_object_unref (GTK_OBJECT (child->widget));
216 gtk_widget_destroy (child->widget);
222 g_list_free (toolbar->children);
224 if (GTK_OBJECT_CLASS (parent_class)->destroy)
225 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
229 gtk_toolbar_map (GtkWidget *widget)
235 g_return_if_fail (widget != NULL);
236 g_return_if_fail (GTK_IS_TOOLBAR (widget));
238 toolbar = GTK_TOOLBAR (widget);
239 GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
241 for (children = toolbar->children; children; children = children->next)
243 child = children->data;
245 if ((child->type != CHILD_SPACE)
246 && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
247 gtk_widget_map (child->widget);
252 gtk_toolbar_unmap (GtkWidget *widget)
258 g_return_if_fail (widget != NULL);
259 g_return_if_fail (GTK_IS_TOOLBAR (widget));
261 toolbar = GTK_TOOLBAR (widget);
262 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
264 for (children = toolbar->children; children; children = children->next)
266 child = children->data;
268 if ((child->type != CHILD_SPACE)
269 && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
270 gtk_widget_unmap (child->widget);
275 gtk_toolbar_draw (GtkWidget *widget,
281 GdkRectangle child_area;
283 g_return_if_fail (widget != NULL);
284 g_return_if_fail (GTK_IS_TOOLBAR (widget));
286 if (GTK_WIDGET_DRAWABLE (widget))
288 toolbar = GTK_TOOLBAR (widget);
290 for (children = toolbar->children; children; children = children->next)
292 child = children->data;
294 if ((child->type != CHILD_SPACE)
295 && gtk_widget_intersect (child->widget, area, &child_area))
296 gtk_widget_draw (child->widget, &child_area);
302 gtk_toolbar_expose (GtkWidget *widget,
303 GdkEventExpose *event)
308 GdkEventExpose child_event;
310 g_return_val_if_fail (widget != NULL, FALSE);
311 g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
312 g_return_val_if_fail (event != NULL, FALSE);
314 if (GTK_WIDGET_DRAWABLE (widget))
316 toolbar = GTK_TOOLBAR (widget);
318 child_event = *event;
320 for (children = toolbar->children; children; children = children->next)
322 child = children->data;
324 if ((child->type != CHILD_SPACE)
325 && GTK_WIDGET_NO_WINDOW (child->widget)
326 && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
327 gtk_widget_event (child->widget, (GdkEvent *) &child_event);
335 gtk_toolbar_size_request (GtkWidget *widget,
336 GtkRequisition *requisition)
342 gint button_maxw, button_maxh;
343 gint widget_maxw, widget_maxh;
345 g_return_if_fail (widget != NULL);
346 g_return_if_fail (GTK_IS_TOOLBAR (widget));
347 g_return_if_fail (requisition != NULL);
349 toolbar = GTK_TOOLBAR (widget);
351 requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
352 requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
359 for (children = toolbar->children; children; children = children->next)
361 child = children->data;
366 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
367 requisition->width += toolbar->space_size;
369 requisition->height += toolbar->space_size;
374 if (GTK_WIDGET_VISIBLE (child->widget))
376 gtk_widget_size_request (child->widget, &child->widget->requisition);
379 button_maxw = MAX (button_maxw, child->widget->requisition.width);
380 button_maxh = MAX (button_maxh, child->widget->requisition.height);
386 if (GTK_WIDGET_VISIBLE (child->widget))
388 gtk_widget_size_request (child->widget, &child->widget->requisition);
390 widget_maxw = MAX (widget_maxw, child->widget->requisition.width);
391 widget_maxh = MAX (widget_maxh, child->widget->requisition.height);
393 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
394 requisition->width += child->widget->requisition.width;
396 requisition->height += child->widget->requisition.height;
402 g_assert_not_reached ();
406 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
408 requisition->width += nbuttons * button_maxw;
409 requisition->height += MAX (button_maxh, widget_maxh);
413 requisition->width += MAX (button_maxw, widget_maxw);
414 requisition->height += nbuttons * button_maxh;
417 toolbar->button_maxw = button_maxw;
418 toolbar->button_maxh = button_maxh;
422 gtk_toolbar_size_allocate (GtkWidget *widget,
423 GtkAllocation *allocation)
431 g_return_if_fail (widget != NULL);
432 g_return_if_fail (GTK_IS_TOOLBAR (widget));
433 g_return_if_fail (allocation != NULL);
435 toolbar = GTK_TOOLBAR (widget);
436 widget->allocation = *allocation;
438 border_width = GTK_CONTAINER (toolbar)->border_width;
440 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
441 alloc.x = allocation->x + border_width;
443 alloc.y = allocation->y + border_width;
445 for (children = toolbar->children; children; children = children->next)
447 child = children->data;
452 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
453 alloc.x += toolbar->space_size;
455 alloc.y += toolbar->space_size;
460 alloc.width = toolbar->button_maxw;
461 alloc.height = toolbar->button_maxh;
463 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
464 alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
466 alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
468 gtk_widget_size_allocate (child->widget, &alloc);
470 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
471 alloc.x += toolbar->button_maxw;
473 alloc.y += toolbar->button_maxh;
478 alloc.width = child->widget->requisition.width;
479 alloc.height = child->widget->requisition.height;
481 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
482 alloc.y = allocation->y + (allocation->height - child->widget->requisition.height) / 2;
484 alloc.x = allocation->x + (allocation->width - child->widget->requisition.width) / 2;
486 gtk_widget_size_allocate (child->widget, &alloc);
488 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
489 alloc.x += child->widget->requisition.width;
491 alloc.y += child->widget->requisition.height;
496 g_assert_not_reached ();
502 gtk_toolbar_add (GtkContainer *container,
505 g_return_if_fail (container != NULL);
506 g_return_if_fail (GTK_IS_TOOLBAR (container));
507 g_return_if_fail (widget != NULL);
509 gtk_toolbar_append_widget (GTK_TOOLBAR (container), NULL, widget);
513 gtk_toolbar_remove (GtkContainer *container,
520 g_return_if_fail (container != NULL);
521 g_return_if_fail (GTK_IS_TOOLBAR (container));
522 g_return_if_fail (widget != NULL);
524 toolbar = GTK_TOOLBAR (container);
526 for (children = toolbar->children; children; children = children->next)
528 child = children->data;
530 if ((child->type != CHILD_SPACE) && (child->widget == widget))
532 gtk_widget_unparent (widget);
534 toolbar->children = g_list_remove_link (toolbar->children, children);
536 g_list_free (children);
537 toolbar->num_children--;
539 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
540 gtk_widget_queue_resize (GTK_WIDGET (container));
548 gtk_toolbar_foreach (GtkContainer *container,
549 GtkCallback callback,
550 gpointer callback_data)
556 g_return_if_fail (container != NULL);
557 g_return_if_fail (GTK_IS_TOOLBAR (container));
558 g_return_if_fail (callback != NULL);
560 toolbar = GTK_TOOLBAR (container);
562 for (children = toolbar->children; children; children = children->next)
564 child = children->data;
566 if (child->type != CHILD_SPACE)
567 (*callback) (child->widget, callback_data);
572 gtk_toolbar_append_item (GtkToolbar *toolbar,
574 const char *tooltip_text,
576 GtkSignalFunc callback,
579 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
580 callback, user_data, toolbar->num_children);
584 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
586 const char *tooltip_text,
588 GtkSignalFunc callback,
591 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
592 callback, user_data, 0);
596 gtk_toolbar_insert_item (GtkToolbar *toolbar,
598 const char *tooltip_text,
600 GtkSignalFunc callback,
607 g_return_val_if_fail (toolbar != NULL, NULL);
608 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
610 child = g_new (Child, 1);
612 child->type = CHILD_BUTTON;
613 child->widget = gtk_button_new ();
616 gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
617 callback, user_data);
620 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
623 child->label = gtk_label_new (text);
628 child->icon = GTK_WIDGET (icon);
632 vbox = gtk_vbox_new (FALSE, 0);
633 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
634 gtk_widget_show (vbox);
637 gtk_box_pack_start (GTK_BOX (vbox), child->icon, FALSE, FALSE, 0);
640 gtk_box_pack_start (GTK_BOX (vbox), child->label, FALSE, FALSE, 0);
642 switch (toolbar->style)
644 case GTK_TOOLBAR_ICONS:
646 gtk_widget_show (child->icon);
649 case GTK_TOOLBAR_TEXT:
651 gtk_widget_show (child->label);
654 case GTK_TOOLBAR_BOTH:
656 gtk_widget_show (child->icon);
659 gtk_widget_show (child->label);
664 g_assert_not_reached ();
667 gtk_widget_show (child->widget);
669 toolbar->children = g_list_insert (toolbar->children, child, position);
670 toolbar->num_children++;
672 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
674 if (GTK_WIDGET_VISIBLE (toolbar))
676 if (GTK_WIDGET_REALIZED (toolbar)
677 && !GTK_WIDGET_REALIZED (child->widget))
678 gtk_widget_realize (child->widget);
680 if (GTK_WIDGET_MAPPED (toolbar)
681 && !GTK_WIDGET_MAPPED (child->widget))
682 gtk_widget_map (child->widget);
685 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
686 gtk_widget_queue_resize (child->widget);
688 return child->widget;
692 gtk_toolbar_append_space (GtkToolbar *toolbar)
694 gtk_toolbar_insert_space (toolbar, toolbar->num_children);
698 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
700 gtk_toolbar_insert_space (toolbar, 0);
704 gtk_toolbar_insert_space (GtkToolbar *toolbar,
709 g_return_if_fail (toolbar != NULL);
710 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
712 child = g_new (Child, 1);
713 child->type = CHILD_SPACE;
714 child->widget = NULL;
718 toolbar->children = g_list_insert (toolbar->children, child, position);
719 toolbar->num_children++;
721 if (GTK_WIDGET_VISIBLE (toolbar))
722 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
726 gtk_toolbar_append_widget (GtkToolbar *toolbar,
727 const char *tooltip_text,
730 gtk_toolbar_insert_widget (toolbar, tooltip_text, widget, toolbar->num_children);
734 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
735 const char *tooltip_text,
738 gtk_toolbar_insert_widget (toolbar, tooltip_text, widget, 0);
742 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
743 const char *tooltip_text,
749 g_return_if_fail (toolbar != NULL);
750 g_return_if_fail (widget != NULL);
752 child = g_new (Child, 1);
753 child->type = CHILD_WIDGET;
754 child->widget = widget;
759 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
761 toolbar->children = g_list_insert (toolbar->children, child, position);
762 toolbar->num_children++;
764 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
766 if (GTK_WIDGET_VISIBLE (toolbar))
768 if (GTK_WIDGET_REALIZED (toolbar)
769 && !GTK_WIDGET_REALIZED (child->widget))
770 gtk_widget_realize (child->widget);
772 if (GTK_WIDGET_MAPPED (toolbar)
773 && !GTK_WIDGET_MAPPED (child->widget))
774 gtk_widget_map (child->widget);
777 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
778 gtk_widget_queue_resize (child->widget);
782 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
783 GtkOrientation orientation)
785 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
789 gtk_toolbar_set_style (GtkToolbar *toolbar,
790 GtkToolbarStyle style)
792 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
796 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
799 g_return_if_fail (toolbar != NULL);
800 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
802 if (toolbar->space_size != space_size)
804 toolbar->space_size = space_size;
805 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
810 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
813 g_return_if_fail (toolbar != NULL);
814 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
817 gtk_tooltips_enable (toolbar->tooltips);
819 gtk_tooltips_disable (toolbar->tooltips);
823 gtk_toolbar_marshal_signal_1 (GtkObject *object,
828 GtkToolbarSignal1 rfunc;
830 rfunc = (GtkToolbarSignal1) func;
832 (*rfunc) (object, GTK_VALUE_ENUM (args[0]), func_data);
836 gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
837 GtkOrientation orientation)
839 g_return_if_fail (toolbar != NULL);
840 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
842 if (toolbar->orientation != orientation)
844 toolbar->orientation = orientation;
845 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
850 gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
851 GtkToolbarStyle style)
856 g_return_if_fail (toolbar != NULL);
857 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
859 if (toolbar->style != style)
861 toolbar->style = style;
863 for (children = toolbar->children; children; children = children->next)
865 child = children->data;
867 if (child->type == CHILD_BUTTON)
870 case GTK_TOOLBAR_ICONS:
871 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
872 gtk_widget_show (child->icon);
874 if (child->label && GTK_WIDGET_VISIBLE (child->label))
875 gtk_widget_hide (child->label);
879 case GTK_TOOLBAR_TEXT:
880 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
881 gtk_widget_hide (child->icon);
883 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
884 gtk_widget_show (child->label);
888 case GTK_TOOLBAR_BOTH:
889 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
890 gtk_widget_show (child->icon);
892 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
893 gtk_widget_show (child->label);
898 g_assert_not_reached ();
902 gtk_widget_queue_resize (GTK_WIDGET (toolbar));