2
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
4
This library 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.1 of the License, or (at your option) any later version.
9
See the file COPYING for the full license text.
12
#include "midori-panel.h"
15
#include <glib/gi18n.h>
17
G_DEFINE_TYPE (MidoriPanel, midori_panel, GTK_TYPE_HBOX)
19
struct _MidoriPanelPrivate
22
GtkWidget* toolbar_label;
30
#define MIDORI_PANEL_GET_PRIVATE(obj) \
31
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
32
MIDORI_TYPE_PANEL, MidoriPanelPrivate))
50
static guint signals[LAST_SIGNAL];
53
midori_panel_finalize (GObject* object);
56
midori_panel_set_property (GObject* object,
62
midori_panel_get_property (GObject* object,
68
midori_panel_close_cb (MidoriPanel* panel)
70
gtk_widget_hide (GTK_WIDGET (panel));
75
midori_cclosure_marshal_BOOLEAN__VOID (GClosure* closure,
78
const GValue* param_values,
79
gpointer invocation_hint,
80
gpointer marshal_data)
82
typedef gboolean(*GMarshalFunc_BOOLEAN__VOID) (gpointer data1,
84
register GMarshalFunc_BOOLEAN__VOID callback;
85
register GCClosure* cc = (GCClosure*) closure;
86
register gpointer data1, data2;
89
g_return_if_fail (return_value != NULL);
90
g_return_if_fail (n_param_values == 1);
92
if (G_CCLOSURE_SWAP_DATA (closure))
94
data1 = closure->data;
95
data2 = g_value_peek_pointer (param_values + 0);
99
data1 = g_value_peek_pointer (param_values + 0);
100
data2 = closure->data;
102
callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data
103
? marshal_data : cc->callback);
104
v_return = callback (data1, data2);
105
g_value_set_boolean (return_value, v_return);
109
midori_panel_class_init (MidoriPanelClass* class)
112
signals[CLOSE] = g_signal_new (
114
G_TYPE_FROM_CLASS (class),
115
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
116
G_STRUCT_OFFSET (MidoriPanelClass, close),
117
g_signal_accumulator_true_handled,
119
midori_cclosure_marshal_BOOLEAN__VOID,
122
signals[SWITCH_PAGE] = g_signal_new (
124
G_TYPE_FROM_CLASS (class),
125
(GSignalFlags)(G_SIGNAL_RUN_LAST),
126
G_STRUCT_OFFSET (MidoriPanelClass, switch_page),
129
g_cclosure_marshal_VOID__INT,
133
class->close = midori_panel_close_cb;
135
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
136
gobject_class->finalize = midori_panel_finalize;
137
gobject_class->set_property = midori_panel_set_property;
138
gobject_class->get_property = midori_panel_get_property;
140
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
142
g_object_class_install_property (gobject_class,
147
_("Appearance of the shadow around each panel"),
148
GTK_TYPE_SHADOW_TYPE,
152
g_object_class_install_property (gobject_class,
154
g_param_spec_object (
157
_("Menu to hold panel items"),
161
g_object_class_install_property (gobject_class,
166
_("The index of the current page"),
170
g_type_class_add_private (class, sizeof (MidoriPanelPrivate));
174
midori_panel_button_close_clicked_cb (GtkWidget* toolitem,
177
gboolean return_value;
178
g_signal_emit (panel, signals[CLOSE], 0, &return_value);
182
midori_panel_init (MidoriPanel* panel)
184
panel->priv = MIDORI_PANEL_GET_PRIVATE (panel);
186
MidoriPanelPrivate* priv = panel->priv;
188
// Create the sidebar
189
priv->toolbar = gtk_toolbar_new ();
190
gtk_toolbar_set_style (GTK_TOOLBAR (priv->toolbar), GTK_TOOLBAR_BOTH);
191
gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->toolbar),
192
GTK_ICON_SIZE_BUTTON);
193
gtk_toolbar_set_orientation (GTK_TOOLBAR (priv->toolbar),
194
GTK_ORIENTATION_VERTICAL);
195
gtk_box_pack_start (GTK_BOX (panel), priv->toolbar, FALSE, FALSE, 0);
196
gtk_widget_show_all (priv->toolbar);
197
GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
198
gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0);
200
// Create the titlebar
201
GtkWidget* labelbar = gtk_toolbar_new ();
202
gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU);
203
gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS);
204
GtkToolItem* toolitem = gtk_tool_item_new ();
205
gtk_tool_item_set_expand (toolitem, TRUE);
206
priv->toolbar_label = gtk_label_new (NULL);
207
gtk_misc_set_alignment (GTK_MISC (priv->toolbar_label), 0, 0.5);
208
gtk_container_add (GTK_CONTAINER (toolitem), priv->toolbar_label);
209
gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6);
210
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
211
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE);
212
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close panel"));
213
sokoke_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem), _("Close panel"));
214
g_signal_connect (toolitem, "clicked",
215
G_CALLBACK (midori_panel_button_close_clicked_cb), panel);
216
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
217
gtk_box_pack_start (GTK_BOX (vbox), labelbar, FALSE, FALSE, 0);
218
gtk_widget_show_all (vbox);
220
// Create the toolbook
221
priv->toolbook = gtk_notebook_new ();
222
gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->toolbook), FALSE);
223
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->toolbook), FALSE);
224
gtk_box_pack_start (GTK_BOX (vbox), priv->toolbook, FALSE, FALSE, 0);
225
gtk_widget_show (priv->toolbook);
227
// Create the notebook
228
priv->notebook = gtk_notebook_new ();
229
gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
230
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
231
priv->frame = gtk_frame_new (NULL);
232
gtk_container_add (GTK_CONTAINER (priv->frame), priv->notebook);
233
gtk_box_pack_start (GTK_BOX (vbox), priv->frame, TRUE, TRUE, 0);
234
gtk_widget_show_all (priv->frame);
238
midori_panel_finalize (GObject* object)
240
MidoriPanel* panel = MIDORI_PANEL (object);
241
MidoriPanelPrivate* priv = panel->priv;
245
// FIXME: Remove all menu items
248
G_OBJECT_CLASS (midori_panel_parent_class)->finalize (object);
252
midori_panel_set_property (GObject* object,
257
MidoriPanel* panel = MIDORI_PANEL (object);
258
MidoriPanelPrivate* priv = panel->priv;
262
case PROP_SHADOW_TYPE:
263
gtk_frame_set_shadow_type (GTK_FRAME (priv->frame),
264
g_value_get_enum (value));
267
katze_object_assign (priv->menu, g_value_get_object (value));
268
// FIXME: Move existing items to the new menu
271
midori_panel_set_current_page (panel, g_value_get_int (value));
274
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
280
midori_panel_get_property (GObject* object,
285
MidoriPanel* panel = MIDORI_PANEL (object);
286
MidoriPanelPrivate* priv = panel->priv;
290
case PROP_SHADOW_TYPE:
291
g_value_set_enum (value,
292
gtk_frame_get_shadow_type (GTK_FRAME (priv->frame)));
295
g_value_set_object (value, priv->menu);
298
g_value_set_int (value, midori_panel_get_current_page (panel));
301
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
309
* Creates a new empty panel.
311
* Return value: a new #MidoriPanel
314
midori_panel_new (void)
316
MidoriPanel* panel = g_object_new (MIDORI_TYPE_PANEL,
319
return GTK_WIDGET (panel);
323
midori_panel_menu_item_activate_cb (GtkWidget* widget,
326
GtkWidget* child = g_object_get_data (G_OBJECT (widget), "page");
327
guint n = midori_panel_page_num (panel, child);
328
midori_panel_set_current_page (panel, n);
329
g_signal_emit (panel, signals[SWITCH_PAGE], 0, n);
333
* midori_panel_append_page:
334
* @panel: a #MidoriPanel
335
* @child: the child widget
336
* @toolbar: a toolbar widget, or %NULL
337
* @icon: a stock ID or icon name, or %NULL
338
* @label: a string to use as the label, or %NULL
340
* Appends a new page to the panel. If @toolbar is specified it will
341
* be packaged above @child.
343
* If @icon is an icon name, the according image is used as an
344
* icon for this page.
346
* If @label is given, it is used as the label of this page.
348
* In the case of an error, -1 is returned.
350
* Return value: the index of the new page, or -1
353
midori_panel_append_page (MidoriPanel* panel,
359
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
360
g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
361
g_return_val_if_fail (!toolbar || GTK_IS_WIDGET (toolbar), -1);
363
MidoriPanelPrivate* priv = panel->priv;
365
GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL);
366
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
367
GTK_POLICY_AUTOMATIC,
368
GTK_POLICY_AUTOMATIC);
369
GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS);
370
gtk_widget_show (scrolled);
372
GObjectClass* gobject_class = G_OBJECT_GET_CLASS (child);
373
if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal)
377
widget = gtk_viewport_new (NULL, NULL);
378
gtk_widget_show (widget);
379
gtk_container_add (GTK_CONTAINER (widget), child);
381
gtk_container_add (GTK_CONTAINER (scrolled), widget);
382
gtk_container_add (GTK_CONTAINER (priv->notebook), scrolled);
385
toolbar = gtk_event_box_new ();
386
gtk_widget_show (toolbar);
387
gtk_container_add (GTK_CONTAINER (priv->toolbook), toolbar);
389
guint n = midori_panel_page_num (panel, child);
391
const gchar* text = label ? label : _("Untitled");
392
g_object_set_data (G_OBJECT (child), "label", (gchar*)text);
395
GtkToolItem* toolitem = gtk_radio_tool_button_new (priv->group);
396
priv->group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (
398
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), text);
401
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_BUTTON);
402
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
404
g_object_set_data (G_OBJECT (toolitem), "page", child);
405
g_signal_connect (toolitem, "clicked",
406
G_CALLBACK (midori_panel_menu_item_activate_cb), panel);
407
gtk_widget_show_all (GTK_WIDGET (toolitem));
408
gtk_toolbar_insert (GTK_TOOLBAR (priv->toolbar), toolitem, -1);
412
GtkWidget* menuitem = gtk_image_menu_item_new_with_label (text);
415
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
416
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
419
gtk_widget_show_all (menuitem);
420
g_object_set_data (G_OBJECT (menuitem), "page", child);
421
g_signal_connect (menuitem, "activate",
422
G_CALLBACK (midori_panel_menu_item_activate_cb),
424
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menuitem);
431
* midori_panel_get_current_page:
432
* @panel: a #MidoriPanel
434
* Retrieves the index of the currently selected page.
436
* If @panel has no children, -1 is returned.
438
* Return value: the index of the current page, or -1
441
midori_panel_get_current_page (MidoriPanel* panel)
443
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
445
MidoriPanelPrivate* priv = panel->priv;
447
return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
451
_midori_panel_child_for_scrolled (MidoriPanel* panel,
454
GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled));
455
if (GTK_IS_VIEWPORT (child))
456
child = gtk_bin_get_child (GTK_BIN (child));
461
* midori_panel_get_nth_page:
462
* @panel: a #MidoriPanel
464
* Retrieves the child widget of the nth page.
466
* If @panel has no children, %NULL is returned.
468
* Return value: the child widget of the new page, or %NULL
471
midori_panel_get_nth_page (MidoriPanel* panel,
474
g_return_val_if_fail (MIDORI_IS_PANEL (panel), NULL);
476
MidoriPanelPrivate* priv = panel->priv;
478
GtkWidget* scrolled = gtk_notebook_get_nth_page (
479
GTK_NOTEBOOK (priv->notebook), page_num);
481
return _midori_panel_child_for_scrolled (panel, scrolled);
486
* midori_panel_get_n_pages:
487
* @panel: a #MidoriPanel
489
* Retrieves the number of pages contained in the panel.
491
* Return value: the number of pages
494
midori_panel_get_n_pages (MidoriPanel* panel)
496
g_return_val_if_fail (MIDORI_IS_PANEL (panel), 0);
498
MidoriPanelPrivate* priv = panel->priv;
500
return gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
504
_midori_panel_scrolled_for_child (MidoriPanel* panel,
507
GtkWidget* scrolled = gtk_widget_get_parent (GTK_WIDGET (child));
508
if (GTK_IS_VIEWPORT (scrolled))
509
scrolled = gtk_widget_get_parent (scrolled);
514
* midori_panel_page_num:
515
* @panel: a #MidoriPanel
517
* Retrieves the index of the page associated to @widget.
519
* If @panel has no children, -1 is returned.
521
* Return value: the index of page associated to @widget, or -1
524
midori_panel_page_num (MidoriPanel* panel,
527
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
529
MidoriPanelPrivate* priv = panel->priv;
531
GtkWidget* scrolled = _midori_panel_scrolled_for_child (panel, child);
532
return gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
536
* midori_panel_set_current_page:
537
* @panel: a #MidoriPanel
538
* @n: index of the page to switch to, or -1 to mean the last page
540
* Switches to the page with the given index.
542
* The child must be visible, otherwise the underlying GtkNotebook will
543
* silently ignore the attempt to switch the page.
546
midori_panel_set_current_page (MidoriPanel* panel,
549
g_return_if_fail (MIDORI_IS_PANEL (panel));
551
MidoriPanelPrivate* priv = panel->priv;
553
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->toolbook), n);
554
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
555
GtkWidget* child = midori_panel_get_nth_page (panel, n);
558
const gchar* label = g_object_get_data (G_OBJECT (child), "label");
559
g_object_set (priv->toolbar_label, "label", label, NULL);