source: trunk/third/bonobo/bonobo/bonobo-ui-toolbar.c @ 16750

Revision 16750, 36.0 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16749, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/**
3 * bonobo-ui-toolbar.h
4 *
5 * Author:
6 *    Ettore Perazzoli
7 *
8 * Copyright (C) 2000 Helix Code, Inc.
9 */
10
11#ifdef HAVE_CONFIG_H
12#include <config.h>
13#endif
14
15#include <gnome.h>
16
17#include "bonobo-ui-toolbar-item.h"
18#include "bonobo-ui-toolbar-popup-item.h"
19
20#include "bonobo-ui-toolbar.h"
21
22
23#define PARENT_TYPE gtk_container_get_type ()
24static GtkContainerClass *parent_class = NULL;
25
26enum {
27        ARG_0,
28        ARG_ORIENTATION,
29        ARG_IS_FLOATING,
30        ARG_PREFERRED_WIDTH,
31        ARG_PREFERRED_HEIGHT
32};
33
34struct _BonoboUIToolbarPrivate {
35        /* The orientation of this toolbar.  */
36        GtkOrientation orientation;
37
38        /* Is the toolbar currently floating */
39        gboolean is_floating;
40
41        /* The style of this toolbar.  */
42        BonoboUIToolbarStyle style;
43
44        /* Styles to use in different orientations */
45        BonoboUIToolbarStyle hstyle;
46        BonoboUIToolbarStyle vstyle;
47
48        /* Sizes of the toolbar.  This is actually the height for
49           horizontal toolbars and the width for vertical toolbars.  */
50        int max_width, max_height;
51        int total_width, total_height;
52
53        /* position of left edge of left-most pack-end item */
54        int end_position;
55
56        /* List of all the items in the toolbar.  Both the ones that have been
57           unparented because they don't fit, and the ones that are visible.
58           The BonoboUIToolbarPopupItem is not here though.  */
59        GList *items;
60
61        /* Pointer to the first element in the `items' list that doesn't fit in
62           the available space.  This is updated at size_allocate.  */
63        GList *first_not_fitting_item;
64
65        /* The pop-up button.  When clicked, it pops up a window with all the
66           items that don't fit.  */
67        BonoboUIToolbarItem *popup_item;
68
69        /* The window we pop-up when the pop-up item is clicked.  */
70        GtkWidget *popup_window;
71
72        /* The vbox within the pop-up window.  */
73        GtkWidget *popup_window_vbox;
74
75        /* Whether we have moved items to the pop-up window.  This is to
76           prevent the size_allocation code to incorrectly hide the pop-up
77           button in that case.  */
78        gboolean items_moved_to_popup_window;
79
80        GtkTooltips *tooltips;
81};
82
83enum {
84        SET_ORIENTATION,
85        STYLE_CHANGED,
86        LAST_SIGNAL
87};
88
89static guint signals[LAST_SIGNAL] = { 0 };
90
91
92/* Width of the pop-up window.  */
93#define POPUP_WINDOW_WIDTH 200
94
95
96/* Utility functions.  */
97
98static void
99parentize_widget (BonoboUIToolbar *toolbar,
100                  GtkWidget *widget)
101{
102        g_assert (widget->parent == NULL);
103
104        /* The following is done according to the Bible, widget_system.txt, IV, 1.  */
105
106        gtk_widget_set_parent (widget, GTK_WIDGET (toolbar));
107
108        if (GTK_WIDGET_REALIZED (toolbar) && ! GTK_WIDGET_REALIZED (widget))
109                gtk_widget_realize (widget);
110
111        if (GTK_WIDGET_MAPPED (toolbar) && ! GTK_WIDGET_MAPPED (widget) &&  GTK_WIDGET_VISIBLE (widget))
112                gtk_widget_map (widget);
113
114        if (GTK_WIDGET_MAPPED (widget))
115                gtk_widget_queue_resize (GTK_WIDGET (toolbar));
116}
117
118static void
119set_attributes_on_child (BonoboUIToolbarItem *item,
120                         GtkOrientation orientation,
121                         BonoboUIToolbarStyle style)
122{
123        bonobo_ui_toolbar_item_set_orientation (item, orientation);
124
125        switch (style) {
126        case BONOBO_UI_TOOLBAR_STYLE_PRIORITY_TEXT:
127                if (! bonobo_ui_toolbar_item_get_want_label (item))
128                        bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_ONLY);
129                else if (orientation == GTK_ORIENTATION_HORIZONTAL)
130                        bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_AND_TEXT_HORIZONTAL);
131                else
132                        bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_AND_TEXT_VERTICAL);
133                break;
134
135        case BONOBO_UI_TOOLBAR_STYLE_ICONS_AND_TEXT:
136                if (orientation == GTK_ORIENTATION_VERTICAL)
137                        bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_AND_TEXT_HORIZONTAL);
138                else
139                        bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_AND_TEXT_VERTICAL);
140                break;
141        case BONOBO_UI_TOOLBAR_STYLE_ICONS_ONLY:
142                bonobo_ui_toolbar_item_set_style (item, BONOBO_UI_TOOLBAR_ITEM_STYLE_ICON_ONLY);
143                break;
144        default:
145                g_assert_not_reached ();
146        }
147}
148
149
150/* Callbacks to do widget housekeeping.  */
151
152static void
153item_destroy_cb (GtkObject *object,
154                 void *data)
155{
156        BonoboUIToolbar *toolbar;
157        BonoboUIToolbarPrivate *priv;
158        GtkWidget *widget;
159
160        toolbar = BONOBO_UI_TOOLBAR (data);
161        priv = toolbar->priv;
162
163        widget = GTK_WIDGET (object);
164        priv->items = g_list_remove (priv->items, object);
165}
166
167static void
168item_activate_cb (BonoboUIToolbarItem *item,
169                  void *data)
170{
171        BonoboUIToolbar *toolbar;
172        BonoboUIToolbarPrivate *priv;
173
174        toolbar = BONOBO_UI_TOOLBAR (data);
175        priv = toolbar->priv;
176
177        bonobo_ui_toolbar_toggle_button_item_set_active (
178                BONOBO_UI_TOOLBAR_TOGGLE_BUTTON_ITEM (priv->popup_item), FALSE);
179}
180
181static void
182item_set_want_label_cb (BonoboUIToolbarItem *item,
183                        gboolean want_label,
184                        void *data)
185{
186        BonoboUIToolbar *toolbar;
187        BonoboUIToolbarPrivate *priv;
188
189        toolbar = BONOBO_UI_TOOLBAR (data);
190        priv = toolbar->priv;
191
192        set_attributes_on_child (item, priv->orientation, priv->style);
193
194        gtk_widget_queue_resize (GTK_WIDGET (toolbar));
195}
196
197
198/* The pop-up window foo.  */
199
200/* Return TRUE if there are actually any items in the pop-up menu.  */
201static void
202create_popup_window (BonoboUIToolbar *toolbar)
203{
204        BonoboUIToolbarPrivate *priv;
205        GtkWidget *hbox;
206        GList *p;
207        int row_width;
208
209        priv = toolbar->priv;
210
211        row_width = 0;
212        hbox = NULL;
213
214        for (p = priv->first_not_fitting_item; p != NULL; p = p->next) {
215                GtkRequisition item_requisition;
216                GtkWidget *item_widget;
217
218                item_widget = GTK_WIDGET (p->data);
219
220                if (! GTK_WIDGET_VISIBLE (item_widget) ||
221                        bonobo_ui_toolbar_item_get_pack_end (BONOBO_UI_TOOLBAR_ITEM (item_widget)))
222
223                        continue;
224
225                if (item_widget->parent != NULL)
226                        gtk_container_remove (GTK_CONTAINER (item_widget->parent), item_widget);
227
228                gtk_widget_get_child_requisition (item_widget, &item_requisition);
229
230                set_attributes_on_child (BONOBO_UI_TOOLBAR_ITEM (item_widget),
231                                         GTK_ORIENTATION_HORIZONTAL,
232                                         priv->style);
233
234                if (hbox == NULL
235                    || (row_width > 0 && item_requisition.width + row_width > POPUP_WINDOW_WIDTH)) {
236                        hbox = gtk_hbox_new (FALSE, 0);
237                        gtk_box_pack_start (GTK_BOX (priv->popup_window_vbox), hbox, FALSE, TRUE, 0);
238                        gtk_widget_show (hbox);
239                        row_width = 0;
240                }
241
242                gtk_box_pack_start (GTK_BOX (hbox), item_widget, FALSE, TRUE, 0);
243
244                row_width += item_requisition.width;
245        }
246}
247
248static void
249hide_popup_window (BonoboUIToolbar *toolbar)
250{
251        BonoboUIToolbarPrivate *priv;
252        GList *p;
253
254        priv = toolbar->priv;
255
256        gdk_pointer_ungrab (GDK_CURRENT_TIME);
257
258        gtk_grab_remove (priv->popup_window);
259        gtk_widget_hide (priv->popup_window);
260
261        priv->items_moved_to_popup_window = FALSE;
262
263        /* Reset the attributes on all the widgets that were moved to the
264           window and move them back to the toolbar.  */
265        for (p = priv->items; p != NULL; p = p->next) {
266                GtkWidget *item_widget;
267
268                item_widget = GTK_WIDGET (p->data);
269                if (item_widget->parent != GTK_WIDGET (toolbar)) {
270                        set_attributes_on_child (BONOBO_UI_TOOLBAR_ITEM (item_widget),
271                                                 priv->orientation, priv->style);
272                        gtk_container_remove (GTK_CONTAINER (item_widget->parent), item_widget);
273                        parentize_widget (toolbar, item_widget);
274                }
275        }
276
277        gtk_widget_queue_resize (GTK_WIDGET (toolbar));
278}
279
280static void
281popup_window_button_release_cb (GtkWidget *widget,
282                                GdkEventButton *event,
283                                void *data)
284{
285        BonoboUIToolbar *toolbar;
286        BonoboUIToolbarPrivate *priv;
287
288        toolbar = BONOBO_UI_TOOLBAR (data);
289        priv = toolbar->priv;
290
291        bonobo_ui_toolbar_toggle_button_item_set_active
292                (BONOBO_UI_TOOLBAR_TOGGLE_BUTTON_ITEM (priv->popup_item), FALSE);
293}
294
295static void
296popup_window_map_cb (GtkWidget *widget,
297                     void *data)
298{
299        BonoboUIToolbar *toolbar;
300
301        toolbar = BONOBO_UI_TOOLBAR (data);
302
303        if (gdk_pointer_grab (widget->window, TRUE,
304                              (GDK_BUTTON_PRESS_MASK
305                               | GDK_BUTTON_RELEASE_MASK
306                               | GDK_ENTER_NOTIFY_MASK
307                               | GDK_LEAVE_NOTIFY_MASK
308                               | GDK_POINTER_MOTION_MASK),
309                              NULL, NULL, GDK_CURRENT_TIME) != 0) {
310                g_warning ("Toolbar pop-up pointer grab failed.");
311                return;
312        }
313
314        gtk_grab_add (widget);
315}
316
317static void
318show_popup_window (BonoboUIToolbar *toolbar)
319{
320        BonoboUIToolbarPrivate *priv;
321        const GtkAllocation *toolbar_allocation;
322        GtkRequisition requisition;
323        int x, y;
324
325        priv = toolbar->priv;
326
327        priv->items_moved_to_popup_window = TRUE;
328
329        create_popup_window (toolbar);
330
331        gdk_window_get_origin (GTK_WIDGET (toolbar)->window, &x, &y);
332
333        toolbar_allocation = & GTK_WIDGET (toolbar)->allocation;
334
335        gtk_widget_size_request (priv->popup_window, &requisition);
336
337        if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
338                x += toolbar_allocation->x + toolbar_allocation->width;
339                if (x >= gdk_screen_width () - requisition.width)
340                        y += toolbar_allocation->height;
341        } else {
342                y += toolbar_allocation->y + toolbar_allocation->height;
343                if (y >= gdk_screen_height () - requisition.height)
344                        x += toolbar_allocation->width;
345        }
346
347        x = CLAMP (x, 0, MAX (0, gdk_screen_width () - requisition.width));
348        y = CLAMP (y, 0, MAX (0, gdk_screen_height () - requisition.height));
349
350        gtk_widget_set_uposition (GTK_WIDGET (priv->popup_window), x, y);
351
352        gtk_signal_connect (GTK_OBJECT (priv->popup_window), "map",
353                            GTK_SIGNAL_FUNC (popup_window_map_cb), toolbar);
354
355        gtk_widget_show (priv->popup_window);
356}
357
358static void
359popup_item_toggled_cb (BonoboUIToolbarToggleButtonItem *toggle_button_item,
360                       void *data)
361{
362        BonoboUIToolbar *toolbar;
363        BonoboUIToolbarPrivate *priv;
364        gboolean active;
365
366        toolbar = BONOBO_UI_TOOLBAR (data);
367        priv = toolbar->priv;
368
369        active = bonobo_ui_toolbar_toggle_button_item_get_active (toggle_button_item);
370
371        if (active)
372                show_popup_window (toolbar);
373        else
374                hide_popup_window (toolbar);
375}
376
377
378/* Layout handling.  */
379
380static int
381get_popup_item_size (BonoboUIToolbar *toolbar)
382{
383        BonoboUIToolbarPrivate *priv;
384        GtkRequisition requisition;
385
386        priv = toolbar->priv;
387
388        gtk_widget_get_child_requisition (
389                GTK_WIDGET (priv->popup_item), &requisition);
390
391        if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
392                return requisition.width;
393        else
394                return requisition.height;
395}
396
397/* Update the various sizes.  This is performed during ::size_request.  */
398static void
399update_sizes (BonoboUIToolbar *toolbar)
400{
401        BonoboUIToolbarPrivate *priv;
402        int max_width, max_height;
403        int total_width, total_height;
404        GList *p;
405
406        priv = toolbar->priv;
407
408        max_width = max_height = total_width = total_height = 0;
409
410        for (p = priv->items; p != NULL; p = p->next) {
411                GtkWidget *item_widget;
412                GtkRequisition item_requisition;
413
414                item_widget = GTK_WIDGET (p->data);
415                if (! GTK_WIDGET_VISIBLE (item_widget) || item_widget->parent != GTK_WIDGET (toolbar))
416                        continue;
417
418                gtk_widget_size_request (item_widget, &item_requisition);
419
420                max_width     = MAX (max_width,  item_requisition.width);
421                total_width  += item_requisition.width;
422                max_height    = MAX (max_height, item_requisition.height);
423                total_height += item_requisition.height;
424        }
425
426        priv->max_width = max_width;
427        priv->total_width = total_width;
428        priv->max_height = max_height;
429        priv->total_height = total_height;
430}
431
432static void
433allocate_popup_item (BonoboUIToolbar *toolbar)
434{
435        BonoboUIToolbarPrivate *priv;
436        GtkRequisition popup_item_requisition;
437        GtkAllocation popup_item_allocation;
438        GtkAllocation *toolbar_allocation;
439        int border_width;
440
441        priv = toolbar->priv;
442
443        /* FIXME what if there is not enough space?  */
444
445        toolbar_allocation = & GTK_WIDGET (toolbar)->allocation;
446
447        border_width = GTK_CONTAINER (toolbar)->border_width;
448
449        gtk_widget_get_child_requisition (
450                GTK_WIDGET (priv->popup_item), &popup_item_requisition);
451
452        popup_item_allocation.x = toolbar_allocation->x;
453        popup_item_allocation.y = toolbar_allocation->y;
454
455        if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
456                popup_item_allocation.x      = priv->end_position - popup_item_requisition.width - border_width;
457                popup_item_allocation.y      += border_width;
458                popup_item_allocation.width  = popup_item_requisition.width;
459                popup_item_allocation.height = toolbar_allocation->height - 2 * border_width;
460        } else {
461                popup_item_allocation.x      += border_width;
462                popup_item_allocation.y      = priv->end_position - popup_item_requisition.height - border_width;
463                popup_item_allocation.width  = toolbar_allocation->width - 2 * border_width;
464                popup_item_allocation.height = popup_item_requisition.height;
465        }
466
467        gtk_widget_size_allocate (GTK_WIDGET (priv->popup_item), &popup_item_allocation);
468}
469
470static void
471setup_popup_item (BonoboUIToolbar *toolbar)
472{
473        BonoboUIToolbarPrivate *priv;
474        GList *p;
475
476        priv = toolbar->priv;
477
478        if (priv->items_moved_to_popup_window) {
479                gtk_widget_show (GTK_WIDGET (priv->popup_item));
480                allocate_popup_item (toolbar);
481                return;
482        }
483
484        for (p = priv->first_not_fitting_item; p != NULL; p = p->next) {
485                GtkWidget *item_widget;
486
487                item_widget = GTK_WIDGET (p->data);
488
489                if (GTK_WIDGET_VISIBLE (item_widget)) {
490                        gtk_widget_show (GTK_WIDGET (priv->popup_item));
491                        allocate_popup_item (toolbar);
492                        return;
493                }
494        }
495
496        gtk_widget_hide (GTK_WIDGET (priv->popup_item));
497}
498
499/*
500 * This is a dirty hack.  We cannot hide the items with gtk_widget_hide ()
501 * because we want to let the user be in control of the physical hidden/shown
502 * state, so we just move the widget to a non-visible area.
503 */
504static void
505hide_not_fitting_items (BonoboUIToolbar *toolbar)
506{
507        BonoboUIToolbarPrivate *priv;
508        const GtkAllocation *allocation;
509        GtkAllocation child_allocation;
510        GList *p;
511
512        priv = toolbar->priv;
513
514        allocation = & GTK_WIDGET (toolbar)->allocation;
515
516        child_allocation.x      = 40000;
517        child_allocation.y      = 40000;
518        child_allocation.width  = 1;
519        child_allocation.height = 1;
520
521        for (p = priv->first_not_fitting_item; p != NULL; p = p->next) {
522                if (bonobo_ui_toolbar_item_get_pack_end (BONOBO_UI_TOOLBAR_ITEM (p->data)))
523                        continue;
524                gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation);
525        }
526}
527
528static void
529size_allocate_helper (BonoboUIToolbar *toolbar,
530                      const GtkAllocation *allocation)
531{
532        BonoboUIToolbarPrivate *priv;
533        GtkAllocation child_allocation;
534        BonoboUIToolbarItem *item;
535        GtkRequisition child_requisition;
536        int border_width;
537        int space_required;
538        int available_space;
539        int extra_space;
540        int num_expandable_items;
541        int popup_item_size;
542        gboolean first_expandable;
543        GList *p;
544
545        GTK_WIDGET (toolbar)->allocation = *allocation;
546
547        priv = toolbar->priv;
548
549        border_width = GTK_CONTAINER (toolbar)->border_width;
550        popup_item_size = get_popup_item_size (toolbar);
551
552        if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
553                available_space = MAX ((int) allocation->width - 2 * border_width, popup_item_size);
554        else
555                available_space = MAX ((int) allocation->height - 2 * border_width, popup_item_size);
556
557        child_allocation.x = allocation->x + border_width;
558        child_allocation.y = allocation->y + border_width;
559
560        /*
561         * if there is exactly one toolbar item, handle it specially, by giving it all of the available space,
562         * even if it doesn't fit, since we never want everything in the pop-up.
563         */     
564        if (priv->items != NULL && priv->items->next == NULL) {
565                item = BONOBO_UI_TOOLBAR_ITEM (priv->items->data);             
566                gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
567                child_allocation.width = child_requisition.width;
568                child_allocation.height = child_requisition.height;
569
570                if (bonobo_ui_toolbar_item_get_expandable (item)) {
571                        if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
572                                child_allocation.width = available_space;
573                        else
574                                child_allocation.height = available_space;
575               
576                }
577                gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);               
578               
579                return;
580        }
581
582        /* first, make a pass through the items to layout the ones that are packed on the right */
583        priv->end_position = allocation->x + available_space;
584        for (p = g_list_last (priv->items); p != NULL; p = p->prev) {
585
586                item = BONOBO_UI_TOOLBAR_ITEM (p->data);
587                if (! bonobo_ui_toolbar_item_get_pack_end (item))
588                        continue;
589
590                gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
591
592                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
593                        available_space -= child_requisition.width;
594                        priv->end_position -= child_requisition.width;
595                       
596                        child_allocation.x = priv->end_position;
597                        child_allocation.width = child_requisition.width;
598                        child_allocation.height = priv->max_height;
599                } else {
600                        available_space -= child_requisition.height;
601                        priv->end_position -= child_requisition.height;
602                       
603                        child_allocation.y = priv->end_position;
604                        child_allocation.height = child_requisition.height;
605                        child_allocation.width = priv->max_width;
606                }
607               
608                gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
609        }
610       
611        /* make a pass through the items to determine how many fit */   
612        space_required = 0;
613        num_expandable_items = 0;
614
615        child_allocation.x = allocation->x + border_width;
616        child_allocation.y = allocation->y + border_width;
617
618        for (p = priv->items; p != NULL; p = p->next) {
619                int item_size;
620
621                item = BONOBO_UI_TOOLBAR_ITEM (p->data);
622                if (! GTK_WIDGET_VISIBLE (item) || GTK_WIDGET (item)->parent != GTK_WIDGET (toolbar) ||
623                        bonobo_ui_toolbar_item_get_pack_end (item))
624                        continue;
625
626                gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
627
628                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
629                        item_size = child_requisition.width;
630                else
631                        item_size = child_requisition.height;
632
633                if (p->next == NULL) {
634                        if (space_required + item_size > available_space)
635                                break;
636                } else {
637                        if (space_required + item_size > available_space - popup_item_size)
638                                break;
639                }
640
641                space_required += item_size;
642
643                if (bonobo_ui_toolbar_item_get_expandable (item))
644                        num_expandable_items ++;
645        }
646
647        priv->first_not_fitting_item = p;
648
649        /* determine the amount of space available for expansion */
650        if (priv->first_not_fitting_item != NULL) {
651                extra_space = 0;
652        } else {
653                extra_space = available_space - space_required;
654                if (priv->first_not_fitting_item != NULL)
655                        extra_space -= popup_item_size;
656        }
657
658        first_expandable = FALSE;
659
660        for (p = priv->items; p != priv->first_not_fitting_item; p = p->next) {
661                BonoboUIToolbarItem *item;
662                GtkRequisition child_requisition;
663                int expansion_amount;
664
665                item = BONOBO_UI_TOOLBAR_ITEM (p->data);
666                if (! GTK_WIDGET_VISIBLE (item) || GTK_WIDGET (item)->parent != GTK_WIDGET (toolbar) ||
667                        bonobo_ui_toolbar_item_get_pack_end (item))
668                        continue;
669
670                gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
671
672                if (! bonobo_ui_toolbar_item_get_expandable (item)) {
673                        expansion_amount = 0;
674                } else {
675                        g_assert (num_expandable_items != 0);
676
677                        expansion_amount = extra_space / num_expandable_items;
678                        if (first_expandable) {
679                                expansion_amount += extra_space % num_expandable_items;
680                                first_expandable = FALSE;
681                        }
682                }
683
684                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
685                        child_allocation.width  = child_requisition.width + expansion_amount;
686                        child_allocation.height = priv->max_height;
687                } else {
688                        child_allocation.width  = priv->max_width;
689                        child_allocation.height = child_requisition.height + expansion_amount;
690                }
691
692                gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
693
694                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
695                        child_allocation.x += child_allocation.width;
696                else
697                        child_allocation.y += child_allocation.height;
698        }
699
700        hide_not_fitting_items (toolbar);
701        setup_popup_item (toolbar);
702}
703
704
705/* GtkObject methods.  */
706
707static void
708impl_destroy (GtkObject *object)
709{
710        BonoboUIToolbar *toolbar;
711        BonoboUIToolbarPrivate *priv;
712        GList *p, *next;
713
714        toolbar = BONOBO_UI_TOOLBAR (object);
715        priv = toolbar->priv;
716
717        for (p = priv->items; p != NULL; p = next) {
718                GtkWidget *item_widget;
719
720                next = p->next;
721                item_widget = GTK_WIDGET (p->data);
722                if (item_widget->parent == NULL)
723                        gtk_widget_destroy (item_widget);
724        }
725
726        if (GTK_WIDGET (priv->popup_item)->parent == NULL)
727                gtk_widget_destroy (GTK_WIDGET (priv->popup_item));
728
729        if (priv->popup_window != NULL)
730                gtk_widget_destroy (priv->popup_window);
731        priv->popup_window = NULL;
732
733        gtk_object_unref (GTK_OBJECT (priv->tooltips));
734        priv->tooltips = NULL;
735
736        if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
737                GTK_OBJECT_CLASS (parent_class)->destroy (object);
738
739}
740
741static void
742impl_finalize (GtkObject *object)
743{
744        BonoboUIToolbar *toolbar;
745        BonoboUIToolbarPrivate *priv;
746
747        toolbar = BONOBO_UI_TOOLBAR (object);
748        priv = toolbar->priv;
749
750        g_list_free (priv->items);
751        priv->items = NULL;
752       
753        g_free (priv);
754
755        if (GTK_OBJECT_CLASS (parent_class)->finalize != NULL)
756                GTK_OBJECT_CLASS (parent_class)->finalize (object);
757}
758
759
760/* GtkWidget methods.  */
761
762static void
763impl_size_request (GtkWidget *widget,
764                   GtkRequisition *requisition)
765{
766        BonoboUIToolbar *toolbar;
767        BonoboUIToolbarPrivate *priv;
768        int border_width;
769
770        toolbar = BONOBO_UI_TOOLBAR (widget);
771        priv = toolbar->priv;
772
773        g_assert (priv->popup_item != NULL);
774
775        update_sizes (toolbar);
776
777        border_width = GTK_CONTAINER (toolbar)->border_width;
778
779        if (priv->is_floating) {
780                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
781                        requisition->width  = priv->total_width;
782                        requisition->height = priv->max_height;
783                } else {
784                        requisition->width  = priv->max_width;
785                        requisition->height = priv->total_height;
786                }
787        } else {
788                GtkRequisition popup_item_requisition;
789
790                gtk_widget_size_request (GTK_WIDGET (priv->popup_item), &popup_item_requisition);
791
792                if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
793                        requisition->width  = popup_item_requisition.width;
794                        requisition->height = MAX (popup_item_requisition.height, priv->max_height);
795                } else {
796                        requisition->width  = MAX (popup_item_requisition.width,  priv->max_width);
797                        requisition->height = popup_item_requisition.height;
798                }
799        }
800
801        requisition->width  += 2 * border_width;
802        requisition->height += 2 * border_width;
803}
804
805static void
806impl_size_allocate (GtkWidget *widget,
807                    GtkAllocation *allocation)
808{
809        BonoboUIToolbar *toolbar;
810        BonoboUIToolbarPrivate *priv;
811
812        toolbar = BONOBO_UI_TOOLBAR (widget);
813        priv = toolbar->priv;
814
815        size_allocate_helper (toolbar, allocation);
816}
817
818static void
819impl_map (GtkWidget *widget)
820{
821        BonoboUIToolbar *toolbar;
822        BonoboUIToolbarPrivate *priv;
823        GList *p;
824
825        toolbar = BONOBO_UI_TOOLBAR (widget);
826        priv = toolbar->priv;
827
828        GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
829
830        for (p = priv->items; p != NULL; p = p->next) {
831                GtkWidget *item_widget;
832
833                item_widget = GTK_WIDGET (p->data);
834                if (item_widget->parent != GTK_WIDGET (toolbar))
835                        continue;
836
837                if (GTK_WIDGET_VISIBLE (item_widget) && ! GTK_WIDGET_MAPPED (item_widget))
838                        gtk_widget_map (item_widget);
839        }
840
841        if (GTK_WIDGET_VISIBLE (priv->popup_item) && ! GTK_WIDGET_MAPPED (priv->popup_item))
842                gtk_widget_map (GTK_WIDGET (priv->popup_item));
843}
844
845static void
846impl_unmap (GtkWidget *widget)
847{
848        BonoboUIToolbar *toolbar;
849        BonoboUIToolbarPrivate *priv;
850        GList *p;
851
852        toolbar = BONOBO_UI_TOOLBAR (widget);
853        priv = toolbar->priv;
854
855        for (p = priv->items; p != NULL; p = p->next) {
856                GtkWidget *item_widget;
857
858                item_widget = GTK_WIDGET (p->data);
859                if (item_widget->parent != GTK_WIDGET (toolbar))
860                        continue;
861
862                if (GTK_WIDGET_VISIBLE (item_widget) && GTK_WIDGET_MAPPED (item_widget))
863                        gtk_widget_unmap (item_widget);
864        }
865
866        if (GTK_WIDGET_VISIBLE (priv->popup_item) && GTK_WIDGET_MAPPED (priv->popup_item))
867                gtk_widget_unmap (GTK_WIDGET (priv->popup_item));
868}
869
870static void
871impl_draw (GtkWidget *widget,
872           GdkRectangle *area)
873{
874        BonoboUIToolbar *toolbar;
875        BonoboUIToolbarPrivate *priv;
876        GdkRectangle item_area;
877        GList *p;
878
879        if (! GTK_WIDGET_DRAWABLE (widget))
880                return;
881
882        toolbar = BONOBO_UI_TOOLBAR (widget);
883        priv = toolbar->priv;
884
885        for (p = priv->items; p != NULL; p = p->next) {
886                GtkWidget *item_widget;
887
888                item_widget = GTK_WIDGET (p->data);
889                if (item_widget->parent != GTK_WIDGET (toolbar))
890                        continue;
891
892                if (gtk_widget_intersect (item_widget, area, &item_area))
893                        gtk_widget_draw (item_widget, &item_area);
894        }
895
896        if (gtk_widget_intersect (GTK_WIDGET (priv->popup_item), area, &item_area))
897                gtk_widget_draw (GTK_WIDGET (priv->popup_item), &item_area);
898}
899
900static int
901impl_expose_event (GtkWidget *widget,
902                   GdkEventExpose *event)
903{
904        BonoboUIToolbar *toolbar;
905        BonoboUIToolbarPrivate *priv;
906        GdkEventExpose item_event;
907        GList *p;
908
909        if (! GTK_WIDGET_DRAWABLE (widget))
910                return FALSE;
911
912        toolbar = BONOBO_UI_TOOLBAR (widget);
913        priv = toolbar->priv;
914
915        item_event = *event;
916
917        for (p = priv->items; p != NULL; p = p->next) {
918                GtkWidget *item_widget;
919
920                item_widget = GTK_WIDGET (p->data);
921                if (item_widget->parent != GTK_WIDGET (toolbar))
922                        continue;
923
924                if (! GTK_WIDGET_NO_WINDOW (item_widget))
925                        continue;
926
927                if (gtk_widget_intersect (item_widget, &event->area, &item_event.area))
928                        gtk_widget_event (item_widget, (GdkEvent *) &item_event);
929        }
930
931        if (gtk_widget_intersect (GTK_WIDGET (priv->popup_item), &event->area, &item_event.area))
932                gtk_widget_event (GTK_WIDGET (priv->popup_item), (GdkEvent *) &item_event);
933
934        return FALSE;
935}
936
937
938/* GtkContainer methods.  */
939
940static void
941impl_remove (GtkContainer *container,
942             GtkWidget    *child)
943{
944        BonoboUIToolbar *toolbar;
945        BonoboUIToolbarPrivate *priv;
946
947        toolbar = BONOBO_UI_TOOLBAR (container);
948        priv = toolbar->priv;
949
950        if (child == GTK_WIDGET (priv->popup_item))
951                priv->popup_item = NULL;
952
953        gtk_widget_unparent (child);
954
955        gtk_widget_queue_resize (GTK_WIDGET (container));
956}
957
958static void
959impl_forall (GtkContainer *container,
960             gboolean include_internals,
961             GtkCallback callback,
962             void *callback_data)
963{
964        BonoboUIToolbar *toolbar;
965        BonoboUIToolbarPrivate *priv;
966        GList *p;
967
968        toolbar = BONOBO_UI_TOOLBAR (container);
969        priv = toolbar->priv;
970
971        p = priv->items;
972        while (p != NULL) {
973                GtkWidget *child;
974                GList *pnext;
975
976                pnext = p->next;
977
978                child = GTK_WIDGET (p->data);
979                if (child->parent == GTK_WIDGET (toolbar))
980                        (* callback) (child, callback_data);
981
982                p = pnext;
983        }
984
985        if (priv->popup_item)
986                (* callback) (GTK_WIDGET (priv->popup_item),
987                              callback_data);
988}
989
990
991/* BonoboUIToolbar signals.  */
992
993static void
994impl_set_orientation (BonoboUIToolbar *toolbar,
995                      GtkOrientation orientation)
996{
997        BonoboUIToolbarPrivate *priv;
998        GList *p;
999
1000        priv = toolbar->priv;
1001
1002        if (orientation == priv->orientation)
1003                return;
1004
1005        priv->orientation = orientation;
1006
1007        for (p = priv->items; p != NULL; p = p->next) {
1008                BonoboUIToolbarItem *item;
1009
1010                item = BONOBO_UI_TOOLBAR_ITEM (p->data);
1011                set_attributes_on_child (item, orientation, priv->style);
1012        }
1013
1014        bonobo_ui_toolbar_item_set_orientation (
1015                BONOBO_UI_TOOLBAR_ITEM (priv->popup_item), orientation);
1016
1017        gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1018}
1019
1020static void
1021impl_style_changed (BonoboUIToolbar *toolbar)
1022{
1023        GList *p;
1024        BonoboUIToolbarStyle style;
1025        BonoboUIToolbarPrivate *priv;
1026
1027        priv = toolbar->priv;
1028
1029        style = (priv->orientation == GTK_ORIENTATION_HORIZONTAL) ? priv->hstyle : priv->vstyle;
1030
1031        if (style == priv->style)
1032                return;
1033
1034        priv->style = style;
1035
1036        for (p = priv->items; p != NULL; p = p->next) {
1037                BonoboUIToolbarItem *item;
1038
1039                item = BONOBO_UI_TOOLBAR_ITEM (p->data);
1040                set_attributes_on_child (item, priv->orientation, style);
1041        }
1042
1043        gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1044}
1045
1046static void
1047impl_get_arg (GtkObject *obj,
1048              GtkArg *arg,
1049              guint arg_id)
1050{
1051        BonoboUIToolbar *toolbar = BONOBO_UI_TOOLBAR (obj);
1052        BonoboUIToolbarPrivate *priv = toolbar->priv;
1053
1054        switch (arg_id) {
1055        case ARG_ORIENTATION:
1056                GTK_VALUE_UINT (*arg) = bonobo_ui_toolbar_get_orientation (toolbar);
1057                break;
1058        case ARG_IS_FLOATING:
1059                GTK_VALUE_BOOL (*arg) = priv->is_floating;
1060                break;
1061        case ARG_PREFERRED_WIDTH:
1062                update_sizes (toolbar);
1063                if (bonobo_ui_toolbar_get_orientation (toolbar) == GTK_ORIENTATION_HORIZONTAL)
1064                        GTK_VALUE_UINT (*arg) = priv->total_width;
1065                else
1066                        GTK_VALUE_UINT (*arg) = priv->max_width;
1067                break;
1068        case ARG_PREFERRED_HEIGHT:
1069                update_sizes (toolbar);
1070                if (bonobo_ui_toolbar_get_orientation (toolbar) == GTK_ORIENTATION_HORIZONTAL)
1071                        GTK_VALUE_UINT (*arg) = priv->max_height;
1072                else
1073                        GTK_VALUE_UINT (*arg) = priv->total_height;
1074                break;
1075        default:
1076                break;
1077        };
1078}
1079
1080static void
1081impl_set_arg (GtkObject *obj,
1082              GtkArg *arg,
1083              guint arg_id)
1084{
1085        BonoboUIToolbar *toolbar = BONOBO_UI_TOOLBAR (obj);
1086        BonoboUIToolbarPrivate *priv = toolbar->priv;
1087
1088        switch (arg_id) {
1089        case ARG_ORIENTATION:
1090                bonobo_ui_toolbar_set_orientation (toolbar, GTK_VALUE_UINT(*arg));
1091                break;
1092        case ARG_IS_FLOATING:
1093                priv->is_floating = GTK_VALUE_BOOL(*arg);
1094                break;
1095        default:
1096                break;
1097        };
1098}
1099
1100static void
1101class_init (BonoboUIToolbarClass *toolbar_class)
1102{
1103        GtkObjectClass *object_class;
1104        GtkWidgetClass *widget_class;
1105        GtkContainerClass *container_class;
1106
1107        object_class = GTK_OBJECT_CLASS (toolbar_class);
1108        object_class->destroy  = impl_destroy;
1109        object_class->finalize = impl_finalize;
1110        object_class->get_arg  = impl_get_arg;
1111        object_class->set_arg  = impl_set_arg;
1112
1113        widget_class = GTK_WIDGET_CLASS (toolbar_class);
1114        widget_class->size_request  = impl_size_request;
1115        widget_class->size_allocate = impl_size_allocate;
1116        widget_class->map           = impl_map;
1117        widget_class->unmap         = impl_unmap;
1118        widget_class->draw          = impl_draw;
1119        widget_class->expose_event  = impl_expose_event;
1120
1121        container_class = GTK_CONTAINER_CLASS (toolbar_class);
1122        container_class->remove = impl_remove;
1123        container_class->forall = impl_forall;
1124
1125        toolbar_class->set_orientation = impl_set_orientation;
1126        toolbar_class->style_changed   = impl_style_changed;
1127
1128        parent_class = gtk_type_class (gtk_container_get_type ());
1129
1130        gtk_object_add_arg_type("BonoboUIToolbar::orientation",
1131                                GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_ORIENTATION);
1132        gtk_object_add_arg_type("BonoboUIToolbar::is_floating",
1133                                GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_IS_FLOATING);
1134
1135        gtk_object_add_arg_type("BonoboUIToolbar::preferred_width",
1136                                GTK_TYPE_UINT, GTK_ARG_READABLE, ARG_PREFERRED_WIDTH);
1137        gtk_object_add_arg_type("BonoboUIToolbar::preferred_height",
1138                                GTK_TYPE_UINT, GTK_ARG_READABLE, ARG_PREFERRED_HEIGHT);
1139
1140        signals[SET_ORIENTATION]
1141                = gtk_signal_new ("set_orientation",
1142                                  GTK_RUN_LAST,
1143                                  object_class->type,
1144                                  GTK_SIGNAL_OFFSET (BonoboUIToolbarClass, set_orientation),
1145                                  gtk_marshal_NONE__INT,
1146                                  GTK_TYPE_NONE, 1,
1147                                  GTK_TYPE_INT);
1148
1149        signals[STYLE_CHANGED]
1150                = gtk_signal_new ("set_style",
1151                                  GTK_RUN_LAST,
1152                                  object_class->type,
1153                                  GTK_SIGNAL_OFFSET (BonoboUIToolbarClass, style_changed),
1154                                  gtk_marshal_NONE__NONE,
1155                                  GTK_TYPE_NONE, 0);
1156
1157        gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
1158}
1159
1160static void
1161init (BonoboUIToolbar *toolbar)
1162{
1163        BonoboUIToolbarPrivate *priv;
1164        BonoboUIToolbarStyle style;
1165
1166        GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
1167        GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
1168
1169        priv = g_new (BonoboUIToolbarPrivate, 1);
1170
1171        style = gnome_preferences_get_toolbar_labels ()
1172                ? BONOBO_UI_TOOLBAR_STYLE_ICONS_AND_TEXT
1173                : BONOBO_UI_TOOLBAR_STYLE_ICONS_ONLY;
1174
1175        priv->orientation                 = GTK_ORIENTATION_HORIZONTAL;
1176        priv->is_floating                 = FALSE;
1177        priv->style                       = style;
1178        priv->hstyle                      = style;
1179        priv->vstyle                      = style;
1180        priv->max_width                   = 0;
1181        priv->total_width                 = 0;
1182        priv->max_height                  = 0;
1183        priv->total_height                = 0;
1184        priv->popup_item                  = NULL;
1185        priv->items                       = NULL;
1186        priv->first_not_fitting_item      = NULL;
1187        priv->popup_window                = NULL;
1188        priv->popup_window_vbox           = NULL;
1189        priv->items_moved_to_popup_window = FALSE;
1190        priv->tooltips                    = gtk_tooltips_new ();
1191
1192        toolbar->priv = priv;
1193}
1194
1195
1196GtkType
1197bonobo_ui_toolbar_get_type (void)
1198{
1199        static GtkType type = 0;
1200
1201        if (type == 0) {
1202                static const GtkTypeInfo info = {
1203                        "BonoboUIToolbar",
1204                        sizeof (BonoboUIToolbar),
1205                        sizeof (BonoboUIToolbarClass),
1206                        (GtkClassInitFunc) class_init,
1207                        (GtkObjectInitFunc) init,
1208                        /* reserved_1 */ NULL,
1209                        /* reserved_2 */ NULL,
1210                        (GtkClassInitFunc) NULL,
1211                };
1212
1213                type = gtk_type_unique (PARENT_TYPE, &info);
1214        }
1215
1216        return type;
1217}
1218
1219void
1220bonobo_ui_toolbar_construct (BonoboUIToolbar *toolbar)
1221{
1222        BonoboUIToolbarPrivate *priv;
1223        GtkWidget *frame;
1224
1225        g_return_if_fail (toolbar != NULL);
1226        g_return_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar));
1227
1228        priv = toolbar->priv;
1229
1230        priv->popup_item = BONOBO_UI_TOOLBAR_ITEM (bonobo_ui_toolbar_popup_item_new ());
1231        bonobo_ui_toolbar_item_set_orientation (priv->popup_item, priv->orientation);
1232        parentize_widget (toolbar, GTK_WIDGET (priv->popup_item));
1233
1234        gtk_signal_connect (GTK_OBJECT (priv->popup_item), "toggled",
1235                            GTK_SIGNAL_FUNC (popup_item_toggled_cb), toolbar);
1236
1237        priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
1238        gtk_signal_connect (GTK_OBJECT (priv->popup_window), "button_release_event",
1239                            GTK_SIGNAL_FUNC (popup_window_button_release_cb), toolbar);
1240
1241        frame = gtk_frame_new (NULL);
1242        gtk_widget_show (frame);
1243        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
1244        gtk_container_add (GTK_CONTAINER (priv->popup_window), frame);
1245
1246        priv->popup_window_vbox = gtk_vbox_new (FALSE, 0);
1247        gtk_widget_show (priv->popup_window_vbox);
1248        gtk_container_add (GTK_CONTAINER (frame), priv->popup_window_vbox);
1249}
1250
1251GtkWidget *
1252bonobo_ui_toolbar_new (void)
1253{
1254        BonoboUIToolbar *toolbar;
1255
1256        toolbar = gtk_type_new (bonobo_ui_toolbar_get_type ());
1257
1258        bonobo_ui_toolbar_construct (toolbar);
1259
1260        return GTK_WIDGET (toolbar);
1261}
1262
1263
1264void
1265bonobo_ui_toolbar_set_orientation (BonoboUIToolbar *toolbar,
1266                                   GtkOrientation orientation)
1267{
1268        g_return_if_fail (toolbar != NULL);
1269        g_return_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar));
1270        g_return_if_fail (orientation == GTK_ORIENTATION_HORIZONTAL
1271                          || orientation == GTK_ORIENTATION_VERTICAL);
1272
1273        gtk_signal_emit (GTK_OBJECT (toolbar), signals[SET_ORIENTATION], orientation);
1274
1275        gtk_signal_emit (GTK_OBJECT (toolbar), signals[STYLE_CHANGED]);
1276}
1277
1278GtkOrientation
1279bonobo_ui_toolbar_get_orientation (BonoboUIToolbar *toolbar)
1280{
1281        BonoboUIToolbarPrivate *priv;
1282
1283        g_return_val_if_fail (toolbar != NULL, GTK_ORIENTATION_HORIZONTAL);
1284        g_return_val_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
1285
1286        priv = toolbar->priv;
1287
1288        return priv->orientation;
1289}
1290
1291
1292BonoboUIToolbarStyle
1293bonobo_ui_toolbar_get_style (BonoboUIToolbar *toolbar)
1294{
1295        BonoboUIToolbarPrivate *priv;
1296
1297        g_return_val_if_fail (toolbar != NULL, BONOBO_UI_TOOLBAR_STYLE_PRIORITY_TEXT);
1298        g_return_val_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar), BONOBO_UI_TOOLBAR_STYLE_PRIORITY_TEXT);
1299
1300        priv = toolbar->priv;
1301
1302        return priv->style;
1303}
1304
1305GtkTooltips *
1306bonobo_ui_toolbar_get_tooltips (BonoboUIToolbar *toolbar)
1307{
1308        BonoboUIToolbarPrivate *priv;
1309
1310        g_return_val_if_fail (toolbar != NULL, NULL);
1311        g_return_val_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar), NULL);
1312
1313        priv = toolbar->priv;
1314
1315        return priv->tooltips;
1316}
1317
1318
1319void
1320bonobo_ui_toolbar_insert (BonoboUIToolbar *toolbar,
1321                          BonoboUIToolbarItem *item,
1322                          int position)
1323{
1324        BonoboUIToolbarPrivate *priv;
1325
1326        g_return_if_fail (toolbar != NULL);
1327        g_return_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar));
1328        g_return_if_fail (item != NULL);
1329        g_return_if_fail (BONOBO_IS_UI_TOOLBAR_ITEM (item));
1330
1331        gtk_object_ref (GTK_OBJECT (item));
1332        gtk_object_sink (GTK_OBJECT (item));
1333
1334        priv = toolbar->priv;
1335
1336        /*
1337         *  This ugly hack is here since we might have unparented
1338         * a widget and then re-added it to the toolbar at a later
1339         * date, and un-parenting doesn't work quite properly yet.
1340         */
1341        if (!g_list_find (priv->items, item))
1342                priv->items = g_list_insert (priv->items, item, position);
1343
1344        gtk_signal_connect_while_alive (GTK_OBJECT (item), "destroy",
1345                                        GTK_SIGNAL_FUNC (item_destroy_cb), toolbar,
1346                                        GTK_OBJECT (toolbar));
1347        gtk_signal_connect_while_alive (GTK_OBJECT (item), "activate",
1348                                        GTK_SIGNAL_FUNC (item_activate_cb), toolbar,
1349                                        GTK_OBJECT (toolbar));
1350        gtk_signal_connect_while_alive (GTK_OBJECT (item), "set_want_label",
1351                                        GTK_SIGNAL_FUNC (item_set_want_label_cb), toolbar,
1352                                        GTK_OBJECT (toolbar));
1353
1354        set_attributes_on_child (item, priv->orientation, priv->style);
1355        parentize_widget (toolbar, GTK_WIDGET (item));
1356
1357        g_assert (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar));
1358
1359        gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1360}
1361
1362GList *
1363bonobo_ui_toolbar_get_children (BonoboUIToolbar *toolbar)
1364{
1365        GList *ret = NULL, *l;
1366
1367        g_return_val_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar), NULL);
1368
1369        for (l = toolbar->priv->items; l; l = l->next) {
1370                GtkWidget *item_widget;
1371
1372                item_widget = GTK_WIDGET (l->data);
1373                if (item_widget->parent != NULL) /* Unparented but still here */
1374                        ret = g_list_prepend (ret, item_widget);
1375        }
1376
1377        return g_list_reverse (ret);
1378}
1379
1380void
1381bonobo_ui_toolbar_set_hv_styles (BonoboUIToolbar      *toolbar,
1382                                 BonoboUIToolbarStyle  hstyle,
1383                                 BonoboUIToolbarStyle  vstyle)
1384{
1385        g_return_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar));
1386
1387        toolbar->priv->hstyle = hstyle;
1388        toolbar->priv->vstyle = vstyle;
1389
1390        gtk_signal_emit (GTK_OBJECT (toolbar), signals [STYLE_CHANGED]);
1391}
1392
1393void
1394bonobo_ui_toolbar_show_tooltips (BonoboUIToolbar *toolbar,
1395                                 gboolean         show_tips)
1396{
1397        g_return_if_fail (BONOBO_IS_UI_TOOLBAR (toolbar));
1398
1399        if (show_tips)
1400                gtk_tooltips_enable (toolbar->priv->tooltips);
1401        else
1402                gtk_tooltips_disable (toolbar->priv->tooltips);
1403}
Note: See TracBrowser for help on using the repository browser.