]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/zoom-control/ephy-zoom-control.c
[ephy-zoom] Add max/min zoom properties
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  *  $Id$
21  */
22
23 #include "config.h"
24
25 #include "ephy-zoom-control.h"
26 #include "ephy-zoom.h"
27
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30
31 #define EPHY_ZOOM_CONTROL_GET_PRIVATE(object)\
32         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControlPrivate))
33
34 struct _EphyZoomControlPrivate
35 {
36         GtkComboBox *combo;
37         float zoom;
38         float min_zoom;
39         float max_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         PROP_MIN_ZOOM,
54         PROP_MAX_ZOOM
55 };
56
57 enum
58 {
59         ZOOM_TO_LEVEL_SIGNAL,
60         LAST_SIGNAL
61 };
62
63 static guint signals[LAST_SIGNAL];
64
65 G_DEFINE_TYPE (EphyZoomControl, ephy_zoom_control, GTK_TYPE_TOOL_ITEM)
66
67 static void
68 combo_changed_cb (GtkComboBox *combo, EphyZoomControl *control)
69 {
70         gint index;
71         float zoom;
72
73         index = gtk_combo_box_get_active (combo);
74         zoom = zoom_levels[index].level;
75
76         if (zoom != control->priv->zoom)
77         {
78                 g_signal_emit (control, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);        
79         }
80 }
81
82 static void
83 sync_zoom_cb (EphyZoomControl *control, GParamSpec *pspec, gpointer data)
84 {
85         EphyZoomControlPrivate *p = control->priv;
86         guint index;
87
88         index = ephy_zoom_get_zoom_level_index (p->zoom);
89
90         g_signal_handler_block (p->combo, p->handler_id);
91         gtk_combo_box_set_active (p->combo, index);
92         g_signal_handler_unblock (p->combo, p->handler_id);     
93 }
94
95 static void
96 sync_zoom_max_min_cb (EphyZoomControl *control, GParamSpec *pspec, gpointer data)
97 {
98         EphyZoomControlPrivate *p = control->priv;
99         GtkListStore *model = (GtkListStore *)gtk_combo_box_get_model (p->combo);
100         GtkTreeIter iter;
101         gint i;
102
103         g_signal_handler_block (p->combo, p->handler_id);
104         gtk_list_store_clear (model);
105
106         for (i = 0; i < n_zoom_levels; i++)
107         {
108                 if (zoom_levels[i].level > 0) {
109                         if (zoom_levels[i].level < p->min_zoom)
110                                 continue;
111
112                         if (zoom_levels[i].level > p->max_zoom)
113                                 break;
114                 }
115
116                 gtk_list_store_append (model, &iter);
117
118                 if (zoom_levels[i].name != NULL) {
119                         gtk_list_store_set (model, &iter,
120                                             COL_TEXT, _(zoom_levels[i].name),
121                                             -1);
122                 } else {
123                         gtk_list_store_set (model, &iter,
124                                             COL_IS_SEP, zoom_levels[i].name == NULL,
125                                             -1);
126                 }
127         }
128
129         gtk_combo_box_set_active (p->combo, ephy_zoom_get_zoom_level_index (p->zoom));
130         g_signal_handler_unblock (p->combo, p->handler_id);
131 }
132
133 static gboolean
134 row_is_separator (GtkTreeModel *model,
135                   GtkTreeIter  *iter,
136                   gpointer      data)
137 {
138         gboolean is_sep;
139         gtk_tree_model_get (model, iter, COL_IS_SEP, &is_sep, -1);
140         return is_sep;
141 }
142
143 static void
144 ephy_zoom_control_finalize (GObject *o)
145 {
146         EphyZoomControl *control = EPHY_ZOOM_CONTROL (o);
147
148         g_object_unref (control->priv->combo);
149
150         G_OBJECT_CLASS (ephy_zoom_control_parent_class)->finalize (o);
151 }
152
153 static void
154 ephy_zoom_control_init (EphyZoomControl *control)
155 {
156         EphyZoomControlPrivate *p;
157         GtkWidget *vbox;
158         GtkCellRenderer *renderer;
159         GtkListStore    *store;
160         GtkTreeIter      iter;
161         guint i;
162
163         p = EPHY_ZOOM_CONTROL_GET_PRIVATE (control);
164         control->priv = p;
165
166         p->zoom = 1.0;
167
168         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
169
170         for (i = 0; i < n_zoom_levels; i++)
171         {
172                 gtk_list_store_append (store, &iter);
173
174                 if (zoom_levels[i].name != NULL) {
175                         gtk_list_store_set (store, &iter,
176                                             COL_TEXT, _(zoom_levels[i].name),
177                                             -1);
178                 } else {
179                         gtk_list_store_set (store, &iter,
180                                             COL_IS_SEP, zoom_levels[i].name == NULL,
181                                             -1);
182                 }
183         }
184
185         p->combo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)));
186         g_object_unref (store);
187
188         renderer = gtk_cell_renderer_text_new ();
189         gtk_cell_layout_pack_start     (GTK_CELL_LAYOUT (p->combo), renderer, TRUE);
190         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (p->combo), renderer,
191                                         "text", COL_TEXT, NULL);
192         gtk_combo_box_set_row_separator_func (p->combo,
193                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
194                                               NULL, NULL);
195
196         gtk_combo_box_set_focus_on_click (p->combo, FALSE);
197         g_object_ref_sink (G_OBJECT (p->combo));
198         gtk_widget_show (GTK_WIDGET (p->combo));
199
200         i = ephy_zoom_get_zoom_level_index (p->zoom);
201         gtk_combo_box_set_active (p->combo, i);
202
203         vbox = gtk_vbox_new (TRUE, 0);
204         gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (p->combo), TRUE, FALSE, 0);
205         gtk_widget_show (vbox);
206
207         gtk_container_add (GTK_CONTAINER (control), vbox);
208
209         p->handler_id = g_signal_connect (p->combo, "changed",
210                                           G_CALLBACK (combo_changed_cb), control);
211         
212         g_signal_connect_object (control, "notify::zoom",
213                                  G_CALLBACK (sync_zoom_cb), NULL, 0);
214         g_signal_connect_object (control, "notify::min-zoom",
215                                  G_CALLBACK (sync_zoom_max_min_cb), NULL, 0);
216         g_signal_connect_object (control, "notify::max-zoom",
217                                  G_CALLBACK (sync_zoom_max_min_cb), NULL, 0);
218 }
219
220 static void
221 ephy_zoom_control_set_property (GObject *object,
222                                 guint prop_id,
223                                 const GValue *value,
224                                 GParamSpec *pspec)
225 {
226         EphyZoomControl *control;
227         EphyZoomControlPrivate *p;
228
229         control = EPHY_ZOOM_CONTROL (object);
230         p = control->priv;
231
232         switch (prop_id)
233         {
234                 case PROP_ZOOM:
235                         p->zoom = g_value_get_float (value);
236                         break;
237                 case PROP_MIN_ZOOM:
238                         p->min_zoom = g_value_get_float (value);
239                         break;
240                 case PROP_MAX_ZOOM:
241                         p->max_zoom = g_value_get_float (value);
242                         break;
243         }
244 }
245
246 static void
247 ephy_zoom_control_get_property (GObject *object,
248                                 guint prop_id,
249                                 GValue *value,
250                                 GParamSpec *pspec)
251 {
252         EphyZoomControl *control;
253         EphyZoomControlPrivate *p;
254
255         control = EPHY_ZOOM_CONTROL (object);
256         p = control->priv;
257
258         switch (prop_id)
259         {
260                 case PROP_ZOOM:
261                         g_value_set_float (value, p->zoom);
262                         break;
263                 case PROP_MIN_ZOOM:
264                         g_value_set_float (value, p->min_zoom);
265                         break;
266                 case PROP_MAX_ZOOM:
267                         g_value_set_float (value, p->max_zoom);
268                         break;
269         }
270 }
271
272 static void
273 ephy_zoom_control_class_init (EphyZoomControlClass *klass)
274 {
275         GObjectClass *object_class;
276         GtkToolItemClass *tool_item_class;
277
278         object_class = (GObjectClass *)klass;
279         tool_item_class = (GtkToolItemClass *)klass;
280
281         object_class->set_property = ephy_zoom_control_set_property;
282         object_class->get_property = ephy_zoom_control_get_property;
283         object_class->finalize = ephy_zoom_control_finalize;
284
285         g_object_class_install_property (object_class,
286                                          PROP_ZOOM,
287                                          g_param_spec_float ("zoom",
288                                                              "Zoom",
289                                                              "Zoom level to display in the item.",
290                                                              ZOOM_MINIMAL,
291                                                              ZOOM_MAXIMAL,
292                                                              1.0,
293                                                              G_PARAM_READWRITE));
294         g_object_class_install_property (object_class,
295                                          PROP_MIN_ZOOM,
296                                          g_param_spec_float ("min-zoom",
297                                                              "MinZoom",
298                                                              "The minimum zoom",
299                                                              ZOOM_MINIMAL,
300                                                              ZOOM_MAXIMAL,
301                                                              ZOOM_MINIMAL,
302                                                              G_PARAM_READWRITE));
303         g_object_class_install_property (object_class,
304                                          PROP_MAX_ZOOM,
305                                          g_param_spec_float ("max-zoom",
306                                                              "MaxZoom",
307                                                              "The maximum zoom",
308                                                              ZOOM_MINIMAL,
309                                                              ZOOM_MAXIMAL,
310                                                              ZOOM_MAXIMAL,
311                                                              G_PARAM_READWRITE));
312
313         signals[ZOOM_TO_LEVEL_SIGNAL] =
314                 g_signal_new ("zoom_to_level",
315                               G_TYPE_FROM_CLASS (klass),
316                               G_SIGNAL_RUN_LAST,
317                               G_STRUCT_OFFSET (EphyZoomControlClass,
318                                                zoom_to_level),
319                               NULL, NULL,
320                               g_cclosure_marshal_VOID__FLOAT,
321                               G_TYPE_NONE,
322                               1,
323                               G_TYPE_FLOAT);
324
325         g_type_class_add_private (object_class, sizeof (EphyZoomControlPrivate));
326 }
327
328 void
329 ephy_zoom_control_set_zoom_level (EphyZoomControl *control, float zoom)
330 {
331         g_return_if_fail (EPHY_IS_ZOOM_CONTROL (control));
332
333         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
334
335         control->priv->zoom = zoom;
336         g_object_notify (G_OBJECT (control), "zoom");
337 }
338
339 float
340 ephy_zoom_control_get_zoom_level (EphyZoomControl *control)
341 {
342         g_return_val_if_fail (EPHY_IS_ZOOM_CONTROL (control), 1.0);
343         
344         return control->priv->zoom;
345 }