]> git.0d.be Git - empathy.git/blob - src/ev-sidebar.c
use gtk_box_new() instead of gtk_[h,v]box_new()
[empathy.git] / src / ev-sidebar.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Red Hat, Inc.
4  *            (C) 2007 Jan Arne Petersen
5  *
6  *  Authors:
7  *    Jonathan Blandford <jrb@alum.mit.edu>
8  *    Jan Arne Petersen <jpetersen@jpetersen.org>
9  *
10  * Evince is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Evince is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301  USA.
23  *
24  * Thursday 03 May 2007: Bastien Nocera: Add exception clause.
25  * See license_change file for details.
26  *
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <string.h>
34 #include <gtk/gtk.h>
35 #include <gdk/gdkkeysyms.h>
36
37 #include "ev-sidebar.h"
38
39 enum
40 {
41         PAGE_COLUMN_ID,
42         PAGE_COLUMN_TITLE,
43         PAGE_COLUMN_NUM_COLS
44 };
45
46 struct _EvSidebarPrivate {
47         GtkWidget *combobox;
48         GtkWidget *notebook;
49 };
50
51 enum {
52         CLOSED,
53         CHANGED,
54         LAST_SIGNAL
55 };
56
57 static int ev_sidebar_table_signals[LAST_SIGNAL] = { 0 };
58
59 G_DEFINE_TYPE (EvSidebar, ev_sidebar, GTK_TYPE_VBOX)
60
61 #define EV_SIDEBAR_GET_PRIVATE(object) \
62                 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR, EvSidebarPrivate))
63
64 static void
65 ev_sidebar_class_init (EvSidebarClass *ev_sidebar_class)
66 {
67         GObjectClass *g_object_class;
68  
69         g_object_class = G_OBJECT_CLASS (ev_sidebar_class);
70            
71         g_type_class_add_private (g_object_class, sizeof (EvSidebarPrivate));
72
73         ev_sidebar_table_signals[CLOSED] =
74                 g_signal_new ("closed",
75                                 G_TYPE_FROM_CLASS (g_object_class),
76                                 G_SIGNAL_RUN_LAST,
77                                 G_STRUCT_OFFSET (EvSidebarClass, closed),
78                                 NULL, NULL,
79                                 g_cclosure_marshal_generic,
80                                 G_TYPE_NONE, 0);
81
82         ev_sidebar_table_signals[CHANGED] =
83                 g_signal_new ("changed",
84                                 G_TYPE_FROM_CLASS (g_object_class),
85                                 G_SIGNAL_RUN_LAST,
86                                 G_STRUCT_OFFSET (EvSidebarClass, closed),
87                                 NULL, NULL,
88                                 g_cclosure_marshal_generic,
89                                 G_TYPE_NONE, 1, G_TYPE_STRING);
90
91 }
92
93 static void
94 ev_sidebar_close_clicked_cb (GtkWidget *widget,
95                              gpointer   user_data)
96 {
97         EvSidebar *ev_sidebar = EV_SIDEBAR (user_data);
98
99         g_signal_emit (G_OBJECT (ev_sidebar),
100                         ev_sidebar_table_signals[CLOSED], 0, NULL);
101         gtk_widget_hide (GTK_WIDGET (ev_sidebar));
102 }
103
104 static void
105 ev_sidebar_combobox_changed_cb (GtkComboBox *combo_box,
106                                 gpointer   user_data)
107 {
108         EvSidebar *ev_sidebar = EV_SIDEBAR (user_data);
109         GtkTreeModel *model;
110         GtkTreeIter iter;
111
112         model = gtk_combo_box_get_model (combo_box);
113
114         if (gtk_combo_box_get_active_iter (combo_box, &iter)) {
115                 GtkTreePath *path;
116                 gint *indices;
117
118                 path = gtk_tree_model_get_path (model, &iter);
119                 indices = gtk_tree_path_get_indices (path);
120
121                 if (indices != NULL) {
122                         gchar *page;
123
124                         gtk_notebook_set_current_page (GTK_NOTEBOOK (ev_sidebar->priv->notebook), indices[0]);
125                         gtk_tree_model_get (model, &iter, PAGE_COLUMN_ID, &page, -1);
126                         g_signal_emit (G_OBJECT (ev_sidebar), ev_sidebar_table_signals[CHANGED], 0, page);
127                         g_free (page);
128                 }
129
130                 gtk_tree_path_free (path);
131         }
132
133 }
134
135 static void
136 ev_sidebar_init (EvSidebar *ev_sidebar)
137 {
138         GtkTreeModel *page_model;
139         GtkWidget *vbox, *hbox;
140         GtkWidget *close_button;
141         GtkCellRenderer *renderer;
142         GtkWidget *image;
143
144         ev_sidebar->priv = EV_SIDEBAR_GET_PRIVATE (ev_sidebar);
145
146         /* data model */
147         page_model = (GtkTreeModel *)
148                         gtk_list_store_new (PAGE_COLUMN_NUM_COLS,
149                                             G_TYPE_STRING,
150                                             G_TYPE_STRING,
151                                             GTK_TYPE_WIDGET,
152                                             G_TYPE_INT);
153
154         /* create a 6 6 6 0 border with GtkBoxes */
155         hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
156         gtk_box_pack_start (GTK_BOX (ev_sidebar), hbox, TRUE, TRUE, 6);
157
158         vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
159         gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
160         gtk_box_pack_start (GTK_BOX (hbox), gtk_box_new (GTK_ORIENTATION_VERTICAL, 0), FALSE, FALSE, 0);
161
162         /* top option menu */
163         hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
164         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
165         gtk_widget_show (hbox);
166
167         ev_sidebar->priv->combobox = gtk_combo_box_new_with_model (page_model);
168         g_signal_connect (ev_sidebar->priv->combobox, "changed",
169                           G_CALLBACK (ev_sidebar_combobox_changed_cb),
170                           ev_sidebar);
171
172         renderer = gtk_cell_renderer_text_new ();
173         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ev_sidebar->priv->combobox), renderer, TRUE);
174         gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ev_sidebar->priv->combobox), renderer, "text", PAGE_COLUMN_TITLE);
175
176         gtk_box_pack_start (GTK_BOX (hbox), ev_sidebar->priv->combobox, TRUE, TRUE, 0);
177         gtk_widget_show (ev_sidebar->priv->combobox);
178
179         g_object_unref (G_OBJECT (page_model));
180
181         close_button = gtk_button_new ();
182         gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
183         g_signal_connect (close_button, "clicked",
184                           G_CALLBACK (ev_sidebar_close_clicked_cb),
185                           ev_sidebar);
186
187         image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
188                                           GTK_ICON_SIZE_MENU);
189         gtk_container_add (GTK_CONTAINER (close_button), image);
190         gtk_widget_show (image);
191    
192         gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
193         gtk_widget_show (close_button);
194    
195         ev_sidebar->priv->notebook = gtk_notebook_new ();
196         gtk_notebook_set_show_border (GTK_NOTEBOOK (ev_sidebar->priv->notebook), FALSE);
197         gtk_notebook_set_show_tabs (GTK_NOTEBOOK (ev_sidebar->priv->notebook), FALSE);
198         gtk_box_pack_start (GTK_BOX (vbox), ev_sidebar->priv->notebook,
199                             TRUE, TRUE, 0);
200         gtk_widget_show (ev_sidebar->priv->notebook);
201 }
202
203 /* Public functions */
204
205 GtkWidget *
206 ev_sidebar_new (void)
207 {
208         GtkWidget *ev_sidebar;
209
210         ev_sidebar = g_object_new (EV_TYPE_SIDEBAR, NULL);
211
212         return ev_sidebar;
213 }
214
215 /* NOTE: Return values from this have to be g_free()d */
216 char *
217 ev_sidebar_get_current_page (EvSidebar *ev_sidebar)
218 {
219         GtkTreeModel *model;
220         GtkTreeIter iter;
221         char *id;
222
223         g_return_val_if_fail (EV_IS_SIDEBAR (ev_sidebar), NULL);
224         g_return_val_if_fail (ev_sidebar->priv != NULL, NULL);
225
226         model = gtk_combo_box_get_model (GTK_COMBO_BOX (ev_sidebar->priv->combobox));
227
228         if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ev_sidebar->priv->combobox), &iter)) {
229                 gtk_tree_model_get (model, &iter, PAGE_COLUMN_ID, &id, -1);
230
231                 return id;
232         }
233
234         return NULL;
235 }
236
237 static gboolean
238 ev_sidebar_get_iter_for_page_id (EvSidebar *ev_sidebar,
239                                  const char *new_page_id,
240                                  GtkTreeIter *iter)
241 {
242         GtkTreeModel *model;
243         gboolean valid;
244         gchar *page_id;
245
246         g_return_val_if_fail (EV_IS_SIDEBAR (ev_sidebar), FALSE);
247         g_return_val_if_fail (ev_sidebar->priv != NULL, FALSE);
248         g_return_val_if_fail (iter != NULL, FALSE);
249
250         model = gtk_combo_box_get_model (GTK_COMBO_BOX (ev_sidebar->priv->combobox));
251
252         valid = gtk_tree_model_get_iter_first (model, iter);
253
254         while (valid) {
255                 gtk_tree_model_get (model, iter, PAGE_COLUMN_ID, &page_id, -1);
256
257                 if (page_id != NULL && strcmp (new_page_id, page_id) == 0) {
258                         g_free (page_id);
259                         return TRUE;
260                 }
261                 g_free (page_id);
262
263                 valid = gtk_tree_model_iter_next (model, iter);
264         }
265
266         return FALSE;
267 }
268
269 void
270 ev_sidebar_set_current_page (EvSidebar *ev_sidebar, const char *new_page_id)
271 {
272         GtkTreeIter iter;
273
274         g_return_if_fail (EV_IS_SIDEBAR (ev_sidebar));
275         g_return_if_fail (new_page_id != NULL);
276
277
278         if (ev_sidebar_get_iter_for_page_id (ev_sidebar, new_page_id, &iter)) {
279                 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ev_sidebar->priv->combobox), &iter);
280         }
281 }
282
283 void
284 ev_sidebar_add_page (EvSidebar   *ev_sidebar,
285                      const gchar *page_id,
286                      const gchar *title,
287                      GtkWidget   *main_widget)
288 {
289         GtkTreeIter iter, iter2;
290         GtkTreeModel *model;
291            
292         g_return_if_fail (EV_IS_SIDEBAR (ev_sidebar));
293         g_return_if_fail (page_id != NULL);
294         g_return_if_fail (title != NULL);
295         g_return_if_fail (GTK_IS_WIDGET (main_widget));
296
297         model = gtk_combo_box_get_model (GTK_COMBO_BOX (ev_sidebar->priv->combobox));
298
299         gtk_widget_set_sensitive (GTK_WIDGET (ev_sidebar), TRUE);
300
301         gtk_widget_show (main_widget);  
302         gtk_notebook_append_page (GTK_NOTEBOOK (ev_sidebar->priv->notebook), main_widget, NULL);
303
304         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
305         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
306                             PAGE_COLUMN_ID, page_id,
307                             PAGE_COLUMN_TITLE, title,
308                             -1);
309
310         if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ev_sidebar->priv->combobox), &iter2)) {
311                 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ev_sidebar->priv->combobox), &iter);
312         }
313 }
314
315 void
316 ev_sidebar_remove_page (EvSidebar   *ev_sidebar,
317                         const gchar *page_id)
318 {
319         GtkTreeIter iter;
320         GtkTreeModel *model;
321            
322         g_return_if_fail (EV_IS_SIDEBAR (ev_sidebar));
323         g_return_if_fail (page_id != NULL);
324
325         model = gtk_combo_box_get_model (GTK_COMBO_BOX (ev_sidebar->priv->combobox));
326
327         if (ev_sidebar_get_iter_for_page_id (ev_sidebar, page_id, &iter)) {
328                 GtkTreePath *path;
329                 gint *indices;
330
331                 path = gtk_tree_model_get_path (model, &iter);
332                 indices = gtk_tree_path_get_indices (path);
333
334                 g_assert (indices != NULL);
335                 gtk_notebook_remove_page (GTK_NOTEBOOK (ev_sidebar->priv->notebook), indices[0]);
336
337                 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
338
339                 if (gtk_tree_model_iter_n_children (model, NULL) != 0) {
340                         gtk_tree_path_prev (path);
341
342                         if (gtk_tree_model_get_iter (model, &iter, path)) {
343                                 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ev_sidebar->priv->combobox), &iter);
344                         }
345                 } else {
346                         gtk_widget_set_sensitive (GTK_WIDGET (ev_sidebar), FALSE);
347                 }
348
349                 gtk_tree_path_free (path);
350         }
351 }
352