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,
107 (GtkArgSetFunc) NULL,
108 (GtkArgGetFunc) NULL,
111 toolbar_type = gtk_type_unique (gtk_container_get_type (), &toolbar_info);
118 gtk_toolbar_class_init (GtkToolbarClass *class)
120 GtkObjectClass *object_class;
121 GtkWidgetClass *widget_class;
122 GtkContainerClass *container_class;
124 object_class = (GtkObjectClass *) class;
125 widget_class = (GtkWidgetClass *) class;
126 container_class = (GtkContainerClass *) class;
128 parent_class = gtk_type_class (gtk_container_get_type ());
130 toolbar_signals[ORIENTATION_CHANGED] =
131 gtk_signal_new ("orientation_changed",
134 GTK_SIGNAL_OFFSET (GtkToolbarClass, orientation_changed),
135 gtk_toolbar_marshal_signal_1,
138 toolbar_signals[STYLE_CHANGED] =
139 gtk_signal_new ("style_changed",
142 GTK_SIGNAL_OFFSET (GtkToolbarClass, style_changed),
143 gtk_toolbar_marshal_signal_1,
147 gtk_object_class_add_signals (object_class, toolbar_signals, LAST_SIGNAL);
149 object_class->destroy = gtk_toolbar_destroy;
151 widget_class->map = gtk_toolbar_map;
152 widget_class->unmap = gtk_toolbar_unmap;
153 widget_class->draw = gtk_toolbar_draw;
154 widget_class->expose_event = gtk_toolbar_expose;
155 widget_class->size_request = gtk_toolbar_size_request;
156 widget_class->size_allocate = gtk_toolbar_size_allocate;
158 container_class->add = gtk_toolbar_add;
159 container_class->remove = gtk_toolbar_remove;
160 container_class->foreach = gtk_toolbar_foreach;
162 class->orientation_changed = gtk_real_toolbar_orientation_changed;
163 class->style_changed = gtk_real_toolbar_style_changed;
167 gtk_toolbar_init (GtkToolbar *toolbar)
169 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
170 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
172 toolbar->num_children = 0;
173 toolbar->children = NULL;
174 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
175 toolbar->style = GTK_TOOLBAR_ICONS;
176 toolbar->space_size = DEFAULT_SPACE_SIZE;
177 toolbar->tooltips = gtk_tooltips_new ();
178 toolbar->button_maxw = 0;
179 toolbar->button_maxh = 0;
183 gtk_toolbar_new (GtkOrientation orientation,
184 GtkToolbarStyle style)
188 toolbar = gtk_type_new (gtk_toolbar_get_type ());
190 toolbar->orientation = orientation;
191 toolbar->style = style;
193 return GTK_WIDGET (toolbar);
197 gtk_toolbar_destroy (GtkObject *object)
203 g_return_if_fail (object != NULL);
204 g_return_if_fail (GTK_IS_TOOLBAR (object));
206 toolbar = GTK_TOOLBAR (object);
208 gtk_tooltips_unref (toolbar->tooltips);
210 for (children = toolbar->children; children; children = children->next)
212 child = children->data;
214 if (child->type != CHILD_SPACE)
216 child->widget->parent = NULL;
217 gtk_object_unref (GTK_OBJECT (child->widget));
218 gtk_widget_destroy (child->widget);
224 g_list_free (toolbar->children);
226 if (GTK_OBJECT_CLASS (parent_class)->destroy)
227 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
231 gtk_toolbar_map (GtkWidget *widget)
237 g_return_if_fail (widget != NULL);
238 g_return_if_fail (GTK_IS_TOOLBAR (widget));
240 toolbar = GTK_TOOLBAR (widget);
241 GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
243 for (children = toolbar->children; children; children = children->next)
245 child = children->data;
247 if ((child->type != CHILD_SPACE)
248 && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
249 gtk_widget_map (child->widget);
254 gtk_toolbar_unmap (GtkWidget *widget)
260 g_return_if_fail (widget != NULL);
261 g_return_if_fail (GTK_IS_TOOLBAR (widget));
263 toolbar = GTK_TOOLBAR (widget);
264 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
266 for (children = toolbar->children; children; children = children->next)
268 child = children->data;
270 if ((child->type != CHILD_SPACE)
271 && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
272 gtk_widget_unmap (child->widget);
277 gtk_toolbar_draw (GtkWidget *widget,
283 GdkRectangle child_area;
285 g_return_if_fail (widget != NULL);
286 g_return_if_fail (GTK_IS_TOOLBAR (widget));
288 if (GTK_WIDGET_DRAWABLE (widget))
290 toolbar = GTK_TOOLBAR (widget);
292 for (children = toolbar->children; children; children = children->next)
294 child = children->data;
296 if ((child->type != CHILD_SPACE)
297 && gtk_widget_intersect (child->widget, area, &child_area))
298 gtk_widget_draw (child->widget, &child_area);
304 gtk_toolbar_expose (GtkWidget *widget,
305 GdkEventExpose *event)
310 GdkEventExpose child_event;
312 g_return_val_if_fail (widget != NULL, FALSE);
313 g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
314 g_return_val_if_fail (event != NULL, FALSE);
316 if (GTK_WIDGET_DRAWABLE (widget))
318 toolbar = GTK_TOOLBAR (widget);
320 child_event = *event;
322 for (children = toolbar->children; children; children = children->next)
324 child = children->data;
326 if ((child->type != CHILD_SPACE)
327 && GTK_WIDGET_NO_WINDOW (child->widget)
328 && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
329 gtk_widget_event (child->widget, (GdkEvent *) &child_event);
337 gtk_toolbar_size_request (GtkWidget *widget,
338 GtkRequisition *requisition)
344 gint button_maxw, button_maxh;
345 gint widget_maxw, widget_maxh;
347 g_return_if_fail (widget != NULL);
348 g_return_if_fail (GTK_IS_TOOLBAR (widget));
349 g_return_if_fail (requisition != NULL);
351 toolbar = GTK_TOOLBAR (widget);
353 requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
354 requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
361 for (children = toolbar->children; children; children = children->next)
363 child = children->data;
368 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
369 requisition->width += toolbar->space_size;
371 requisition->height += toolbar->space_size;
376 if (GTK_WIDGET_VISIBLE (child->widget))
378 gtk_widget_size_request (child->widget, &child->widget->requisition);
381 button_maxw = MAX (button_maxw, child->widget->requisition.width);
382 button_maxh = MAX (button_maxh, child->widget->requisition.height);
388 if (GTK_WIDGET_VISIBLE (child->widget))
390 gtk_widget_size_request (child->widget, &child->widget->requisition);
392 widget_maxw = MAX (widget_maxw, child->widget->requisition.width);
393 widget_maxh = MAX (widget_maxh, child->widget->requisition.height);
395 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
396 requisition->width += child->widget->requisition.width;
398 requisition->height += child->widget->requisition.height;
404 g_assert_not_reached ();
408 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
410 requisition->width += nbuttons * button_maxw;
411 requisition->height += MAX (button_maxh, widget_maxh);
415 requisition->width += MAX (button_maxw, widget_maxw);
416 requisition->height += nbuttons * button_maxh;
419 toolbar->button_maxw = button_maxw;
420 toolbar->button_maxh = button_maxh;
424 gtk_toolbar_size_allocate (GtkWidget *widget,
425 GtkAllocation *allocation)
433 g_return_if_fail (widget != NULL);
434 g_return_if_fail (GTK_IS_TOOLBAR (widget));
435 g_return_if_fail (allocation != NULL);
437 toolbar = GTK_TOOLBAR (widget);
438 widget->allocation = *allocation;
440 border_width = GTK_CONTAINER (toolbar)->border_width;
442 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
443 alloc.x = allocation->x + border_width;
445 alloc.y = allocation->y + border_width;
447 for (children = toolbar->children; children; children = children->next)
449 child = children->data;
454 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
455 alloc.x += toolbar->space_size;
457 alloc.y += toolbar->space_size;
462 alloc.width = toolbar->button_maxw;
463 alloc.height = toolbar->button_maxh;
465 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
466 alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
468 alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
470 gtk_widget_size_allocate (child->widget, &alloc);
472 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
473 alloc.x += toolbar->button_maxw;
475 alloc.y += toolbar->button_maxh;
480 alloc.width = child->widget->requisition.width;
481 alloc.height = child->widget->requisition.height;
483 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
484 alloc.y = allocation->y + (allocation->height - child->widget->requisition.height) / 2;
486 alloc.x = allocation->x + (allocation->width - child->widget->requisition.width) / 2;
488 gtk_widget_size_allocate (child->widget, &alloc);
490 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
491 alloc.x += child->widget->requisition.width;
493 alloc.y += child->widget->requisition.height;
498 g_assert_not_reached ();
504 gtk_toolbar_add (GtkContainer *container,
507 g_return_if_fail (container != NULL);
508 g_return_if_fail (GTK_IS_TOOLBAR (container));
509 g_return_if_fail (widget != NULL);
511 gtk_toolbar_append_widget (GTK_TOOLBAR (container), widget, NULL);
515 gtk_toolbar_remove (GtkContainer *container,
522 g_return_if_fail (container != NULL);
523 g_return_if_fail (GTK_IS_TOOLBAR (container));
524 g_return_if_fail (widget != NULL);
526 toolbar = GTK_TOOLBAR (container);
528 for (children = toolbar->children; children; children = children->next)
530 child = children->data;
532 if ((child->type != CHILD_SPACE) && (child->widget == widget))
534 gtk_widget_unparent (widget);
536 toolbar->children = g_list_remove_link (toolbar->children, children);
538 g_list_free (children);
539 toolbar->num_children--;
541 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
542 gtk_widget_queue_resize (GTK_WIDGET (container));
550 gtk_toolbar_foreach (GtkContainer *container,
551 GtkCallback callback,
552 gpointer callback_data)
558 g_return_if_fail (container != NULL);
559 g_return_if_fail (GTK_IS_TOOLBAR (container));
560 g_return_if_fail (callback != NULL);
562 toolbar = GTK_TOOLBAR (container);
564 for (children = toolbar->children; children; children = children->next)
566 child = children->data;
568 if (child->type != CHILD_SPACE)
569 (*callback) (child->widget, callback_data);
574 gtk_toolbar_append_item (GtkToolbar *toolbar,
576 const char *tooltip_text,
578 GtkSignalFunc callback,
581 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
582 callback, user_data, toolbar->num_children);
586 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
588 const char *tooltip_text,
590 GtkSignalFunc callback,
593 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
594 callback, user_data, 0);
598 gtk_toolbar_insert_item (GtkToolbar *toolbar,
600 const char *tooltip_text,
602 GtkSignalFunc callback,
609 g_return_val_if_fail (toolbar != NULL, NULL);
610 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
612 child = g_new (Child, 1);
614 child->type = CHILD_BUTTON;
615 child->widget = gtk_button_new ();
618 gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
619 callback, user_data);
622 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
625 child->label = gtk_label_new (text);
630 child->icon = GTK_WIDGET (icon);
634 vbox = gtk_vbox_new (FALSE, 0);
635 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
636 gtk_widget_show (vbox);
639 gtk_box_pack_start (GTK_BOX (vbox), child->icon, FALSE, FALSE, 0);
642 gtk_box_pack_start (GTK_BOX (vbox), child->label, FALSE, FALSE, 0);
644 switch (toolbar->style)
646 case GTK_TOOLBAR_ICONS:
648 gtk_widget_show (child->icon);
651 case GTK_TOOLBAR_TEXT:
653 gtk_widget_show (child->label);
656 case GTK_TOOLBAR_BOTH:
658 gtk_widget_show (child->icon);
661 gtk_widget_show (child->label);
666 g_assert_not_reached ();
669 gtk_widget_show (child->widget);
671 toolbar->children = g_list_insert (toolbar->children, child, position);
672 toolbar->num_children++;
674 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
676 if (GTK_WIDGET_VISIBLE (toolbar))
678 if (GTK_WIDGET_REALIZED (toolbar)
679 && !GTK_WIDGET_REALIZED (child->widget))
680 gtk_widget_realize (child->widget);
682 if (GTK_WIDGET_MAPPED (toolbar)
683 && !GTK_WIDGET_MAPPED (child->widget))
684 gtk_widget_map (child->widget);
687 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
688 gtk_widget_queue_resize (child->widget);
690 return child->widget;
694 gtk_toolbar_append_space (GtkToolbar *toolbar)
696 gtk_toolbar_insert_space (toolbar, toolbar->num_children);
700 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
702 gtk_toolbar_insert_space (toolbar, 0);
706 gtk_toolbar_insert_space (GtkToolbar *toolbar,
711 g_return_if_fail (toolbar != NULL);
712 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
714 child = g_new (Child, 1);
715 child->type = CHILD_SPACE;
716 child->widget = NULL;
720 toolbar->children = g_list_insert (toolbar->children, child, position);
721 toolbar->num_children++;
723 if (GTK_WIDGET_VISIBLE (toolbar))
724 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
728 gtk_toolbar_append_widget (GtkToolbar *toolbar,
730 const char *tooltip_text)
732 gtk_toolbar_insert_widget (toolbar, widget, tooltip_text, toolbar->num_children);
736 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
738 const char *tooltip_text)
740 gtk_toolbar_insert_widget (toolbar, widget, tooltip_text, 0);
744 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
746 const char *tooltip_text,
751 g_return_if_fail (toolbar != NULL);
752 g_return_if_fail (widget != NULL);
754 child = g_new (Child, 1);
755 child->type = CHILD_WIDGET;
756 child->widget = widget;
761 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
763 toolbar->children = g_list_insert (toolbar->children, child, position);
764 toolbar->num_children++;
766 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
768 if (GTK_WIDGET_VISIBLE (toolbar))
770 if (GTK_WIDGET_REALIZED (toolbar)
771 && !GTK_WIDGET_REALIZED (child->widget))
772 gtk_widget_realize (child->widget);
774 if (GTK_WIDGET_MAPPED (toolbar)
775 && !GTK_WIDGET_MAPPED (child->widget))
776 gtk_widget_map (child->widget);
779 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
780 gtk_widget_queue_resize (child->widget);
784 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
785 GtkOrientation orientation)
787 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
791 gtk_toolbar_set_style (GtkToolbar *toolbar,
792 GtkToolbarStyle style)
794 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
798 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
801 g_return_if_fail (toolbar != NULL);
802 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
804 if (toolbar->space_size != space_size)
806 toolbar->space_size = space_size;
807 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
812 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
815 g_return_if_fail (toolbar != NULL);
816 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
819 gtk_tooltips_enable (toolbar->tooltips);
821 gtk_tooltips_disable (toolbar->tooltips);
825 gtk_toolbar_marshal_signal_1 (GtkObject *object,
830 GtkToolbarSignal1 rfunc;
832 rfunc = (GtkToolbarSignal1) func;
834 (*rfunc) (object, GTK_VALUE_ENUM (args[0]), func_data);
838 gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
839 GtkOrientation orientation)
841 g_return_if_fail (toolbar != NULL);
842 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
844 if (toolbar->orientation != orientation)
846 toolbar->orientation = orientation;
847 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
852 gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
853 GtkToolbarStyle style)
858 g_return_if_fail (toolbar != NULL);
859 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
861 if (toolbar->style != style)
863 toolbar->style = style;
865 for (children = toolbar->children; children; children = children->next)
867 child = children->data;
869 if (child->type == CHILD_BUTTON)
872 case GTK_TOOLBAR_ICONS:
873 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
874 gtk_widget_show (child->icon);
876 if (child->label && GTK_WIDGET_VISIBLE (child->label))
877 gtk_widget_hide (child->label);
881 case GTK_TOOLBAR_TEXT:
882 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
883 gtk_widget_hide (child->icon);
885 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
886 gtk_widget_show (child->label);
890 case GTK_TOOLBAR_BOTH:
891 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
892 gtk_widget_show (child->icon);
894 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
895 gtk_widget_show (child->label);
900 g_assert_not_reached ();
904 gtk_widget_queue_resize (GTK_WIDGET (toolbar));