]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/zoom-control/ephy-zoom-control.c
Output zoom-control Makefile. build zoom-control subdir.
[evince.git] / cut-n-paste / zoom-control / ephy-zoom-control.c
1 /*
2  *  Copyright (C) 2003, 2004 Christian Persch
3  *
4  *  Modified 2005 by James Bowes for use in evince.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2, or (at your option)
9  *  any later version.
10  *
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
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  *  $Id$
21  */
22
23 #include "config.h"
24
25 #include "ephy-zoom-control.h"
26 #include "ephy-zoom.h"
27 #include "ev-debug.h"
28
29 #include <gtk/gtk.h>
30 #include <gtk/gtkcombobox.h>
31 #include <gtk/gtktooltips.h>
32 #include <glib/gi18n.h>
33
34 #define EPHY_ZOOM_CONTROL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControlPrivate))
35
36 struct _EphyZoomControlPrivate
37 {
38         GtkComboBox *combo;
39         float zoom;
40         guint handler_id;
41 };
42
43 enum
44 {
45         COL_TEXT,
46         COL_IS_SEP
47 };
48
49 enum
50 {
51         PROP_0,
52         PROP_ZOOM
53 };
54
55 enum
56 {
57         ZOOM_TO_LEVEL_SIGNAL,
58         LAST_SIGNAL
59 };
60
61 static guint signals[LAST_SIGNAL];
62
63 static GObjectClass *parent_class = NULL;
64
65 static void     ephy_zoom_control_class_init    (EphyZoomControlClass *klass);
66 static void     ephy_zoom_control_init          (EphyZoomControl *control);
67 static void     ephy_zoom_control_finalize      (GObject *o);
68
69 GType
70 ephy_zoom_control_get_type (void)
71 {
72         static GType type = 0;
73
74         if (G_UNLIKELY (type == 0))
75         {
76                 static const GTypeInfo our_info =
77                         {
78                                 sizeof (EphyZoomControlClass),
79                                 NULL, /* base_init */
80                                 NULL, /* base_finalize */
81                                 (GClassInitFunc) ephy_zoom_control_class_init,
82                                 NULL,
83                                 NULL, /* class_data */
84                                 sizeof (EphyZoomControl),
85                                 0, /* n_preallocs */
86                                 (GInstanceInitFunc) ephy_zoom_control_init,
87                         };
88
89                 type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
90                                                "EphyZoomControl",
91                                                &our_info, 0);
92         }
93
94         return type;
95 }
96
97 static void
98 combo_changed_cb (GtkComboBox *combo, EphyZoomControl *control)
99 {
100         gint index;
101         float zoom;
102
103         index = gtk_combo_box_get_active (combo);
104         zoom = zoom_levels[index].level;
105
106         if (zoom != control->priv->zoom)
107         {
108                 g_signal_emit (control, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);        
109         }
110 }
111
112 static void
113 sync_zoom_cb (EphyZoomControl *control, GParamSpec *pspec, gpointer data)
114 {
115         EphyZoomControlPrivate *p = control->priv;
116         guint index;
117
118         index = ephy_zoom_get_zoom_level_index (p->zoom);
119
120         g_signal_handler_block (p->combo, p->handler_id);
121         gtk_combo_box_set_active (p->combo, index);
122         g_signal_handler_unblock (p->combo, p->handler_id);     
123 }
124
125 static gboolean
126 row_is_separator (GtkTreeModel *model,
127                   GtkTreeIter  *iter,
128                   gpointer      data)
129 {
130         gboolean is_sep;
131         gtk_tree_model_get (model, iter, COL_IS_SEP, &is_sep, -1);
132         return is_sep;
133 }
134
135 static void
136 ephy_zoom_control_init (EphyZoomControl *control)
137 {
138         EphyZoomControlPrivate *p;
139         GtkWidget *vbox;
140         GtkCellRenderer *renderer;
141         GtkListStore    *store;
142         GtkTreeIter      iter;
143         guint i;
144
145         p = EPHY_ZOOM_CONTROL_GET_PRIVATE (control);
146         control->priv = p;
147
148         p->zoom = 1.0;
149
150         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
151
152         for (i = 0; i < n_zoom_levels; i++)
153         {
154                 gtk_list_store_append (store, &iter);
155                 gtk_list_store_set    (store, &iter,
156                                        COL_TEXT, zoom_levels[i].name,
157                                        COL_IS_SEP, zoom_levels[i].name == NULL,
158                                        -1);
159         }
160
161         p->combo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)));
162         g_object_unref (store);
163
164         renderer = gtk_cell_renderer_text_new ();
165         gtk_cell_layout_pack_start     (GTK_CELL_LAYOUT (p->combo), renderer, TRUE);
166         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (p->combo), renderer,
167                                         "text", COL_TEXT, NULL);
168         gtk_combo_box_set_row_separator_func (p->combo,
169                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
170                                               NULL, NULL);
171
172         gtk_combo_box_set_focus_on_click (p->combo, FALSE);
173         g_object_ref (p->combo);
174         gtk_object_sink (GTK_OBJECT (p->combo));
175         gtk_widget_show (GTK_WIDGET (p->combo));
176
177         i = ephy_zoom_get_zoom_level_index (p->zoom);
178         gtk_combo_box_set_active (p->combo, i);
179
180         vbox = gtk_vbox_new (TRUE, 0);
181         gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (p->combo), TRUE, FALSE, 0);
182         gtk_widget_show (vbox);
183
184         gtk_container_add (GTK_CONTAINER (control), vbox);
185
186         p->handler_id = g_signal_connect (p->combo, "changed",
187                                           G_CALLBACK (combo_changed_cb), control);
188         
189         g_signal_connect_object (control, "notify::zoom",
190                                  G_CALLBACK (sync_zoom_cb), NULL, 0);
191 }
192
193 static void
194 ephy_zoom_control_set_property (GObject *object,
195                                 guint prop_id,
196                                 const GValue *value,
197                                 GParamSpec *pspec)
198 {
199         EphyZoomControl *control;
200         EphyZoomControlPrivate *p;
201
202         control = EPHY_ZOOM_CONTROL (object);
203         p = control->priv;
204
205         switch (prop_id)
206         {
207                 case PROP_ZOOM:
208                         p->zoom = g_value_get_float (value);
209                         break;
210         }
211 }
212
213 static void
214 ephy_zoom_control_get_property (GObject *object,
215                                 guint prop_id,
216                                 GValue *value,
217                                 GParamSpec *pspec)
218 {
219         EphyZoomControl *control;
220         EphyZoomControlPrivate *p;
221
222         control = EPHY_ZOOM_CONTROL (object);
223         p = control->priv;
224
225         switch (prop_id)
226         {
227                 case PROP_ZOOM:
228                         g_value_set_float (value, p->zoom);
229                         break;
230         }
231 }
232
233 static void
234 set_combo_tooltip (GtkWidget *widget, 
235                    GtkTooltipsData *data)
236 {
237         if (GTK_IS_BUTTON (widget))
238         {
239                 gtk_tooltips_set_tip (data->tooltips, widget,
240                                       data->tip_text, data->tip_private);
241         }
242 }
243
244 static void
245 combo_realized (GtkWidget *combo,
246                 GtkWidget *control)
247 {
248         GtkTooltipsData *data;
249
250         data = gtk_tooltips_data_get (control);
251         g_return_if_fail (data != NULL);
252
253         gtk_container_forall (GTK_CONTAINER (combo),
254                               (GtkCallback) set_combo_tooltip, data);
255 }
256
257 static gboolean
258 ephy_zoom_control_set_tooltip (GtkToolItem *tool_item,
259                                GtkTooltips *tooltips,
260                                const char *tip_text,
261                                const char *tip_private)
262 {
263         EphyZoomControl *control = EPHY_ZOOM_CONTROL (tool_item);
264         GtkWidget *widget = GTK_WIDGET (tool_item);
265
266         /* hack to make tooltips work also on Ctrl-F1 */
267         gtk_tooltips_set_tip (tooltips, widget, tip_text, tip_private);
268
269         g_signal_handlers_disconnect_by_func
270                 (control->priv->combo, G_CALLBACK (combo_realized), widget);
271
272         if (GTK_WIDGET_REALIZED (tool_item))
273         {
274                 combo_realized (GTK_WIDGET (control->priv->combo), widget);
275         }
276         else
277         {
278                 g_signal_connect_after (control->priv->combo, "realize",
279                                         G_CALLBACK (combo_realized), widget);
280         }
281
282         return TRUE;
283 }
284
285 static void
286 ephy_zoom_control_class_init (EphyZoomControlClass *klass)
287 {
288         GObjectClass *object_class;
289         GtkToolItemClass *tool_item_class;
290
291         parent_class = g_type_class_peek_parent (klass);
292
293         object_class = (GObjectClass *)klass;
294         tool_item_class = (GtkToolItemClass *)klass;
295
296         object_class->set_property = ephy_zoom_control_set_property;
297         object_class->get_property = ephy_zoom_control_get_property;
298         object_class->finalize = ephy_zoom_control_finalize;
299
300         tool_item_class->set_tooltip = ephy_zoom_control_set_tooltip;
301
302         g_object_class_install_property (object_class,
303                                          PROP_ZOOM,
304                                          g_param_spec_float ("zoom",
305                                                              "Zoom",
306                                                              "Zoom level to display in the item.",
307                                                              ZOOM_MINIMAL,
308                                                              ZOOM_MAXIMAL,
309                                                              1.0,
310                                                              G_PARAM_READWRITE));
311
312         signals[ZOOM_TO_LEVEL_SIGNAL] =
313                 g_signal_new ("zoom_to_level",
314                               G_TYPE_FROM_CLASS (klass),
315                               G_SIGNAL_RUN_LAST,
316                               G_STRUCT_OFFSET (EphyZoomControlClass,
317                                                zoom_to_level),
318                               NULL, NULL,
319                               g_cclosure_marshal_VOID__FLOAT,
320                               G_TYPE_NONE,
321                               1,
322                               G_TYPE_FLOAT);
323
324         g_type_class_add_private (object_class, sizeof (EphyZoomControlPrivate));
325 }
326
327 static void
328 ephy_zoom_control_finalize (GObject *o)
329 {
330         EphyZoomControl *control = EPHY_ZOOM_CONTROL (o);
331
332         g_object_unref (control->priv->combo);
333
334         G_OBJECT_CLASS (parent_class)->finalize (o);
335 }
336
337 void
338 ephy_zoom_control_set_zoom_level (EphyZoomControl *control, float zoom)
339 {
340         g_return_if_fail (EPHY_IS_ZOOM_CONTROL (control));
341
342         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
343
344         control->priv->zoom = zoom;
345         g_object_notify (G_OBJECT (control), "zoom");
346 }
347
348 float
349 ephy_zoom_control_get_zoom_level (EphyZoomControl *control)
350 {
351         g_return_val_if_fail (EPHY_IS_ZOOM_CONTROL (control), 1.0);
352         
353         return control->priv->zoom;
354 }