]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/zoom-control/ephy-zoom-control.c
07bd030269daf6416ae472cfbbb4684cd24a51fb
[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         guint handler_id;
39 };
40
41 enum
42 {
43         COL_TEXT,
44         COL_IS_SEP
45 };
46
47 enum
48 {
49         PROP_0,
50         PROP_ZOOM
51 };
52
53 enum
54 {
55         ZOOM_TO_LEVEL_SIGNAL,
56         LAST_SIGNAL
57 };
58
59 static guint signals[LAST_SIGNAL];
60
61 G_DEFINE_TYPE (EphyZoomControl, ephy_zoom_control, GTK_TYPE_TOOL_ITEM)
62
63 static void
64 combo_changed_cb (GtkComboBox *combo, EphyZoomControl *control)
65 {
66         gint index;
67         float zoom;
68
69         index = gtk_combo_box_get_active (combo);
70         zoom = zoom_levels[index].level;
71
72         if (zoom != control->priv->zoom)
73         {
74                 g_signal_emit (control, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);        
75         }
76 }
77
78 static void
79 sync_zoom_cb (EphyZoomControl *control, GParamSpec *pspec, gpointer data)
80 {
81         EphyZoomControlPrivate *p = control->priv;
82         guint index;
83
84         index = ephy_zoom_get_zoom_level_index (p->zoom);
85
86         g_signal_handler_block (p->combo, p->handler_id);
87         gtk_combo_box_set_active (p->combo, index);
88         g_signal_handler_unblock (p->combo, p->handler_id);     
89 }
90
91 static gboolean
92 row_is_separator (GtkTreeModel *model,
93                   GtkTreeIter  *iter,
94                   gpointer      data)
95 {
96         gboolean is_sep;
97         gtk_tree_model_get (model, iter, COL_IS_SEP, &is_sep, -1);
98         return is_sep;
99 }
100
101 static void
102 ephy_zoom_control_finalize (GObject *o)
103 {
104         EphyZoomControl *control = EPHY_ZOOM_CONTROL (o);
105
106         g_object_unref (control->priv->combo);
107
108         G_OBJECT_CLASS (ephy_zoom_control_parent_class)->finalize (o);
109 }
110
111 static void
112 ephy_zoom_control_init (EphyZoomControl *control)
113 {
114         EphyZoomControlPrivate *p;
115         GtkWidget *vbox;
116         GtkCellRenderer *renderer;
117         GtkListStore    *store;
118         GtkTreeIter      iter;
119         guint i;
120
121         p = EPHY_ZOOM_CONTROL_GET_PRIVATE (control);
122         control->priv = p;
123
124         p->zoom = 1.0;
125
126         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
127
128         for (i = 0; i < n_zoom_levels; i++)
129         {
130                 gtk_list_store_append (store, &iter);
131
132                 if (zoom_levels[i].name != NULL) {
133                         gtk_list_store_set (store, &iter,
134                                             COL_TEXT, _(zoom_levels[i].name),
135                                             -1);
136                 } else {
137                         gtk_list_store_set (store, &iter,
138                                             COL_IS_SEP, zoom_levels[i].name == NULL,
139                                             -1);
140                 }
141         }
142
143         p->combo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)));
144         g_object_unref (store);
145
146         renderer = gtk_cell_renderer_text_new ();
147         gtk_cell_layout_pack_start     (GTK_CELL_LAYOUT (p->combo), renderer, TRUE);
148         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (p->combo), renderer,
149                                         "text", COL_TEXT, NULL);
150         gtk_combo_box_set_row_separator_func (p->combo,
151                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
152                                               NULL, NULL);
153
154         gtk_combo_box_set_focus_on_click (p->combo, FALSE);
155         g_object_ref_sink (G_OBJECT (p->combo));
156         gtk_widget_show (GTK_WIDGET (p->combo));
157
158         i = ephy_zoom_get_zoom_level_index (p->zoom);
159         gtk_combo_box_set_active (p->combo, i);
160
161         vbox = gtk_vbox_new (TRUE, 0);
162         gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (p->combo), TRUE, FALSE, 0);
163         gtk_widget_show (vbox);
164
165         gtk_container_add (GTK_CONTAINER (control), vbox);
166
167         p->handler_id = g_signal_connect (p->combo, "changed",
168                                           G_CALLBACK (combo_changed_cb), control);
169         
170         g_signal_connect_object (control, "notify::zoom",
171                                  G_CALLBACK (sync_zoom_cb), NULL, 0);
172 }
173
174 static void
175 ephy_zoom_control_set_property (GObject *object,
176                                 guint prop_id,
177                                 const GValue *value,
178                                 GParamSpec *pspec)
179 {
180         EphyZoomControl *control;
181         EphyZoomControlPrivate *p;
182
183         control = EPHY_ZOOM_CONTROL (object);
184         p = control->priv;
185
186         switch (prop_id)
187         {
188                 case PROP_ZOOM:
189                         p->zoom = g_value_get_float (value);
190                         break;
191         }
192 }
193
194 static void
195 ephy_zoom_control_get_property (GObject *object,
196                                 guint prop_id,
197                                 GValue *value,
198                                 GParamSpec *pspec)
199 {
200         EphyZoomControl *control;
201         EphyZoomControlPrivate *p;
202
203         control = EPHY_ZOOM_CONTROL (object);
204         p = control->priv;
205
206         switch (prop_id)
207         {
208                 case PROP_ZOOM:
209                         g_value_set_float (value, p->zoom);
210                         break;
211         }
212 }
213
214 static void
215 ephy_zoom_control_class_init (EphyZoomControlClass *klass)
216 {
217         GObjectClass *object_class;
218         GtkToolItemClass *tool_item_class;
219
220         object_class = (GObjectClass *)klass;
221         tool_item_class = (GtkToolItemClass *)klass;
222
223         object_class->set_property = ephy_zoom_control_set_property;
224         object_class->get_property = ephy_zoom_control_get_property;
225         object_class->finalize = ephy_zoom_control_finalize;
226
227         g_object_class_install_property (object_class,
228                                          PROP_ZOOM,
229                                          g_param_spec_float ("zoom",
230                                                              "Zoom",
231                                                              "Zoom level to display in the item.",
232                                                              ZOOM_MINIMAL,
233                                                              ZOOM_MAXIMAL,
234                                                              1.0,
235                                                              G_PARAM_READWRITE));
236
237         signals[ZOOM_TO_LEVEL_SIGNAL] =
238                 g_signal_new ("zoom_to_level",
239                               G_TYPE_FROM_CLASS (klass),
240                               G_SIGNAL_RUN_LAST,
241                               G_STRUCT_OFFSET (EphyZoomControlClass,
242                                                zoom_to_level),
243                               NULL, NULL,
244                               g_cclosure_marshal_VOID__FLOAT,
245                               G_TYPE_NONE,
246                               1,
247                               G_TYPE_FLOAT);
248
249         g_type_class_add_private (object_class, sizeof (EphyZoomControlPrivate));
250 }
251
252 void
253 ephy_zoom_control_set_zoom_level (EphyZoomControl *control, float zoom)
254 {
255         g_return_if_fail (EPHY_IS_ZOOM_CONTROL (control));
256
257         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
258
259         control->priv->zoom = zoom;
260         g_object_notify (G_OBJECT (control), "zoom");
261 }
262
263 float
264 ephy_zoom_control_get_zoom_level (EphyZoomControl *control)
265 {
266         g_return_val_if_fail (EPHY_IS_ZOOM_CONTROL (control), 1.0);
267         
268         return control->priv->zoom;
269 }