Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
e-shell-switcher.c:130:37 | clang-analyzer | Access to field 'data' results in a dereference of a null pointer (loaded from field 'proxies') | ||
e-shell-switcher.c:130:37 | clang-analyzer | Access to field 'data' results in a dereference of a null pointer (loaded from field 'proxies') |
1 /*
2 * e-shell-switcher.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 /**
23 * SECTION: e-shell-switcher
24 * @short_description: buttons for switching views
25 * @include: shell/e-shell-switcher.h
26 **/
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "e-shell-switcher.h"
33
34 #include <glib/gi18n.h>
35 #include <libebackend/libebackend.h>
36
37 #define E_SHELL_SWITCHER_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE \
39 ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherPrivate))
40
41 #define E_SHELL_SWITCHER_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE \
43 ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherPrivate))
44
45 #define H_PADDING 6
46 #define V_PADDING 6
47
48 struct _EShellSwitcherPrivate {
49 GList *proxies;
50 gboolean style_set;
51 GtkToolbarStyle style;
52 GtkSettings *settings;
53 gulong settings_handler_id;
54 gboolean toolbar_visible;
55 };
56
57 enum {
58 PROP_0,
59 PROP_TOOLBAR_STYLE,
60 PROP_TOOLBAR_VISIBLE
61 };
62
63 enum {
64 STYLE_CHANGED,
65 LAST_SIGNAL
66 };
67
68 static guint signals[LAST_SIGNAL];
69
70 /* Forward Declarations */
71 static void shell_switcher_tool_shell_iface_init (GtkToolShellIface *iface);
72
73 G_DEFINE_TYPE_WITH_CODE (
74 EShellSwitcher,
75 e_shell_switcher,
76 GTK_TYPE_BIN,
77 G_IMPLEMENT_INTERFACE (
78 E_TYPE_EXTENSIBLE, NULL)
79 G_IMPLEMENT_INTERFACE (
80 GTK_TYPE_TOOL_SHELL,
81 shell_switcher_tool_shell_iface_init))
82
83 static gint
84 shell_switcher_layout_actions (EShellSwitcher *switcher)
85 {
86 GtkAllocation allocation;
87 gint num_btns = g_list_length (switcher->priv->proxies), btns_per_row;
88 GList **rows, *p;
89 gboolean icons_only;
90 gint row_number;
91 gint max_width = 0;
92 gint max_height = 0;
93 gint row_last;
94 gint x, y;
95 gint i;
96
97 gtk_widget_get_allocation (GTK_WIDGET (switcher), &allocation);
98
99 y = allocation.y + allocation.height;
100
101 if (num_btns == 0)
102 return allocation.height;
103
104 icons_only = (switcher->priv->style == GTK_TOOLBAR_ICONS);
105
106 /* Figure out the max width and height. */
107 for (p = switcher->priv->proxies; p != NULL; p = p->next) {
108 GtkWidget *widget = p->data;
109 GtkRequisition requisition;
110
111 gtk_widget_get_preferred_size (widget, &requisition, NULL);
112 max_height = MAX (max_height, requisition.height);
113 max_width = MAX (max_width, requisition.width);
114 }
115
116 /* Figure out how many rows and columns we'll use. */
117 btns_per_row = MAX (1, allocation.width / (max_width + H_PADDING));
118 if (!icons_only) {
119 /* If using text buttons, we want to try to have a
120 * completely filled-in grid, but if we can't, we want
121 * the odd row to have just a single button. */
122 while (btns_per_row > 0 && num_btns % btns_per_row > 1)
123 btns_per_row--;
124 }
125
126 /* Assign buttons to rows. */
127 rows = g_new0 (GList *, num_btns / btns_per_row + 1);
128
129 if (!icons_only && num_btns % btns_per_row != 0) {
130 rows[0] = g_list_append (rows[0], switcher->priv->proxies->data);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
131
132 p = switcher->priv->proxies->next;
133 row_number = p ? 1 : 0;
134 } else {
135 p = switcher->priv->proxies;
136 row_number = 0;
137 }
138
139 for (; p != NULL; p = p->next) {
140 GtkWidget *widget = p->data;
141
142 if (g_list_length (rows[row_number]) == btns_per_row)
143 row_number++;
144
145 rows[row_number] = g_list_append (rows[row_number], widget);
146 }
147
148 row_last = row_number;
149
150 /* Layout the buttons. */
151 for (i = row_last; i >= 0; i--) {
152 gint len, extra_width;
153
154 x = H_PADDING + allocation.x;
155 y -= max_height;
156 len = g_list_length (rows[i]);
157 if (!icons_only)
158 extra_width =
159 (allocation.width - (len * max_width) -
160 (len * H_PADDING)) / len;
161 else
162 extra_width = 0;
163 for (p = rows[i]; p != NULL; p = p->next) {
164 GtkAllocation child_allocation;
165
166 child_allocation.x = x;
167 child_allocation.y = y;
168 child_allocation.width = max_width + extra_width;
169 child_allocation.height = max_height;
170
171 gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation);
172
173 x += child_allocation.width + H_PADDING;
174 }
175
176 y -= V_PADDING;
177 }
178
179 for (i = 0; i <= row_last; i++)
180 g_list_free (rows[i]);
181 g_free (rows);
182
183 return y - allocation.y;
184 }
185
186 static void
187 shell_switcher_toolbar_style_changed_cb (EShellSwitcher *switcher)
188 {
189 if (!switcher->priv->style_set) {
190 switcher->priv->style_set = TRUE;
191 e_shell_switcher_unset_style (switcher);
192 }
193 }
194
195 static void
196 shell_switcher_set_property (GObject *object,
197 guint property_id,
198 const GValue *value,
199 GParamSpec *pspec)
200 {
201 switch (property_id) {
202 case PROP_TOOLBAR_STYLE:
203 e_shell_switcher_set_style (
204 E_SHELL_SWITCHER (object),
205 g_value_get_enum (value));
206 return;
207
208 case PROP_TOOLBAR_VISIBLE:
209 e_shell_switcher_set_visible (
210 E_SHELL_SWITCHER (object),
211 g_value_get_boolean (value));
212 return;
213 }
214
215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
216 }
217
218 static void
219 shell_switcher_get_property (GObject *object,
220 guint property_id,
221 GValue *value,
222 GParamSpec *pspec)
223 {
224 switch (property_id) {
225 case PROP_TOOLBAR_STYLE:
226 g_value_set_enum (
227 value, e_shell_switcher_get_style (
228 E_SHELL_SWITCHER (object)));
229 return;
230
231 case PROP_TOOLBAR_VISIBLE:
232 g_value_set_boolean (
233 value, e_shell_switcher_get_visible (
234 E_SHELL_SWITCHER (object)));
235 return;
236 }
237
238 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
239 }
240
241 static void
242 shell_switcher_dispose (GObject *object)
243 {
244 EShellSwitcherPrivate *priv;
245
246 priv = E_SHELL_SWITCHER_GET_PRIVATE (object);
247
248 while (priv->proxies != NULL) {
249 GtkWidget *widget = priv->proxies->data;
250 gtk_container_remove (GTK_CONTAINER (object), widget);
251 }
252
253 /* Chain up to parent's dispose() method. */
254 G_OBJECT_CLASS (e_shell_switcher_parent_class)->dispose (object);
255 }
256
257 static void
258 shell_switcher_get_preferred_width (GtkWidget *widget,
259 gint *minimum,
260 gint *natural)
261 {
262 EShellSwitcherPrivate *priv;
263 GtkWidget *child;
264 GList *iter;
265
266 priv = E_SHELL_SWITCHER_GET_PRIVATE (widget);
267
268 *minimum = *natural = 0;
269
270 child = gtk_bin_get_child (GTK_BIN (widget));
271 if (child != NULL)
272 gtk_widget_get_preferred_width (child, minimum, natural);
273
274 if (!priv->toolbar_visible)
275 return;
276
277 for (iter = priv->proxies; iter != NULL; iter = iter->next) {
278 GtkWidget *widget_proxy = iter->data;
279 gint child_min, child_nat;
280
281 gtk_widget_get_preferred_width (
282 widget_proxy, &child_min, &child_nat);
283
284 child_min += H_PADDING;
285 child_nat += H_PADDING;
286
287 *minimum = MAX (*minimum, child_min);
288 *natural = MAX (*natural, child_nat);
289 }
290 }
291
292 static void
293 shell_switcher_get_preferred_height (GtkWidget *widget,
294 gint *minimum,
295 gint *natural)
296 {
297 EShellSwitcherPrivate *priv;
298 GtkWidget *child;
299 GList *iter;
300
301 priv = E_SHELL_SWITCHER_GET_PRIVATE (widget);
302
303 *minimum = *natural = 0;
304
305 child = gtk_bin_get_child (GTK_BIN (widget));
306 if (child != NULL)
307 gtk_widget_get_preferred_height (child, minimum, natural);
308
309 if (!priv->toolbar_visible)
310 return;
311
312 for (iter = priv->proxies; iter != NULL; iter = iter->next) {
313 GtkWidget *widget = iter->data;
314 gint child_min, child_nat;
315
316 gtk_widget_get_preferred_height (
317 widget, &child_min, &child_nat);
318
319 child_min += V_PADDING;
320 child_nat += V_PADDING;
321
322 *minimum += child_min;
323 *natural += child_nat;
324 }
325 }
326
327 static void
328 shell_switcher_size_allocate (GtkWidget *widget,
329 GtkAllocation *allocation)
330 {
331 EShellSwitcher *switcher;
332 GtkAllocation child_allocation;
333 GtkWidget *child;
334 gint height;
335
336 switcher = E_SHELL_SWITCHER (widget);
337
338 gtk_widget_set_allocation (widget, allocation);
339
340 if (switcher->priv->toolbar_visible)
341 height = shell_switcher_layout_actions (switcher);
342 else
343 height = allocation->height;
344
345 child_allocation.x = allocation->x;
346 child_allocation.y = allocation->y;
347 child_allocation.width = allocation->width;
348 child_allocation.height = height;
349
350 child = gtk_bin_get_child (GTK_BIN (widget));
351 if (child != NULL)
352 gtk_widget_size_allocate (child, &child_allocation);
353 }
354
355 static void
356 shell_switcher_screen_changed (GtkWidget *widget,
357 GdkScreen *previous_screen)
358 {
359 EShellSwitcherPrivate *priv;
360 GtkSettings *settings;
361
362 priv = E_SHELL_SWITCHER_GET_PRIVATE (widget);
363
364 if (gtk_widget_has_screen (widget))
365 settings = gtk_widget_get_settings (widget);
366 else
367 settings = NULL;
368
369 if (settings == priv->settings)
370 return;
371
372 if (priv->settings != NULL) {
373 g_signal_handler_disconnect (
374 priv->settings, priv->settings_handler_id);
375 g_object_unref (priv->settings);
376 }
377
378 if (settings != NULL) {
379 priv->settings = g_object_ref (settings);
380 priv->settings_handler_id = g_signal_connect_swapped (
381 settings, "notify::gtk-toolbar-style",
382 G_CALLBACK (shell_switcher_toolbar_style_changed_cb),
383 widget);
384 } else
385 priv->settings = NULL;
386
387 shell_switcher_toolbar_style_changed_cb (E_SHELL_SWITCHER (widget));
388 }
389
390 static void
391 shell_switcher_remove (GtkContainer *container,
392 GtkWidget *widget)
393 {
394 EShellSwitcherPrivate *priv;
395 GList *link;
396
397 priv = E_SHELL_SWITCHER_GET_PRIVATE (container);
398
399 /* Look in the internal widgets first. */
400
401 link = g_list_find (priv->proxies, widget);
402 if (link != NULL) {
403 GtkWidget *widget = link->data;
404
405 gtk_widget_unparent (widget);
406 priv->proxies = g_list_delete_link (priv->proxies, link);
407 gtk_widget_queue_resize (GTK_WIDGET (container));
408 return;
409 }
410
411 /* Chain up to parent's remove() method. */
412 GTK_CONTAINER_CLASS (e_shell_switcher_parent_class)->remove (
413 container, widget);
414 }
415
416 static void
417 shell_switcher_forall (GtkContainer *container,
418 gboolean include_internals,
419 GtkCallback callback,
420 gpointer callback_data)
421 {
422 EShellSwitcherPrivate *priv;
423
424 priv = E_SHELL_SWITCHER_GET_PRIVATE (container);
425
426 if (include_internals)
427 g_list_foreach (
428 priv->proxies, (GFunc) callback, callback_data);
429
430 /* Chain up to parent's forall() method. */
431 GTK_CONTAINER_CLASS (e_shell_switcher_parent_class)->forall (
432 container, include_internals, callback, callback_data);
433 }
434
435 static void
436 shell_switcher_style_changed (EShellSwitcher *switcher,
437 GtkToolbarStyle style)
438 {
439 if (switcher->priv->style == style)
440 return;
441
442 switcher->priv->style = style;
443
444 g_list_foreach (
445 switcher->priv->proxies,
446 (GFunc) gtk_tool_item_toolbar_reconfigured, NULL);
447
448 gtk_widget_queue_resize (GTK_WIDGET (switcher));
449 g_object_notify (G_OBJECT (switcher), "toolbar-style");
450 }
451
452 static GtkIconSize
453 shell_switcher_get_icon_size (GtkToolShell *shell)
454 {
455 return GTK_ICON_SIZE_LARGE_TOOLBAR;
456 }
457
458 static GtkOrientation
459 shell_switcher_get_orientation (GtkToolShell *shell)
460 {
461 return GTK_ORIENTATION_HORIZONTAL;
462 }
463
464 static GtkToolbarStyle
465 shell_switcher_get_style (GtkToolShell *shell)
466 {
467 return e_shell_switcher_get_style (E_SHELL_SWITCHER (shell));
468 }
469
470 static GtkReliefStyle
471 shell_switcher_get_relief_style (GtkToolShell *shell)
472 {
473 return GTK_RELIEF_NORMAL;
474 }
475
476 static gfloat
477 shell_switcher_get_text_alignment (GtkToolShell *shell)
478 {
479 return 0.0;
480 }
481
482 static void
483 e_shell_switcher_class_init (EShellSwitcherClass *class)
484 {
485 GObjectClass *object_class;
486 GtkWidgetClass *widget_class;
487 GtkContainerClass *container_class;
488
489 g_type_class_add_private (class, sizeof (EShellSwitcherPrivate));
490
491 object_class = G_OBJECT_CLASS (class);
492 object_class->set_property = shell_switcher_set_property;
493 object_class->get_property = shell_switcher_get_property;
494 object_class->dispose = shell_switcher_dispose;
495
496 widget_class = GTK_WIDGET_CLASS (class);
497 widget_class->get_preferred_width = shell_switcher_get_preferred_width;
498 widget_class->get_preferred_height = shell_switcher_get_preferred_height;
499 widget_class->size_allocate = shell_switcher_size_allocate;
500 widget_class->screen_changed = shell_switcher_screen_changed;
501
502 container_class = GTK_CONTAINER_CLASS (class);
503 container_class->remove = shell_switcher_remove;
504 container_class->forall = shell_switcher_forall;
505
506 class->style_changed = shell_switcher_style_changed;
507
508 /**
509 * EShellSwitcher:toolbar-style
510 *
511 * The switcher's toolbar style.
512 **/
513 g_object_class_install_property (
514 object_class,
515 PROP_TOOLBAR_STYLE,
516 g_param_spec_enum (
517 "toolbar-style",
518 "Toolbar Style",
519 "The switcher's toolbar style",
520 GTK_TYPE_TOOLBAR_STYLE,
521 E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE,
522 G_PARAM_READWRITE |
523 G_PARAM_CONSTRUCT));
524
525 /**
526 * EShellSwitcher:toolbar-visible
527 *
528 * Whether the switcher is visible.
529 **/
530 g_object_class_install_property (
531 object_class,
532 PROP_TOOLBAR_VISIBLE,
533 g_param_spec_boolean (
534 "toolbar-visible",
535 "Toolbar Visible",
536 "Whether the switcher is visible",
537 TRUE,
538 G_PARAM_READWRITE |
539 G_PARAM_CONSTRUCT));
540
541 /**
542 * EShellSwitcher::style-changed
543 * @switcher: the #EShellSwitcher which emitted the signal
544 * @style: the new #GtkToolbarStyle of the switcher
545 *
546 * Emitted when the style of the switcher changes.
547 **/
548 signals[STYLE_CHANGED] = g_signal_new (
549 "style-changed",
550 G_OBJECT_CLASS_TYPE (class),
551 G_SIGNAL_RUN_FIRST,
552 G_STRUCT_OFFSET (EShellSwitcherClass, style_changed),
553 NULL, NULL,
554 g_cclosure_marshal_VOID__ENUM,
555 G_TYPE_NONE, 1,
556 GTK_TYPE_TOOLBAR_STYLE);
557 }
558
559 static void
560 e_shell_switcher_init (EShellSwitcher *switcher)
561 {
562 switcher->priv = E_SHELL_SWITCHER_GET_PRIVATE (switcher);
563
564 gtk_widget_set_has_window (GTK_WIDGET (switcher), FALSE);
565
566 e_extensible_load_extensions (E_EXTENSIBLE (switcher));
567 }
568
569 static void
570 shell_switcher_tool_shell_iface_init (GtkToolShellIface *iface)
571 {
572 iface->get_icon_size = shell_switcher_get_icon_size;
573 iface->get_orientation = shell_switcher_get_orientation;
574 iface->get_style = shell_switcher_get_style;
575 iface->get_relief_style = shell_switcher_get_relief_style;
576 iface->get_text_alignment = shell_switcher_get_text_alignment;
577 }
578
579 /**
580 * e_shell_switcher_new:
581 *
582 * Creates a new #EShellSwitcher instance.
583 *
584 * Returns: a new #EShellSwitcher instance
585 **/
586 GtkWidget *
587 e_shell_switcher_new (void)
588 {
589 return g_object_new (E_TYPE_SHELL_SWITCHER, NULL);
590 }
591
592 /*
593 * gtk+ doesn't give us what we want - a middle click,
594 * option on toolbar items, so we have to get it by force.
595 */
596 static GtkButton *
597 tool_item_get_button (GtkWidget *widget)
598 {
599 GtkWidget *child;
600
601 g_return_val_if_fail (GTK_IS_TOOL_ITEM (widget), NULL);
602
603 child = gtk_bin_get_child (GTK_BIN (widget));
604 if (child != NULL && GTK_IS_BUTTON (child))
605 return GTK_BUTTON (child);
606 else
607 return NULL;
608 }
609
610 static gboolean
611 tool_item_button_cb (GtkWidget *internal_widget,
612 GdkEventButton *event,
613 GtkAction *action)
614 {
615 g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
616
617 if (event->button == 2) {
618 gtk_action_activate (action);
619 return TRUE;
620 }
621 return FALSE;
622 }
623
624 /**
625 * e_shell_switcher_add_action:
626 * @switcher: an #EShellSwitcher
627 * @switch_action: a #GtkAction
628 * @new_window_action: a #GtkAction
629 *
630 * Adds a button to @switcher that proxies for @switcher_action.
631 * Switcher buttons appear in the order they were added. A middle
632 * click opens a new window of this type.
633 *
634 * #EShellWindow adds switcher actions in the order given by the
635 * <structfield>sort_order</structfield> field in #EShellBackendClass.
636 **/
637 void
638 e_shell_switcher_add_action (EShellSwitcher *switcher,
639 GtkAction *switch_action,
640 GtkAction *new_window_action)
641 {
642 GtkWidget *widget;
643 GtkButton *button;
644
645 g_return_if_fail (E_IS_SHELL_SWITCHER (switcher));
646 g_return_if_fail (GTK_IS_ACTION (switch_action));
647 g_return_if_fail (GTK_IS_ACTION (new_window_action));
648
649 g_object_ref (switch_action);
650 widget = gtk_action_create_tool_item (switch_action);
651 gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE);
652 gtk_widget_show (widget);
653
654 button = tool_item_get_button (widget);
655 if (button != NULL)
656 g_signal_connect (
657 button, "button-release-event",
658 G_CALLBACK (tool_item_button_cb),
659 new_window_action);
660
661 switcher->priv->proxies = g_list_append (
662 switcher->priv->proxies, widget);
663
664 gtk_widget_set_parent (widget, GTK_WIDGET (switcher));
665 gtk_widget_queue_resize (GTK_WIDGET (switcher));
666 }
667
668 /**
669 * e_shell_switcher_get_style:
670 * @switcher: an #EShellSwitcher
671 *
672 * Returns whether @switcher has text, icons or both.
673 *
674 * Returns: the current style of @shell
675 **/
676 GtkToolbarStyle
677 e_shell_switcher_get_style (EShellSwitcher *switcher)
678 {
679 g_return_val_if_fail (
680 E_IS_SHELL_SWITCHER (switcher),
681 E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE);
682
683 return switcher->priv->style;
684 }
685
686 /**
687 * e_shell_switcher_set_style:
688 * @switcher: an #EShellSwitcher
689 * @style: the new style for @switcher
690 *
691 * Alters the view of @switcher to display either icons only, text only,
692 * or both.
693 **/
694 void
695 e_shell_switcher_set_style (EShellSwitcher *switcher,
696 GtkToolbarStyle style)
697 {
698 g_return_if_fail (E_IS_SHELL_SWITCHER (switcher));
699
700 switcher->priv->style_set = TRUE;
701 g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style);
702 }
703
704 /**
705 * e_shell_switcher_unset_style:
706 * @switcher: an #EShellSwitcher
707 *
708 * Unsets a switcher style set with e_shell_switcher_set_style(), so
709 * that user preferences will be used to determine the switcher style.
710 **/
711 void
712 e_shell_switcher_unset_style (EShellSwitcher *switcher)
713 {
714 GtkSettings *settings;
715 GtkToolbarStyle style;
716
717 g_return_if_fail (E_IS_SHELL_SWITCHER (switcher));
718
719 if (!switcher->priv->style_set)
720 return;
721
722 settings = switcher->priv->settings;
723 if (settings != NULL)
724 g_object_get (settings, "gtk-toolbar-style", &style, NULL);
725 else
726 style = E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE;
727
728 if (style == GTK_TOOLBAR_BOTH)
729 style = GTK_TOOLBAR_BOTH_HORIZ;
730
731 if (style != switcher->priv->style)
732 g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style);
733
734 switcher->priv->style_set = FALSE;
735 }
736
737 /**
738 * e_shell_switcher_get_visible:
739 * @switcher: an #EShellSwitcher
740 *
741 * Returns %TRUE if the switcher buttons are visible.
742 *
743 * Note that switcher button visibility is different than
744 * @switcher<!-- -->'s GTK_VISIBLE flag, since #EShellSwitcher
745 * is actually a container widget for #EShellSidebar.
746 *
747 * Returns: %TRUE if the switcher buttons are visible
748 **/
749 gboolean
750 e_shell_switcher_get_visible (EShellSwitcher *switcher)
751 {
752 g_return_val_if_fail (E_IS_SHELL_SWITCHER (switcher), FALSE);
753
754 return switcher->priv->toolbar_visible;
755 }
756
757 /**
758 * e_shell_switcher_set_visible:
759 * @switcher: an #EShellSwitcher
760 * @visible: whether the switcher buttons should be visible
761 *
762 * Sets the switcher button visiblity to @visible.
763 *
764 * Note that switcher button visibility is different than
765 * @switcher<!-- -->'s GTK_VISIBLE flag, since #EShellSwitcher
766 * is actually a container widget for #EShellSidebar.
767 **/
768 void
769 e_shell_switcher_set_visible (EShellSwitcher *switcher,
770 gboolean visible)
771 {
772 GList *iter;
773
774 g_return_if_fail (E_IS_SHELL_SWITCHER (switcher));
775
776 if (switcher->priv->toolbar_visible == visible)
777 return;
778
779 switcher->priv->toolbar_visible = visible;
780
781 for (iter = switcher->priv->proxies; iter != NULL; iter = iter->next)
782 g_object_set (iter->data, "visible", visible, NULL);
783
784 gtk_widget_queue_resize (GTK_WIDGET (switcher));
785
786 g_object_notify (G_OBJECT (switcher), "toolbar-visible");
787 }