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);
171 toolbar->num_children = 0;
172 toolbar->children = NULL;
173 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
174 toolbar->style = GTK_TOOLBAR_ICONS;
175 toolbar->space_size = DEFAULT_SPACE_SIZE;
176 toolbar->tooltips = gtk_tooltips_new ();
177 toolbar->button_maxw = 0;
178 toolbar->button_maxh = 0;
182 gtk_toolbar_new (GtkOrientation orientation,
183 GtkToolbarStyle style)
187 toolbar = gtk_type_new (gtk_toolbar_get_type ());
189 toolbar->orientation = orientation;
190 toolbar->style = style;
192 return GTK_WIDGET (toolbar);
196 gtk_toolbar_destroy (GtkObject *object)
202 g_return_if_fail (object != NULL);
203 g_return_if_fail (GTK_IS_TOOLBAR (object));
205 toolbar = GTK_TOOLBAR (object);
207 gtk_tooltips_unref (toolbar->tooltips);
209 for (children = toolbar->children; children; children = children->next)
211 child = children->data;
213 if (child->type != CHILD_SPACE)
215 child->widget->parent = NULL;
216 gtk_object_unref (GTK_OBJECT (child->widget));
217 gtk_widget_destroy (child->widget);
223 g_list_free (toolbar->children);
225 if (GTK_OBJECT_CLASS (parent_class)->destroy)
226 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
230 gtk_toolbar_map (GtkWidget *widget)
236 g_return_if_fail (widget != NULL);
237 g_return_if_fail (GTK_IS_TOOLBAR (widget));
239 toolbar = GTK_TOOLBAR (widget);
240 GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
242 for (children = toolbar->children; children; children = children->next)
244 child = children->data;
246 if ((child->type != CHILD_SPACE)
247 && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
248 gtk_widget_map (child->widget);
253 gtk_toolbar_unmap (GtkWidget *widget)
259 g_return_if_fail (widget != NULL);
260 g_return_if_fail (GTK_IS_TOOLBAR (widget));
262 toolbar = GTK_TOOLBAR (widget);
263 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
265 for (children = toolbar->children; children; children = children->next)
267 child = children->data;
269 if ((child->type != CHILD_SPACE)
270 && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
271 gtk_widget_unmap (child->widget);
276 gtk_toolbar_draw (GtkWidget *widget,
282 GdkRectangle child_area;
284 g_return_if_fail (widget != NULL);
285 g_return_if_fail (GTK_IS_TOOLBAR (widget));
287 if (GTK_WIDGET_DRAWABLE (widget))
289 toolbar = GTK_TOOLBAR (widget);
291 for (children = toolbar->children; children; children = children->next)
293 child = children->data;
295 if ((child->type != CHILD_SPACE)
296 && gtk_widget_intersect (child->widget, area, &child_area))
297 gtk_widget_draw (child->widget, &child_area);
303 gtk_toolbar_expose (GtkWidget *widget,
304 GdkEventExpose *event)
309 GdkEventExpose child_event;
311 g_return_val_if_fail (widget != NULL, FALSE);
312 g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
313 g_return_val_if_fail (event != NULL, FALSE);
315 if (GTK_WIDGET_DRAWABLE (widget))
317 toolbar = GTK_TOOLBAR (widget);
319 child_event = *event;
321 for (children = toolbar->children; children; children = children->next)
323 child = children->data;
325 if ((child->type != CHILD_SPACE)
326 && GTK_WIDGET_NO_WINDOW (child->widget)
327 && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
328 gtk_widget_event (child->widget, (GdkEvent *) &child_event);
336 gtk_toolbar_size_request (GtkWidget *widget,
337 GtkRequisition *requisition)
343 gint button_maxw, button_maxh;
344 gint widget_maxw, widget_maxh;
346 g_return_if_fail (widget != NULL);
347 g_return_if_fail (GTK_IS_TOOLBAR (widget));
348 g_return_if_fail (requisition != NULL);
350 toolbar = GTK_TOOLBAR (widget);
352 requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
353 requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
360 for (children = toolbar->children; children; children = children->next)
362 child = children->data;
367 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
368 requisition->width += toolbar->space_size;
370 requisition->height += toolbar->space_size;
375 if (GTK_WIDGET_VISIBLE (child->widget))
377 gtk_widget_size_request (child->widget, &child->widget->requisition);
380 button_maxw = MAX (button_maxw, child->widget->requisition.width);
381 button_maxh = MAX (button_maxh, child->widget->requisition.height);
387 if (GTK_WIDGET_VISIBLE (child->widget))
389 gtk_widget_size_request (child->widget, &child->widget->requisition);
391 widget_maxw = MAX (widget_maxw, child->widget->requisition.width);
392 widget_maxh = MAX (widget_maxh, child->widget->requisition.height);
394 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
395 requisition->width += child->widget->requisition.width;
397 requisition->height += child->widget->requisition.height;
403 g_assert_not_reached ();
407 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
409 requisition->width += nbuttons * button_maxw;
410 requisition->height += MAX (button_maxh, widget_maxh);
414 requisition->width += MAX (button_maxw, widget_maxw);
415 requisition->height += nbuttons * button_maxh;
418 toolbar->button_maxw = button_maxw;
419 toolbar->button_maxh = button_maxh;
423 gtk_toolbar_size_allocate (GtkWidget *widget,
424 GtkAllocation *allocation)
432 g_return_if_fail (widget != NULL);
433 g_return_if_fail (GTK_IS_TOOLBAR (widget));
434 g_return_if_fail (allocation != NULL);
436 toolbar = GTK_TOOLBAR (widget);
437 widget->allocation = *allocation;
439 border_width = GTK_CONTAINER (toolbar)->border_width;
441 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
442 alloc.x = allocation->x + border_width;
444 alloc.y = allocation->y + border_width;
446 for (children = toolbar->children; children; children = children->next)
448 child = children->data;
453 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
454 alloc.x += toolbar->space_size;
456 alloc.y += toolbar->space_size;
461 alloc.width = toolbar->button_maxw;
462 alloc.height = toolbar->button_maxh;
464 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
465 alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
467 alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
469 gtk_widget_size_allocate (child->widget, &alloc);
471 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
472 alloc.x += toolbar->button_maxw;
474 alloc.y += toolbar->button_maxh;
479 alloc.width = child->widget->requisition.width;
480 alloc.height = child->widget->requisition.height;
482 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
483 alloc.y = allocation->y + (allocation->height - child->widget->requisition.height) / 2;
485 alloc.x = allocation->x + (allocation->width - child->widget->requisition.width) / 2;
487 gtk_widget_size_allocate (child->widget, &alloc);
489 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
490 alloc.x += child->widget->requisition.width;
492 alloc.y += child->widget->requisition.height;
497 g_assert_not_reached ();
503 gtk_toolbar_add (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 gtk_toolbar_append_widget (GTK_TOOLBAR (container), NULL, widget);
514 gtk_toolbar_remove (GtkContainer *container,
521 g_return_if_fail (container != NULL);
522 g_return_if_fail (GTK_IS_TOOLBAR (container));
523 g_return_if_fail (widget != NULL);
525 toolbar = GTK_TOOLBAR (container);
527 for (children = toolbar->children; children; children = children->next)
529 child = children->data;
531 if ((child->type != CHILD_SPACE) && (child->widget == widget))
533 gtk_widget_unparent (widget);
535 toolbar->children = g_list_remove_link (toolbar->children, children);
537 g_list_free (children);
538 toolbar->num_children--;
540 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
541 gtk_widget_queue_resize (GTK_WIDGET (container));
549 gtk_toolbar_foreach (GtkContainer *container,
550 GtkCallback callback,
551 gpointer callback_data)
557 g_return_if_fail (container != NULL);
558 g_return_if_fail (GTK_IS_TOOLBAR (container));
559 g_return_if_fail (callback != NULL);
561 toolbar = GTK_TOOLBAR (container);
563 for (children = toolbar->children; children; children = children->next)
565 child = children->data;
567 if (child->type != CHILD_SPACE)
568 (*callback) (child->widget, callback_data);
573 gtk_toolbar_append_item (GtkToolbar *toolbar,
575 const char *tooltip_text,
577 GtkSignalFunc callback,
580 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
581 callback, user_data, toolbar->num_children);
585 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
587 const char *tooltip_text,
589 GtkSignalFunc callback,
592 return gtk_toolbar_insert_item (toolbar, text, tooltip_text, icon,
593 callback, user_data, 0);
597 gtk_toolbar_insert_item (GtkToolbar *toolbar,
599 const char *tooltip_text,
601 GtkSignalFunc callback,
608 g_return_val_if_fail (toolbar != NULL, NULL);
609 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
611 child = g_new (Child, 1);
613 child->type = CHILD_BUTTON;
614 child->widget = gtk_button_new ();
617 gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
618 callback, user_data);
621 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
624 child->label = gtk_label_new (text);
629 child->icon = GTK_WIDGET (icon);
633 vbox = gtk_vbox_new (FALSE, 0);
634 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
635 gtk_widget_show (vbox);
638 gtk_box_pack_start (GTK_BOX (vbox), child->icon, FALSE, FALSE, 0);
641 gtk_box_pack_start (GTK_BOX (vbox), child->label, FALSE, FALSE, 0);
643 switch (toolbar->style)
645 case GTK_TOOLBAR_ICONS:
647 gtk_widget_show (child->icon);
650 case GTK_TOOLBAR_TEXT:
652 gtk_widget_show (child->label);
655 case GTK_TOOLBAR_BOTH:
657 gtk_widget_show (child->icon);
660 gtk_widget_show (child->label);
665 g_assert_not_reached ();
668 gtk_widget_show (child->widget);
670 toolbar->children = g_list_insert (toolbar->children, child, position);
671 toolbar->num_children++;
673 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
675 if (GTK_WIDGET_VISIBLE (toolbar))
677 if (GTK_WIDGET_REALIZED (toolbar)
678 && !GTK_WIDGET_REALIZED (child->widget))
679 gtk_widget_realize (child->widget);
681 if (GTK_WIDGET_MAPPED (toolbar)
682 && !GTK_WIDGET_MAPPED (child->widget))
683 gtk_widget_map (child->widget);
686 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
687 gtk_widget_queue_resize (child->widget);
689 return child->widget;
693 gtk_toolbar_append_space (GtkToolbar *toolbar)
695 gtk_toolbar_insert_space (toolbar, toolbar->num_children);
699 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
701 gtk_toolbar_insert_space (toolbar, 0);
705 gtk_toolbar_insert_space (GtkToolbar *toolbar,
710 g_return_if_fail (toolbar != NULL);
711 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
713 child = g_new (Child, 1);
714 child->type = CHILD_SPACE;
715 child->widget = NULL;
719 toolbar->children = g_list_insert (toolbar->children, child, position);
720 toolbar->num_children++;
722 if (GTK_WIDGET_VISIBLE (toolbar))
723 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
727 gtk_toolbar_append_widget (GtkToolbar *toolbar,
728 const char *tooltip_text,
731 gtk_toolbar_insert_widget (toolbar, tooltip_text, widget, toolbar->num_children);
735 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
736 const char *tooltip_text,
739 gtk_toolbar_insert_widget (toolbar, tooltip_text, widget, 0);
743 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
744 const char *tooltip_text,
750 g_return_if_fail (toolbar != NULL);
751 g_return_if_fail (widget != NULL);
753 child = g_new (Child, 1);
754 child->type = CHILD_WIDGET;
755 child->widget = widget;
760 gtk_tooltips_set_tips (toolbar->tooltips, child->widget, tooltip_text);
762 toolbar->children = g_list_insert (toolbar->children, child, position);
763 toolbar->num_children++;
765 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
767 if (GTK_WIDGET_VISIBLE (toolbar))
769 if (GTK_WIDGET_REALIZED (toolbar)
770 && !GTK_WIDGET_REALIZED (child->widget))
771 gtk_widget_realize (child->widget);
773 if (GTK_WIDGET_MAPPED (toolbar)
774 && !GTK_WIDGET_MAPPED (child->widget))
775 gtk_widget_map (child->widget);
778 if (GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_VISIBLE (toolbar))
779 gtk_widget_queue_resize (child->widget);
783 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
784 GtkOrientation orientation)
786 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
790 gtk_toolbar_set_style (GtkToolbar *toolbar,
791 GtkToolbarStyle style)
793 gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
797 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
800 g_return_if_fail (toolbar != NULL);
801 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
803 if (toolbar->space_size != space_size)
805 toolbar->space_size = space_size;
806 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
811 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
814 g_return_if_fail (toolbar != NULL);
815 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
818 gtk_tooltips_enable (toolbar->tooltips);
820 gtk_tooltips_disable (toolbar->tooltips);
824 gtk_toolbar_marshal_signal_1 (GtkObject *object,
829 GtkToolbarSignal1 rfunc;
831 rfunc = (GtkToolbarSignal1) func;
833 (*rfunc) (object, GTK_VALUE_ENUM (args[0]), func_data);
837 gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar,
838 GtkOrientation orientation)
840 g_return_if_fail (toolbar != NULL);
841 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
843 if (toolbar->orientation != orientation)
845 toolbar->orientation = orientation;
846 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
851 gtk_real_toolbar_style_changed (GtkToolbar *toolbar,
852 GtkToolbarStyle style)
857 g_return_if_fail (toolbar != NULL);
858 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
860 if (toolbar->style != style)
862 toolbar->style = style;
864 for (children = toolbar->children; children; children = children->next)
866 child = children->data;
868 if (child->type == CHILD_BUTTON)
871 case GTK_TOOLBAR_ICONS:
872 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
873 gtk_widget_show (child->icon);
875 if (child->label && GTK_WIDGET_VISIBLE (child->label))
876 gtk_widget_hide (child->label);
880 case GTK_TOOLBAR_TEXT:
881 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
882 gtk_widget_hide (child->icon);
884 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
885 gtk_widget_show (child->label);
889 case GTK_TOOLBAR_BOTH:
890 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
891 gtk_widget_show (child->icon);
893 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
894 gtk_widget_show (child->label);
899 g_assert_not_reached ();
903 gtk_widget_queue_resize (GTK_WIDGET (toolbar));