1 /*
2 * pluma-panel.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2005 - Paolo Maggi
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 /*
25 * Modified by the pluma Team, 2005. See the AUTHORS file for a
26 * list of people on the pluma Team.
27 * See the ChangeLog files for a list of changes.
28 *
29 * $Id$
30 */
31
32 #include "pluma-panel.h"
33
34 #include <glib/gi18n.h>
35 #include <gtk/gtk.h>
36 #include <gdk/gdk.h>
37 #include <gdk/gdkkeysyms.h>
38
39 #include "pluma-close-button.h"
40 #include "pluma-window.h"
41 #include "pluma-debug.h"
42
43 #define PANEL_ITEM_KEY "PlumaPanelItemKey"
44
45 struct _PlumaPanelPrivate
46 {
47 GtkOrientation orientation;
48
49 /* Title bar (vertical panel only) */
50 GtkWidget *title_image;
51 GtkWidget *title_label;
52
53 /* Notebook */
54 GtkWidget *notebook;
55 };
56
57 typedef struct _PlumaPanelItem PlumaPanelItem;
58
59 struct _PlumaPanelItem
60 {
61 gchar *name;
62 GtkWidget *icon;
63 };
64
65 /* Properties */
66 enum {
67 PROP_0,
68 PROP_ORIENTATION
69 };
70
71 /* Signals */
72 enum {
73 ITEM_ADDED,
74 ITEM_REMOVED,
75 CLOSE,
76 FOCUS_DOCUMENT,
77 LAST_SIGNAL
78 };
79
80 static guint signals[LAST_SIGNAL] = { 0 };
81
82 static GObject *pluma_panel_constructor (GType type,
83 guint n_construct_properties,
84 GObjectConstructParam *construct_properties);
85
86
G_DEFINE_TYPE_WITH_PRIVATE(PlumaPanel,pluma_panel,GTK_TYPE_BOX)87 G_DEFINE_TYPE_WITH_PRIVATE (PlumaPanel, pluma_panel, GTK_TYPE_BOX)
88
89 static void
90 pluma_panel_finalize (GObject *obj)
91 {
92 if (G_OBJECT_CLASS (pluma_panel_parent_class)->finalize)
93 (*G_OBJECT_CLASS (pluma_panel_parent_class)->finalize) (obj);
94 }
95
96 static void
pluma_panel_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)97 pluma_panel_get_property (GObject *object,
98 guint prop_id,
99 GValue *value,
100 GParamSpec *pspec)
101 {
102 PlumaPanel *panel = PLUMA_PANEL (object);
103
104 switch (prop_id)
105 {
106 case PROP_ORIENTATION:
107 g_value_set_enum(value, panel->priv->orientation);
108 break;
109 default:
110 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111 break;
112 }
113 }
114
115 static void
pluma_panel_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)116 pluma_panel_set_property (GObject *object,
117 guint prop_id,
118 const GValue *value,
119 GParamSpec *pspec)
120 {
121 PlumaPanel *panel = PLUMA_PANEL (object);
122
123 switch (prop_id)
124 {
125 case PROP_ORIENTATION:
126 panel->priv->orientation = g_value_get_enum (value);
127 break;
128 default:
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
130 break;
131 }
132 }
133
134 static void
pluma_panel_close(PlumaPanel * panel)135 pluma_panel_close (PlumaPanel *panel)
136 {
137 gtk_widget_hide (GTK_WIDGET (panel));
138 }
139
140 static void
pluma_panel_focus_document(PlumaPanel * panel)141 pluma_panel_focus_document (PlumaPanel *panel)
142 {
143 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel));
144 if (gtk_widget_is_toplevel (toplevel) && PLUMA_IS_WINDOW (toplevel))
145 {
146 PlumaView *view;
147
148 view = pluma_window_get_active_view (PLUMA_WINDOW (toplevel));
149 if (view != NULL)
150 gtk_widget_grab_focus (GTK_WIDGET (view));
151 }
152 }
153
154 static void
pluma_panel_grab_focus(GtkWidget * w)155 pluma_panel_grab_focus (GtkWidget *w)
156 {
157 gint n;
158 GtkWidget *tab;
159 PlumaPanel *panel = PLUMA_PANEL (w);
160
161 n = gtk_notebook_get_current_page (GTK_NOTEBOOK (panel->priv->notebook));
162 if (n == -1)
163 return;
164
165 tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (panel->priv->notebook),
166 n);
167 g_return_if_fail (tab != NULL);
168
169 gtk_widget_grab_focus (tab);
170 }
171
172 static void
pluma_panel_class_init(PlumaPanelClass * klass)173 pluma_panel_class_init (PlumaPanelClass *klass)
174 {
175 GtkBindingSet *binding_set;
176 GObjectClass *object_class = G_OBJECT_CLASS (klass);
177 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
178
179 object_class->constructor = pluma_panel_constructor;
180 object_class->finalize = pluma_panel_finalize;
181 object_class->get_property = pluma_panel_get_property;
182 object_class->set_property = pluma_panel_set_property;
183
184 g_object_class_install_property (object_class,
185 PROP_ORIENTATION,
186 g_param_spec_enum ("panel-orientation",
187 "Panel Orientation",
188 "The panel's orientation",
189 GTK_TYPE_ORIENTATION,
190 GTK_ORIENTATION_VERTICAL,
191 G_PARAM_WRITABLE |
192 G_PARAM_READABLE |
193 G_PARAM_CONSTRUCT_ONLY |
194 G_PARAM_STATIC_STRINGS));
195
196 widget_class->grab_focus = pluma_panel_grab_focus;
197
198 klass->close = pluma_panel_close;
199 klass->focus_document = pluma_panel_focus_document;
200
201 signals[ITEM_ADDED] =
202 g_signal_new ("item_added",
203 G_OBJECT_CLASS_TYPE (klass),
204 G_SIGNAL_RUN_FIRST,
205 G_STRUCT_OFFSET (PlumaPanelClass, item_added),
206 NULL, NULL,
207 g_cclosure_marshal_VOID__OBJECT,
208 G_TYPE_NONE,
209 1,
210 GTK_TYPE_WIDGET);
211 signals[ITEM_REMOVED] =
212 g_signal_new ("item_removed",
213 G_OBJECT_CLASS_TYPE (klass),
214 G_SIGNAL_RUN_FIRST,
215 G_STRUCT_OFFSET (PlumaPanelClass, item_removed),
216 NULL, NULL,
217 g_cclosure_marshal_VOID__OBJECT,
218 G_TYPE_NONE,
219 1,
220 GTK_TYPE_WIDGET);
221
222 /* Keybinding signals */
223 signals[CLOSE] =
224 g_signal_new ("close",
225 G_OBJECT_CLASS_TYPE (klass),
226 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
227 G_STRUCT_OFFSET (PlumaPanelClass, close),
228 NULL, NULL,
229 g_cclosure_marshal_VOID__VOID,
230 G_TYPE_NONE, 0);
231 signals[FOCUS_DOCUMENT] =
232 g_signal_new ("focus_document",
233 G_OBJECT_CLASS_TYPE (klass),
234 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
235 G_STRUCT_OFFSET (PlumaPanelClass, focus_document),
236 NULL, NULL,
237 g_cclosure_marshal_VOID__VOID,
238 G_TYPE_NONE, 0);
239 binding_set = gtk_binding_set_by_class (klass);
240
241 gtk_binding_entry_add_signal (binding_set,
242 GDK_KEY_Escape,
243 0,
244 "close",
245 0);
246 gtk_binding_entry_add_signal (binding_set,
247 GDK_KEY_Return,
248 GDK_CONTROL_MASK,
249 "focus_document",
250 0);
251 }
252
253 /* This is ugly, since it supports only known
254 * storage types of GtkImage, otherwise fall back
255 * to the empty icon.
256 * See http://bugzilla.gnome.org/show_bug.cgi?id=317520.
257 */
258 static void
set_gtk_image_from_gtk_image(GtkImage * image,GtkImage * source)259 set_gtk_image_from_gtk_image (GtkImage *image,
260 GtkImage *source)
261 {
262 switch (gtk_image_get_storage_type (source))
263 {
264 case GTK_IMAGE_EMPTY:
265 gtk_image_clear (image);
266 break;
267 case GTK_IMAGE_PIXBUF:
268 {
269 GdkPixbuf *pb;
270
271 pb = gtk_image_get_pixbuf (source);
272 gtk_image_set_from_pixbuf (image, pb);
273 }
274 break;
275 case GTK_IMAGE_ANIMATION:
276 {
277 GdkPixbufAnimation *a;
278
279 a = gtk_image_get_animation (source);
280 gtk_image_set_from_animation (image, a);
281 }
282 break;
283 case GTK_IMAGE_ICON_NAME:
284 {
285 const gchar *n;
286 GtkIconSize s;
287
288 gtk_image_get_icon_name (source, &n, &s);
289 gtk_image_set_from_icon_name (image, n, s);
290 }
291 break;
292 default:
293 gtk_image_set_from_icon_name (image,
294 "text-x-generic",
295 GTK_ICON_SIZE_MENU);
296 }
297 }
298
299 static void
sync_title(PlumaPanel * panel,PlumaPanelItem * item)300 sync_title (PlumaPanel *panel,
301 PlumaPanelItem *item)
302 {
303 if (panel->priv->orientation != GTK_ORIENTATION_VERTICAL)
304 return;
305
306 if (item != NULL)
307 {
308 gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
309 item->name);
310
311 set_gtk_image_from_gtk_image (GTK_IMAGE (panel->priv->title_image),
312 GTK_IMAGE (item->icon));
313 }
314 else
315 {
316 gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
317 _("Empty"));
318
319 gtk_image_set_from_icon_name (GTK_IMAGE (panel->priv->title_image),
320 "text-x-generic",
321 GTK_ICON_SIZE_MENU);
322 }
323 }
324
325 static void
notebook_page_changed(GtkNotebook * notebook,GtkWidget * page,guint page_num,PlumaPanel * panel)326 notebook_page_changed (GtkNotebook *notebook,
327 GtkWidget *page,
328 guint page_num,
329 PlumaPanel *panel)
330 {
331 GtkWidget *item;
332 PlumaPanelItem *data;
333
334 item = gtk_notebook_get_nth_page (notebook, page_num);
335 g_return_if_fail (item != NULL);
336
337 data = (PlumaPanelItem *)g_object_get_data (G_OBJECT (item),
338 PANEL_ITEM_KEY);
339 g_return_if_fail (data != NULL);
340
341 sync_title (panel, data);
342 }
343
344 static void
panel_show(PlumaPanel * panel,gpointer user_data)345 panel_show (PlumaPanel *panel,
346 gpointer user_data)
347 {
348 gint page;
349 GtkNotebook *nb;
350
351 nb = GTK_NOTEBOOK (panel->priv->notebook);
352
353 page = gtk_notebook_get_current_page (nb);
354
355 if (page != -1)
356 notebook_page_changed (nb, NULL, page, panel);
357 }
358
359 static void
pluma_panel_init(PlumaPanel * panel)360 pluma_panel_init (PlumaPanel *panel)
361 {
362 panel->priv = pluma_panel_get_instance_private (panel);
363
364 gtk_orientable_set_orientation (GTK_ORIENTABLE (panel), GTK_ORIENTATION_VERTICAL);
365 }
366
367 static void
close_button_clicked_cb(GtkWidget * widget,GtkWidget * panel)368 close_button_clicked_cb (GtkWidget *widget,
369 GtkWidget *panel)
370 {
371 gtk_widget_hide (panel);
372 }
373
374 static GtkWidget *
create_close_button(PlumaPanel * panel)375 create_close_button (PlumaPanel *panel)
376 {
377 GtkWidget *button;
378
379 button = pluma_close_button_new ();
380
381 gtk_widget_set_tooltip_text (button, _("Hide panel"));
382
383 g_signal_connect (button,
384 "clicked",
385 G_CALLBACK (close_button_clicked_cb),
386 panel);
387
388 return button;
389 }
390
391 static void
build_notebook_for_panel(PlumaPanel * panel)392 build_notebook_for_panel (PlumaPanel *panel)
393 {
394 /* Create the panel notebook */
395 panel->priv->notebook = gtk_notebook_new ();
396
397 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (panel->priv->notebook),
398 GTK_POS_BOTTOM);
399 gtk_notebook_set_scrollable (GTK_NOTEBOOK (panel->priv->notebook),
400 TRUE);
401 gtk_notebook_popup_enable (GTK_NOTEBOOK (panel->priv->notebook));
402
403 gtk_widget_show (GTK_WIDGET (panel->priv->notebook));
404
405 g_signal_connect (panel->priv->notebook,
406 "switch-page",
407 G_CALLBACK (notebook_page_changed),
408 panel);
409 }
410
411 static void
build_horizontal_panel(PlumaPanel * panel)412 build_horizontal_panel (PlumaPanel *panel)
413 {
414 GtkWidget *box;
415 GtkWidget *sidebar;
416 GtkWidget *close_button;
417
418 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
419
420 gtk_box_pack_start (GTK_BOX (box),
421 panel->priv->notebook,
422 TRUE,
423 TRUE,
424 0);
425
426 /* Toolbar, close button and first separator */
427 sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
428 gtk_container_set_border_width (GTK_CONTAINER (sidebar), 4);
429
430 gtk_box_pack_start (GTK_BOX (box),
431 sidebar,
432 FALSE,
433 FALSE,
434 0);
435
436 close_button = create_close_button (panel);
437
438 gtk_box_pack_start (GTK_BOX (sidebar),
439 close_button,
440 FALSE,
441 FALSE,
442 0);
443
444 gtk_widget_show_all (box);
445
446 gtk_box_pack_start (GTK_BOX (panel),
447 box,
448 TRUE,
449 TRUE,
450 0);
451 }
452
453 static void
build_vertical_panel(PlumaPanel * panel)454 build_vertical_panel (PlumaPanel *panel)
455 {
456 GtkWidget *close_button;
457 GtkWidget *title_hbox;
458 GtkWidget *icon_name_hbox;
459 GtkWidget *dummy_label;
460
461 /* Create title hbox */
462 title_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
463 gtk_container_set_border_width (GTK_CONTAINER (title_hbox), 5);
464
465 gtk_box_pack_start (GTK_BOX (panel), title_hbox, FALSE, FALSE, 0);
466
467 icon_name_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
468 gtk_box_pack_start (GTK_BOX (title_hbox),
469 icon_name_hbox,
470 TRUE,
471 TRUE,
472 0);
473
474 panel->priv->title_image =
475 gtk_image_new_from_icon_name ("text-x-generic",
476 GTK_ICON_SIZE_MENU);
477 gtk_box_pack_start (GTK_BOX (icon_name_hbox),
478 panel->priv->title_image,
479 FALSE,
480 TRUE,
481 0);
482
483 dummy_label = gtk_label_new (" ");
484
485 gtk_box_pack_start (GTK_BOX (icon_name_hbox),
486 dummy_label,
487 FALSE,
488 FALSE,
489 0);
490
491 panel->priv->title_label = gtk_label_new (_("Empty"));
492 gtk_label_set_xalign (GTK_LABEL (panel->priv->title_label), 0.0);
493 gtk_label_set_ellipsize(GTK_LABEL (panel->priv->title_label), PANGO_ELLIPSIZE_END);
494
495 gtk_box_pack_start (GTK_BOX (icon_name_hbox),
496 panel->priv->title_label,
497 TRUE,
498 TRUE,
499 0);
500
501 close_button = create_close_button (panel);
502
503 gtk_box_pack_start (GTK_BOX (title_hbox),
504 close_button,
505 FALSE,
506 FALSE,
507 0);
508
509 gtk_widget_show_all (title_hbox);
510
511 gtk_box_pack_start (GTK_BOX (panel),
512 panel->priv->notebook,
513 TRUE,
514 TRUE,
515 0);
516 }
517
518 static GObject *
pluma_panel_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)519 pluma_panel_constructor (GType type,
520 guint n_construct_properties,
521 GObjectConstructParam *construct_properties)
522 {
523
524 /* Invoke parent constructor. */
525 PlumaPanelClass *klass = PLUMA_PANEL_CLASS (g_type_class_peek (PLUMA_TYPE_PANEL));
526 GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
527 GObject *obj = parent_class->constructor (type,
528 n_construct_properties,
529 construct_properties);
530
531 /* Build the panel, now that we know the orientation
532 (_init has been called previously) */
533 PlumaPanel *panel = PLUMA_PANEL (obj);
534
535 build_notebook_for_panel (panel);
536 if (panel->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
537 build_horizontal_panel (panel);
538 else
539 build_vertical_panel (panel);
540
541 g_signal_connect (panel,
542 "show",
543 G_CALLBACK (panel_show),
544 NULL);
545
546 return obj;
547 }
548
549 /**
550 * pluma_panel_new:
551 * @orientation: a #GtkOrientation
552 *
553 * Creates a new #PlumaPanel with the given @orientation. You shouldn't create
554 * a new panel use pluma_window_get_side_panel() or pluma_window_get_bottom_panel()
555 * instead.
556 *
557 * Returns: a new #PlumaPanel object.
558 */
559 GtkWidget *
pluma_panel_new(GtkOrientation orientation)560 pluma_panel_new (GtkOrientation orientation)
561 {
562 return GTK_WIDGET (g_object_new (PLUMA_TYPE_PANEL, "panel-orientation", orientation, NULL));
563 }
564
565 static GtkWidget *
build_tab_label(PlumaPanel * panel,GtkWidget * item,const gchar * name,GtkWidget * icon)566 build_tab_label (PlumaPanel *panel,
567 GtkWidget *item,
568 const gchar *name,
569 GtkWidget *icon)
570 {
571 GtkWidget *hbox, *label_hbox, *label_ebox;
572 GtkWidget *label;
573
574 /* set hbox spacing and label padding (see below) so that there's an
575 * equal amount of space around the label */
576 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
577
578 label_ebox = gtk_event_box_new ();
579 gtk_event_box_set_visible_window (GTK_EVENT_BOX (label_ebox), FALSE);
580 gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0);
581
582 label_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
583 gtk_container_add (GTK_CONTAINER (label_ebox), label_hbox);
584
585 /* setup icon */
586 gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0);
587
588 /* setup label */
589 label = gtk_label_new (name);
590 gtk_label_set_xalign (GTK_LABEL (label), 0.0);
591 gtk_widget_set_margin_start (label, 0);
592 gtk_widget_set_margin_end (label, 0);
593 gtk_widget_set_margin_top (label, 0);
594 gtk_widget_set_margin_bottom (label, 0);
595 gtk_box_pack_start (GTK_BOX (label_hbox), label, TRUE, TRUE, 0);
596
597 gtk_widget_set_tooltip_text (label_ebox, name);
598
599 gtk_widget_show_all (hbox);
600
601 if (panel->priv->orientation == GTK_ORIENTATION_VERTICAL)
602 gtk_widget_hide(label);
603
604 g_object_set_data (G_OBJECT (item), "label", label);
605 g_object_set_data (G_OBJECT (item), "hbox", hbox);
606
607 return hbox;
608 }
609
610 /**
611 * pluma_panel_add_item:
612 * @panel: a #PlumaPanel
613 * @item: the #GtkWidget to add to the @panel
614 * @name: the name to be shown in the @panel
615 * @image: the image to be shown in the @panel
616 *
617 * Adds a new item to the @panel.
618 */
619 void
pluma_panel_add_item(PlumaPanel * panel,GtkWidget * item,const gchar * name,GtkWidget * image)620 pluma_panel_add_item (PlumaPanel *panel,
621 GtkWidget *item,
622 const gchar *name,
623 GtkWidget *image)
624 {
625 PlumaPanelItem *data;
626 GtkWidget *tab_label;
627 GtkWidget *menu_label;
628 gint w, h;
629
630 g_return_if_fail (PLUMA_IS_PANEL (panel));
631 g_return_if_fail (GTK_IS_WIDGET (item));
632 g_return_if_fail (name != NULL);
633 g_return_if_fail (image == NULL || GTK_IS_IMAGE (image));
634
635 data = g_new (PlumaPanelItem, 1);
636
637 data->name = g_strdup (name);
638
639 if (image == NULL)
640 {
641 /* default to empty */
642 data->icon = gtk_image_new_from_icon_name ("text-x-generic",
643 GTK_ICON_SIZE_MENU);
644 }
645 else
646 {
647 data->icon = image;
648 }
649
650 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
651 gtk_widget_set_size_request (data->icon, w, h);
652
653 g_object_set_data (G_OBJECT (item),
654 PANEL_ITEM_KEY,
655 data);
656
657 tab_label = build_tab_label (panel, item, data->name, data->icon);
658
659 menu_label = gtk_label_new (name);
660 gtk_label_set_xalign (GTK_LABEL (menu_label), 0.0);
661
662 if (!gtk_widget_get_visible (item))
663 gtk_widget_show (item);
664
665 gtk_notebook_append_page_menu (GTK_NOTEBOOK (panel->priv->notebook),
666 item,
667 tab_label,
668 menu_label);
669
670 g_signal_emit (G_OBJECT (panel), signals[ITEM_ADDED], 0, item);
671 }
672
673 /**
674 * pluma_panel_add_item_with_icon:
675 * @panel: a #PlumaPanel
676 * @item: the #GtkWidget to add to the @panel
677 * @name: the name to be shown in the @panel
678 * @icon_name: a icon name
679 *
680 * Same as pluma_panel_add_item() but using an image from icon name.
681 */
682 void
pluma_panel_add_item_with_icon(PlumaPanel * panel,GtkWidget * item,const gchar * name,const gchar * icon_name)683 pluma_panel_add_item_with_icon (PlumaPanel *panel,
684 GtkWidget *item,
685 const gchar *name,
686 const gchar *icon_name)
687 {
688 GtkWidget *icon = NULL;
689
690 if (icon_name != NULL)
691 {
692 icon = gtk_image_new_from_icon_name (icon_name,
693 GTK_ICON_SIZE_MENU);
694 }
695
696 pluma_panel_add_item (panel, item, name, icon);
697 }
698
699 /**
700 * pluma_panel_remove_item:
701 * @panel: a #PlumaPanel
702 * @item: the item to be removed from the panel
703 *
704 * Removes the widget @item from the panel if it is in the @panel and returns
705 * %TRUE if there was not any problem.
706 *
707 * Returns: %TRUE if it was well removed.
708 */
709 gboolean
pluma_panel_remove_item(PlumaPanel * panel,GtkWidget * item)710 pluma_panel_remove_item (PlumaPanel *panel,
711 GtkWidget *item)
712 {
713 PlumaPanelItem *data;
714 gint page_num;
715
716 g_return_val_if_fail (PLUMA_IS_PANEL (panel), FALSE);
717 g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
718
719 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
720 item);
721
722 if (page_num == -1)
723 return FALSE;
724
725 data = (PlumaPanelItem *)g_object_get_data (G_OBJECT (item),
726 PANEL_ITEM_KEY);
727 g_return_val_if_fail (data != NULL, FALSE);
728
729 g_free (data->name);
730 g_free (data);
731
732 g_object_set_data (G_OBJECT (item),
733 PANEL_ITEM_KEY,
734 NULL);
735
736 /* ref the item to keep it alive during signal emission */
737 g_object_ref (G_OBJECT (item));
738
739 gtk_notebook_remove_page (GTK_NOTEBOOK (panel->priv->notebook),
740 page_num);
741
742 /* if we removed all the pages, reset the title */
743 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook)) == 0)
744 sync_title (panel, NULL);
745
746 g_signal_emit (G_OBJECT (panel), signals[ITEM_REMOVED], 0, item);
747
748 g_object_unref (G_OBJECT (item));
749
750 return TRUE;
751 }
752
753 /**
754 * pluma_panel_activate_item:
755 * @panel: a #PlumaPanel
756 * @item: the item to be activated
757 *
758 * Switches to the page that contains @item.
759 *
760 * Returns: %TRUE if it was activated
761 */
762 gboolean
pluma_panel_activate_item(PlumaPanel * panel,GtkWidget * item)763 pluma_panel_activate_item (PlumaPanel *panel,
764 GtkWidget *item)
765 {
766 gint page_num;
767
768 g_return_val_if_fail (PLUMA_IS_PANEL (panel), FALSE);
769 g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
770
771 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
772 item);
773
774 if (page_num == -1)
775 return FALSE;
776
777 gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->priv->notebook),
778 page_num);
779
780 return TRUE;
781 }
782
783 /**
784 * pluma_panel_item_is_active:
785 * @panel: a #PlumaPanel
786 * @item: a #GtkWidget
787 *
788 * Returns whether @item is the active widget in @panel
789 *
790 * Returns: %TRUE if @item is the active widget
791 */
792 gboolean
pluma_panel_item_is_active(PlumaPanel * panel,GtkWidget * item)793 pluma_panel_item_is_active (PlumaPanel *panel,
794 GtkWidget *item)
795 {
796 gint cur_page;
797 gint page_num;
798
799 g_return_val_if_fail (PLUMA_IS_PANEL (panel), FALSE);
800 g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
801
802 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
803 item);
804
805 if (page_num == -1)
806 return FALSE;
807
808 cur_page = gtk_notebook_get_current_page (
809 GTK_NOTEBOOK (panel->priv->notebook));
810
811 return (page_num == cur_page);
812 }
813
814 /**
815 * pluma_panel_get_orientation:
816 * @panel: a #PlumaPanel
817 *
818 * Gets the orientation of the @panel.
819 *
820 * Returns: the #GtkOrientation of #PlumaPanel
821 */
822 GtkOrientation
pluma_panel_get_orientation(PlumaPanel * panel)823 pluma_panel_get_orientation (PlumaPanel *panel)
824 {
825 g_return_val_if_fail (PLUMA_IS_PANEL (panel), GTK_ORIENTATION_VERTICAL);
826
827 return panel->priv->orientation;
828 }
829
830 /**
831 * pluma_panel_get_n_items:
832 * @panel: a #PlumaPanel
833 *
834 * Gets the number of items in a @panel.
835 *
836 * Returns: the number of items contained in #PlumaPanel
837 */
838 gint
pluma_panel_get_n_items(PlumaPanel * panel)839 pluma_panel_get_n_items (PlumaPanel *panel)
840 {
841 g_return_val_if_fail (PLUMA_IS_PANEL (panel), -1);
842
843 return gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook));
844 }
845
846 gint
_pluma_panel_get_active_item_id(PlumaPanel * panel)847 _pluma_panel_get_active_item_id (PlumaPanel *panel)
848 {
849 gint cur_page;
850 GtkWidget *item;
851 PlumaPanelItem *data;
852
853 g_return_val_if_fail (PLUMA_IS_PANEL (panel), 0);
854
855 cur_page = gtk_notebook_get_current_page (
856 GTK_NOTEBOOK (panel->priv->notebook));
857 if (cur_page == -1)
858 return 0;
859
860 item = gtk_notebook_get_nth_page (
861 GTK_NOTEBOOK (panel->priv->notebook),
862 cur_page);
863
864 /* FIXME: for now we use as the hash of the name as id.
865 * However the name is not guaranteed to be unique and
866 * it is a translated string, so it's subotimal, but should
867 * be good enough for now since we don't want to add an
868 * ad hoc id argument.
869 */
870
871 data = (PlumaPanelItem *)g_object_get_data (G_OBJECT (item),
872 PANEL_ITEM_KEY);
873 g_return_val_if_fail (data != NULL, 0);
874
875 return g_str_hash (data->name);
876 }
877
878 void
_pluma_panel_set_active_item_by_id(PlumaPanel * panel,gint id)879 _pluma_panel_set_active_item_by_id (PlumaPanel *panel,
880 gint id)
881 {
882 gint n, i;
883
884 g_return_if_fail (PLUMA_IS_PANEL (panel));
885
886 if (id == 0)
887 return;
888
889 n = gtk_notebook_get_n_pages (
890 GTK_NOTEBOOK (panel->priv->notebook));
891
892 for (i = 0; i < n; i++)
893 {
894 GtkWidget *item;
895 PlumaPanelItem *data;
896
897 item = gtk_notebook_get_nth_page (
898 GTK_NOTEBOOK (panel->priv->notebook), i);
899
900 data = (PlumaPanelItem *)g_object_get_data (G_OBJECT (item),
901 PANEL_ITEM_KEY);
902 g_return_if_fail (data != NULL);
903
904 if (g_str_hash (data->name) == id)
905 {
906 gtk_notebook_set_current_page (
907 GTK_NOTEBOOK (panel->priv->notebook), i);
908
909 return;
910 }
911 }
912 }
913