1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
4
* Copyright (C) 2003 Ettore Perazzoli,
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of version 2 of the GNU General Public
9
* License as published by the Free Software Foundation.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
16
* You should have received a copy of the GNU General Public
17
* License along with this program; if not, write to the
18
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
* Boston, MA 02111-1307, USA.
21
* Copied and adapted from ESidebar.[ch] from evolution
23
* Authors: Ettore Perazzoli <ettore@ximian.com>
24
* Naba Kumar <naba@gnome.org>
32
#include "gdl-switcher.h"
33
#include "gdl-tools.h"
34
#include "libgdlmarshal.h"
35
#include "libgdltypebuiltins.h"
38
#include <gtk/gtkhbox.h>
39
#include <gtk/gtkimage.h>
40
#include <gtk/gtklabel.h>
41
#include <gtk/gtktogglebutton.h>
44
#include <gconf/gconf-client.h>
45
#include <libgnome/gnome-gconf.h>
48
static void gdl_switcher_set_property (GObject *object,
52
static void gdl_switcher_get_property (GObject *object,
57
static void gdl_switcher_add_button (GdlSwitcher *switcher,
59
const gchar *tooltips,
60
const gchar *stock_id,
61
const GdkPixbuf *pixbuf_icon,
63
static void gdl_switcher_remove_button (GdlSwitcher *switcher, gint switcher_id);
64
static void gdl_switcher_select_page (GdlSwitcher *switcher, gint switcher_id);
65
static void gdl_switcher_select_button (GdlSwitcher *switcher, gint switcher_id);
66
static void gdl_switcher_set_show_buttons (GdlSwitcher *switcher, gboolean show);
67
static void gdl_switcher_set_style (GdlSwitcher *switcher,
68
GdlSwitcherStyle switcher_style);
69
static GdlSwitcherStyle gdl_switcher_get_style (GdlSwitcher *switcher);
77
GtkWidget *button_widget;
82
GtkTooltips *tooltips;
86
struct _GdlSwitcherPrivate {
87
GdlSwitcherStyle switcher_style;
88
GdlSwitcherStyle toolbar_style;
93
guint style_changed_id;
94
gint buttons_height_request;
98
GDL_CLASS_BOILERPLATE (GdlSwitcher, gdl_switcher, GtkNotebook, GTK_TYPE_NOTEBOOK)
100
#define INTERNAL_MODE(switcher) (switcher->priv->switcher_style == \
101
GDL_SWITCHER_STYLE_TOOLBAR ? switcher->priv->toolbar_style : \
102
switcher->priv->switcher_style)
107
/* Utility functions. */
110
button_new (GtkWidget *button_widget, GtkWidget *label, GtkWidget *icon,
111
GtkTooltips *tooltips, GtkWidget *arrow, GtkWidget *hbox, int id)
113
Button *button = g_new (Button, 1);
115
button->button_widget = button_widget;
116
button->label = label;
118
button->arrow = arrow;
120
button->tooltips = tooltips;
123
g_object_ref (button_widget);
124
g_object_ref (label);
126
g_object_ref (arrow);
128
g_object_ref (tooltips);
134
button_free (Button *button)
136
g_object_unref (button->button_widget);
137
g_object_unref (button->label);
138
g_object_unref (button->icon);
139
g_object_unref (button->hbox);
140
g_object_unref (button->tooltips);
145
gdl_switcher_get_page_id (GtkWidget *widget)
147
static gint switcher_id_count = 0;
149
switcher_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
151
if (switcher_id <= 0) {
152
switcher_id = ++switcher_id_count;
153
g_object_set_data (G_OBJECT (widget), "__switcher_id",
154
GINT_TO_POINTER (switcher_id));
160
update_buttons (GdlSwitcher *switcher, int new_selected_id)
164
switcher->priv->in_toggle = TRUE;
166
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
167
Button *button = p->data;
169
if (button->id == new_selected_id) {
170
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
171
(button->button_widget), TRUE);
172
gtk_widget_set_sensitive (button->arrow, TRUE);
174
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
175
(button->button_widget), FALSE);
176
gtk_widget_set_sensitive (button->arrow, FALSE);
180
switcher->priv->in_toggle = FALSE;
186
button_toggled_callback (GtkToggleButton *toggle_button,
187
GdlSwitcher *switcher)
190
gboolean is_active = FALSE;
193
if (switcher->priv->in_toggle)
196
switcher->priv->in_toggle = TRUE;
198
if (gtk_toggle_button_get_active (toggle_button))
201
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
202
Button *button = p->data;
204
if (button->button_widget != GTK_WIDGET (toggle_button)) {
205
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
206
(button->button_widget), FALSE);
207
gtk_widget_set_sensitive (button->arrow, FALSE);
209
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
210
(button->button_widget), TRUE);
211
gtk_widget_set_sensitive (button->arrow, TRUE);
216
switcher->priv->in_toggle = FALSE;
220
gdl_switcher_select_page (switcher, id);
224
/* Returns -1 if layout didn't happen because a resize request was queued */
226
layout_buttons (GdlSwitcher *switcher)
228
GtkRequisition client_requisition;
229
GtkAllocation *allocation = & GTK_WIDGET (switcher)->allocation;
230
GdlSwitcherStyle switcher_style;
232
int num_btns = g_slist_length (switcher->priv->buttons);
237
int max_btn_width = 0, max_btn_height = 0;
238
int optimal_layout_width = 0;
243
int last_buttons_height;
245
last_buttons_height = switcher->priv->buttons_height_request;
247
GDL_CALL_PARENT (GTK_WIDGET_CLASS, size_request,
248
(GTK_WIDGET (switcher), &client_requisition));
250
y = allocation->y + allocation->height - V_PADDING - 1;
255
switcher_style = INTERNAL_MODE (switcher);
256
icons_only = (switcher_style == GDL_SWITCHER_STYLE_ICON);
258
/* Figure out the max width and height */
259
optimal_layout_width = H_PADDING;
260
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
261
GtkRequisition requisition;
264
gtk_widget_size_request (GTK_WIDGET (button->button_widget),
266
optimal_layout_width += requisition.width + H_PADDING;
267
max_btn_height = MAX (max_btn_height, requisition.height);
268
max_btn_width = MAX (max_btn_width, requisition.width);
271
/* Figure out how many rows and columns we'll use. */
272
btns_per_row = allocation->width / (max_btn_width + H_PADDING);
274
/* If all the buttons could fit in the single row, have it so */
275
if (allocation->width >= optimal_layout_width)
277
btns_per_row = num_btns;
280
/* If using text buttons, we want to try to have a
281
* completely filled-in grid, but if we can't, we want
282
* the odd row to have just a single button.
284
while (num_btns % btns_per_row > 1)
288
rows_count = num_btns / btns_per_row;
289
if (num_btns % btns_per_row != 0)
292
/* Assign buttons to rows */
293
rows = g_new0 (GSList *, rows_count);
295
if (!icons_only && num_btns % btns_per_row != 0) {
296
button = switcher->priv->buttons->data;
297
rows [0] = g_slist_append (rows [0], button->button_widget);
299
p = switcher->priv->buttons->next;
300
row_number = p ? 1 : 0;
302
p = switcher->priv->buttons;
306
for (; p != NULL; p = p->next) {
309
if (g_slist_length (rows [row_number]) == btns_per_row)
312
rows [row_number] = g_slist_append (rows [row_number],
313
button->button_widget);
316
row_last = row_number;
318
/* If there are more than 1 row of buttons, save the current height
319
* requirement for subsequent size requests.
323
switcher->priv->buttons_height_request =
324
(row_last + 1) * (max_btn_height + V_PADDING) + 1;
325
} else { /* Otherwize clear it */
326
if (last_buttons_height >= 0) {
328
switcher->priv->buttons_height_request = -1;
332
/* If it turns out that we now require smaller height for the buttons
333
* than it was last time, make a resize request to ensure our
334
* size requisition is properly communicated to the parent (otherwise
335
* parent tend to keep assuming the older size).
337
if (last_buttons_height > switcher->priv->buttons_height_request)
339
gtk_widget_queue_resize (GTK_WIDGET (switcher));
343
/* Layout the buttons. */
344
for (i = row_last; i >= 0; i --) {
345
int len, extra_width;
349
/* Check for possible size over flow (taking into account client
352
if (y < (allocation->y + client_requisition.height)) {
353
/* We have an overflow: Insufficient allocation */
354
if (last_buttons_height < switcher->priv->buttons_height_request) {
355
/* Request for a new resize */
356
gtk_widget_queue_resize (GTK_WIDGET (switcher));
360
x = H_PADDING + allocation->x;
361
len = g_slist_length (rows[i]);
362
if (switcher_style == GDL_SWITCHER_STYLE_TEXT ||
363
switcher_style == GDL_SWITCHER_STYLE_BOTH)
364
extra_width = (allocation->width - (len * max_btn_width )
365
- (len * H_PADDING)) / len;
368
for (p = rows [i]; p != NULL; p = p->next) {
369
GtkAllocation child_allocation;
371
child_allocation.x = x;
372
child_allocation.y = y;
373
if (rows_count == 1 && row_number == 0)
375
GtkRequisition child_requisition;
376
gtk_widget_size_request (GTK_WIDGET (p->data),
378
child_allocation.width = child_requisition.width;
382
child_allocation.width = max_btn_width + extra_width;
384
child_allocation.height = max_btn_height;
386
gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation);
388
x += child_allocation.width + H_PADDING;
394
for (i = 0; i <= row_last; i ++)
395
g_slist_free (rows [i]);
402
do_layout (GdlSwitcher *switcher)
404
GtkAllocation *allocation = & GTK_WIDGET (switcher)->allocation;
405
GtkAllocation child_allocation;
408
if (switcher->priv->show) {
409
y = layout_buttons (switcher);
410
if (y < 0) /* Layout did not happen and a resize was requested */
414
y = allocation->y + allocation->height;
416
/* Place the parent widget. */
417
child_allocation.x = allocation->x;
418
child_allocation.y = allocation->y;
419
child_allocation.width = allocation->width;
420
child_allocation.height = y - allocation->y;
422
GDL_CALL_PARENT (GTK_WIDGET_CLASS, size_allocate,
423
(GTK_WIDGET (switcher), &child_allocation));
426
/* GtkContainer methods. */
429
gdl_switcher_forall (GtkContainer *container, gboolean include_internals,
430
GtkCallback callback, void *callback_data)
432
GdlSwitcher *switcher =
433
GDL_SWITCHER (container);
436
GDL_CALL_PARENT (GTK_CONTAINER_CLASS, forall,
437
(GTK_CONTAINER (switcher), include_internals,
438
callback, callback_data));
439
if (include_internals) {
440
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
441
GtkWidget *widget = ((Button *) p->data)->button_widget;
442
(* callback) (widget, callback_data);
448
gdl_switcher_remove (GtkContainer *container, GtkWidget *widget)
451
GdlSwitcher *switcher =
452
GDL_SWITCHER (container);
455
switcher_id = gdl_switcher_get_page_id (widget);
456
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
457
Button *b = (Button *) p->data;
459
if (b->id == switcher_id) {
460
gtk_widget_unparent (b->button_widget);
461
switcher->priv->buttons =
462
g_slist_remove_link (switcher->priv->buttons, p);
464
gtk_widget_queue_resize (GTK_WIDGET (switcher));
468
GDL_CALL_PARENT (GTK_CONTAINER_CLASS, remove,
469
(GTK_CONTAINER (switcher), widget));
472
/* GtkWidget methods. */
475
gdl_switcher_size_request (GtkWidget *widget, GtkRequisition *requisition)
477
GdlSwitcher *switcher = GDL_SWITCHER (widget);
479
gint button_height = 0;
481
GDL_CALL_PARENT (GTK_WIDGET_CLASS, size_request,
482
(GTK_WIDGET (switcher), requisition));
484
if (!switcher->priv->show)
487
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
489
Button *button = p->data;
490
GtkRequisition button_requisition;
492
gtk_widget_size_request (button->button_widget, &button_requisition);
493
button_width = button_requisition.width + 2 * H_PADDING;
494
requisition->width = MAX (requisition->width, button_width);
495
button_height = MAX (button_height,
496
button_requisition.height + 2 * V_PADDING);
499
if (switcher->priv->buttons_height_request > 0) {
500
requisition->height += switcher->priv->buttons_height_request;
502
requisition->height += button_height + V_PADDING;
507
gdl_switcher_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
509
widget->allocation = *allocation;
510
do_layout (GDL_SWITCHER (widget));
514
gdl_switcher_expose (GtkWidget *widget, GdkEventExpose *event)
517
GdlSwitcher *switcher = GDL_SWITCHER (widget);
518
if (switcher->priv->show) {
519
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
520
GtkWidget *button = ((Button *) p->data)->button_widget;
521
gtk_container_propagate_expose (GTK_CONTAINER (widget),
525
GDL_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS, expose_event,
526
(widget, event), FALSE);
530
gdl_switcher_map (GtkWidget *widget)
533
GdlSwitcher *switcher = GDL_SWITCHER (widget);
535
if (switcher->priv->show) {
536
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
537
GtkWidget *button = ((Button *) p->data)->button_widget;
538
gtk_widget_map (button);
541
GDL_CALL_PARENT (GTK_WIDGET_CLASS, map, (widget));
544
/* GObject methods. */
547
gdl_switcher_set_property (GObject *object,
552
GdlSwitcher *switcher = GDL_SWITCHER (object);
555
case PROP_SWITCHER_STYLE:
556
gdl_switcher_set_style (switcher, g_value_get_enum (value));
559
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
565
gdl_switcher_get_property (GObject *object,
570
GdlSwitcher *switcher = GDL_SWITCHER (object);
573
case PROP_SWITCHER_STYLE:
574
g_value_set_enum (value, gdl_switcher_get_style (switcher));
577
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
583
gdl_switcher_dispose (GObject *object)
585
GdlSwitcherPrivate *priv = GDL_SWITCHER (object)->priv;
588
GConfClient *gconf_client = gconf_client_get_default ();
590
if (priv->style_changed_id) {
591
gconf_client_notify_remove (gconf_client, priv->style_changed_id);
592
priv->style_changed_id = 0;
594
g_object_unref (gconf_client);
597
g_slist_foreach (priv->buttons, (GFunc) button_free, NULL);
598
g_slist_free (priv->buttons);
599
priv->buttons = NULL;
601
GDL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
605
gdl_switcher_finalize (GObject *object)
607
GdlSwitcherPrivate *priv = GDL_SWITCHER (object)->priv;
611
GDL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
614
/* Signal handlers */
617
gdl_switcher_notify_cb (GObject *g_object, GParamSpec *pspec,
618
GdlSwitcher *switcher)
621
g_return_if_fail (switcher != NULL && GDL_IS_SWITCHER (switcher));
622
show_tabs = gtk_notebook_get_show_tabs (GTK_NOTEBOOK (switcher));
623
gdl_switcher_set_show_buttons (switcher, !show_tabs);
627
gdl_switcher_switch_page_cb (GtkNotebook *nb, GtkNotebookPage *page,
628
gint page_num, GdlSwitcher *switcher)
630
GtkWidget *page_widget;
634
/* Change switcher button */
635
page_widget = gtk_notebook_get_nth_page (nb, page_num);
636
switcher_id = gdl_switcher_get_page_id (page_widget);
637
gdl_switcher_select_button (GDL_SWITCHER (switcher), switcher_id);
641
gdl_switcher_page_added_cb (GtkNotebook *nb, GtkWidget *page,
642
gint page_num, GdlSwitcher *switcher)
646
switcher_id = gdl_switcher_get_page_id (page);
648
gdl_switcher_add_button (GDL_SWITCHER (switcher), NULL, NULL, NULL, NULL,
650
gdl_switcher_select_button (GDL_SWITCHER (switcher), switcher_id);
654
gdl_switcher_select_page (GdlSwitcher *switcher, gint id)
656
GList *children, *node;
657
children = gtk_container_get_children (GTK_CONTAINER (switcher));
662
switcher_id = gdl_switcher_get_page_id (GTK_WIDGET (node->data));
663
if (switcher_id == id)
666
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (switcher),
667
GTK_WIDGET (node->data));
668
g_signal_handlers_block_by_func (switcher,
669
gdl_switcher_switch_page_cb,
671
gtk_notebook_set_current_page (GTK_NOTEBOOK (switcher), page_num);
672
g_signal_handlers_unblock_by_func (switcher,
673
gdl_switcher_switch_page_cb,
677
node = g_list_next (node);
679
g_list_free (children);
682
/* Initialization. */
685
gdl_switcher_class_init (GdlSwitcherClass *klass)
687
GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass);
688
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
689
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
690
GObjectClass *object_class = G_OBJECT_CLASS (klass);
692
container_class->forall = gdl_switcher_forall;
693
container_class->remove = gdl_switcher_remove;
695
widget_class->size_request = gdl_switcher_size_request;
696
widget_class->size_allocate = gdl_switcher_size_allocate;
697
widget_class->expose_event = gdl_switcher_expose;
698
widget_class->map = gdl_switcher_map;
700
object_class->dispose = gdl_switcher_dispose;
701
object_class->finalize = gdl_switcher_finalize;
702
object_class->set_property = gdl_switcher_set_property;
703
object_class->get_property = gdl_switcher_get_property;
705
g_object_class_install_property (
706
object_class, PROP_SWITCHER_STYLE,
707
g_param_spec_enum ("switcher-style", _("Switcher Style"),
708
_("Switcher buttons style"),
709
GDL_TYPE_SWITCHER_STYLE,
710
GDL_SWITCHER_STYLE_BOTH,
715
gdl_switcher_instance_init (GdlSwitcher *switcher)
717
GdlSwitcherPrivate *priv;
719
GTK_WIDGET_SET_FLAGS (switcher, GTK_NO_WINDOW);
721
priv = g_new0 (GdlSwitcherPrivate, 1);
722
switcher->priv = priv;
725
priv->buttons_height_request = -1;
727
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (switcher), GTK_POS_BOTTOM);
728
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (switcher), FALSE);
729
gtk_notebook_set_show_border (GTK_NOTEBOOK (switcher), FALSE);
730
gdl_switcher_set_style (switcher, GDL_SWITCHER_STYLE_BOTH);
732
/* notebook signals */
733
g_signal_connect (switcher, "switch-page",
734
G_CALLBACK (gdl_switcher_switch_page_cb), switcher);
735
g_signal_connect (switcher, "page-added",
736
G_CALLBACK (gdl_switcher_page_added_cb), switcher);
737
g_signal_connect (switcher, "notify::show-tabs",
738
G_CALLBACK (gdl_switcher_notify_cb), switcher);
742
gdl_switcher_new (void)
744
GdlSwitcher *switcher = g_object_new (gdl_switcher_get_type (), NULL);
745
return GTK_WIDGET (switcher);
749
gdl_switcher_add_button (GdlSwitcher *switcher, const gchar *label,
750
const gchar *tooltips, const gchar *stock_id,
751
const GdkPixbuf *pixbuf_icon, gint switcher_id)
753
GtkWidget *button_widget;
755
GtkWidget *icon_widget;
756
GtkWidget *label_widget;
758
GtkTooltips *button_tooltips;
760
button_widget = gtk_toggle_button_new ();
761
if (switcher->priv->show)
762
gtk_widget_show (button_widget);
763
g_signal_connect (button_widget, "toggled",
764
G_CALLBACK (button_toggled_callback),
766
hbox = gtk_hbox_new (FALSE, 3);
767
gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
768
gtk_container_add (GTK_CONTAINER (button_widget), hbox);
769
gtk_widget_show (hbox);
772
icon_widget = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
773
else if (pixbuf_icon)
774
icon_widget = gtk_image_new_from_pixbuf (pixbuf_icon);
776
icon_widget = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_BUTTON);
778
gtk_widget_show (icon_widget);
781
gchar *text = g_strdup_printf ("Item %d", switcher_id);
782
label_widget = gtk_label_new (text);
785
label_widget = gtk_label_new (label);
787
gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
788
gtk_widget_show (label_widget);
789
button_tooltips = gtk_tooltips_new();
790
gtk_tooltips_set_tip (GTK_TOOLTIPS (button_tooltips), button_widget,
793
switch (INTERNAL_MODE (switcher)) {
794
case GDL_SWITCHER_STYLE_TEXT:
795
gtk_box_pack_start (GTK_BOX (hbox), label_widget, TRUE, TRUE, 0);
796
gtk_tooltips_disable (button_tooltips);
798
case GDL_SWITCHER_STYLE_ICON:
799
gtk_box_pack_start (GTK_BOX (hbox), icon_widget, TRUE, TRUE, 0);
800
gtk_tooltips_enable (button_tooltips);
802
case GDL_SWITCHER_STYLE_BOTH:
804
gtk_box_pack_start (GTK_BOX (hbox), icon_widget, FALSE, TRUE, 0);
805
gtk_box_pack_start (GTK_BOX (hbox), label_widget, TRUE, TRUE, 0);
806
gtk_tooltips_disable (button_tooltips);
809
arrow = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_NONE);
810
gtk_widget_show (arrow);
811
gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
813
switcher->priv->buttons =
814
g_slist_append (switcher->priv->buttons,
815
button_new (button_widget, label_widget,
816
icon_widget, button_tooltips,
817
arrow, hbox, switcher_id));
818
gtk_widget_set_parent (button_widget, GTK_WIDGET (switcher));
820
gtk_widget_queue_resize (GTK_WIDGET (switcher));
824
gdl_switcher_remove_button (GdlSwitcher *switcher, gint switcher_id)
828
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
829
Button *button = p->data;
831
if (button->id == switcher_id)
833
gtk_container_remove (GTK_CONTAINER (switcher),
834
button->button_widget);
838
gtk_widget_queue_resize (GTK_WIDGET (switcher));
842
gdl_switcher_select_button (GdlSwitcher *switcher, gint switcher_id)
844
update_buttons (switcher, switcher_id);
846
/* Select the notebook page associated with this button */
847
gdl_switcher_select_page (switcher, switcher_id);
851
gdl_switcher_insert_page (GdlSwitcher *switcher, GtkWidget *page,
852
GtkWidget *tab_widget, const gchar *label,
853
const gchar *tooltips, const gchar *stock_id,
854
const GdkPixbuf *pixbuf_icon, gint position)
858
g_signal_handlers_block_by_func (switcher,
859
gdl_switcher_page_added_cb,
863
tab_widget = gtk_label_new (label);
864
gtk_widget_show (tab_widget);
866
switcher_id = gdl_switcher_get_page_id (page);
867
gdl_switcher_add_button (switcher, label, tooltips, stock_id, pixbuf_icon, switcher_id);
868
ret_position = gtk_notebook_insert_page (GTK_NOTEBOOK (switcher), page,
869
tab_widget, position);
870
g_signal_handlers_unblock_by_func (switcher,
871
gdl_switcher_page_added_cb,
877
set_switcher_style_internal (GdlSwitcher *switcher,
878
GdlSwitcherStyle switcher_style )
882
if (switcher_style == GDL_SWITCHER_STYLE_TABS &&
883
switcher->priv->show == FALSE)
886
if (switcher_style == GDL_SWITCHER_STYLE_TABS)
888
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (switcher), TRUE);
892
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (switcher), FALSE);
894
if (switcher_style == INTERNAL_MODE (switcher))
897
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
898
Button *button = p->data;
900
gtk_container_remove (GTK_CONTAINER (button->hbox), button->arrow);
901
switch (switcher_style) {
902
case GDL_SWITCHER_STYLE_TEXT:
903
gtk_container_remove (GTK_CONTAINER (button->hbox), button->icon);
904
if (INTERNAL_MODE (switcher)
905
== GDL_SWITCHER_STYLE_ICON) {
906
gtk_box_pack_start (GTK_BOX (button->hbox), button->label,
908
gtk_widget_show (button->label);
909
gtk_tooltips_disable (button->tooltips);
912
case GDL_SWITCHER_STYLE_ICON:
913
gtk_container_remove(GTK_CONTAINER (button->hbox), button->label);
914
if (INTERNAL_MODE (switcher)
915
== GDL_SWITCHER_STYLE_TEXT) {
916
gtk_box_pack_start (GTK_BOX (button->hbox), button->icon,
918
gtk_widget_show (button->icon);
920
gtk_container_child_set (GTK_CONTAINER (button->hbox),
921
button->icon, "expand", TRUE, NULL);
922
gtk_tooltips_enable (button->tooltips);
924
case GDL_SWITCHER_STYLE_BOTH:
925
if (INTERNAL_MODE (switcher)
926
== GDL_SWITCHER_STYLE_TEXT) {
927
gtk_container_remove (GTK_CONTAINER (button->hbox),
929
gtk_box_pack_start (GTK_BOX (button->hbox), button->icon,
931
gtk_widget_show (button->icon);
933
gtk_container_child_set (GTK_CONTAINER (button->hbox),
934
button->icon, "expand", FALSE, NULL);
937
gtk_tooltips_disable (button->tooltips);
938
gtk_box_pack_start (GTK_BOX (button->hbox), button->label, TRUE,
940
gtk_widget_show (button->label);
945
gtk_box_pack_start (GTK_BOX (button->hbox), button->arrow, FALSE,
951
static GConfEnumStringPair toolbar_styles[] = {
952
{ GDL_SWITCHER_STYLE_TEXT, "text" },
953
{ GDL_SWITCHER_STYLE_ICON, "icons" },
954
{ GDL_SWITCHER_STYLE_BOTH, "both" },
955
{ GDL_SWITCHER_STYLE_BOTH, "both-horiz" },
956
{ GDL_SWITCHER_STYLE_BOTH, "both_horiz" },
961
style_changed_notify (GConfClient *gconf, guint id, GConfEntry *entry,
964
GdlSwitcher *switcher = data;
968
val = gconf_client_get_string (gconf,
969
"/desktop/gnome/interface/toolbar_style",
971
if (val == NULL || !gconf_string_to_enum (toolbar_styles, val,
973
switcher_style = GDL_SWITCHER_STYLE_BOTH;
976
set_switcher_style_internal (GDL_SWITCHER (switcher), switcher_style);
977
switcher->priv->toolbar_style = switcher_style;
979
gtk_widget_queue_resize (GTK_WIDGET (switcher));
983
gdl_switcher_set_style (GdlSwitcher *switcher, GdlSwitcherStyle switcher_style)
985
GConfClient *gconf_client = gconf_client_get_default ();
987
if (switcher_style == GDL_SWITCHER_STYLE_TABS &&
988
switcher->priv->show == FALSE)
991
if (switcher->priv->switcher_style == switcher_style &&
992
switcher->priv->show == TRUE)
995
if (switcher->priv->switcher_style == GDL_SWITCHER_STYLE_TOOLBAR) {
996
if (switcher->priv->style_changed_id) {
997
gconf_client_notify_remove (gconf_client,
998
switcher->priv->style_changed_id);
999
switcher->priv->style_changed_id = 0;
1003
if (switcher_style != GDL_SWITCHER_STYLE_TOOLBAR) {
1004
set_switcher_style_internal (switcher, switcher_style);
1006
gtk_widget_queue_resize (GTK_WIDGET (switcher));
1008
/* This is a little bit tricky, toolbar style is more
1009
* of a meta-style where the actual style is dictated by
1010
* the gnome toolbar setting, so that is why we have
1011
* the is_toolbar_style bool - it tracks the toolbar
1012
* style while the switcher_style member is the actual look and
1014
switcher->priv->style_changed_id =
1015
gconf_client_notify_add (gconf_client,
1016
"/desktop/gnome/interface/toolbar_style",
1017
style_changed_notify, switcher,
1019
style_changed_notify (gconf_client, 0, NULL, switcher);
1022
g_object_unref (gconf_client);
1024
if (switcher_style != GDL_SWITCHER_STYLE_TABS)
1025
switcher->priv->switcher_style = switcher_style;
1028
#else /* HAVE_GNOME */
1031
gdl_switcher_set_style (GdlSwitcher *switcher, GdlSwitcherStyle switcher_style)
1033
if (switcher_style == GDL_SWITCHER_STYLE_TABS &&
1034
switcher->priv->show == FALSE)
1037
if (switcher->priv->switcher_style == switcher_style &&
1038
switcher->priv->show == TRUE)
1041
set_switcher_style_internal (switcher,
1043
GDL_SWITCHER_STYLE_TOOLBAR)?
1044
GDL_SWITCHER_STYLE_BOTH : switcher_style));
1045
gtk_widget_queue_resize (GTK_WIDGET (switcher));
1047
if (switcher_style != GDL_SWITCHER_STYLE_TABS)
1048
switcher->priv->switcher_style = switcher_style;
1051
#endif /* HAVE_GNOME */
1054
gdl_switcher_set_show_buttons (GdlSwitcher *switcher, gboolean show)
1058
if (switcher->priv->show == show)
1061
for (p = switcher->priv->buttons; p != NULL; p = p->next) {
1062
Button *button = p->data;
1065
gtk_widget_show (button->button_widget);
1067
gtk_widget_hide (button->button_widget);
1070
switcher->priv->show = show;
1072
gtk_widget_queue_resize (GTK_WIDGET (switcher));
1075
static GdlSwitcherStyle
1076
gdl_switcher_get_style (GdlSwitcher *switcher)
1078
if (!switcher->priv->show)
1079
return GDL_SWITCHER_STYLE_TABS;
1080
return switcher->priv->switcher_style;