]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/zoom-control/ephy-zoom-action.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / cut-n-paste / zoom-control / ephy-zoom-action.c
1 /*
2  *  Copyright (C) 2003 Marco Pesenti Gritti
3  *  Copyright (C) 2003, 2004 Christian Persch
4  *
5  *  Modified 2005 by James Bowes for use in evince.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  *  $Id$
22  */
23
24 #include "config.h"
25
26 #include "ephy-zoom-action.h"
27 #include "ephy-zoom-control.h"
28 #include "ephy-zoom.h"
29
30 #include <glib-object.h>
31 #include <glib/gi18n.h>
32 #include <gtk/gtk.h>
33
34 #define EPHY_ZOOM_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ZOOM_ACTION, EphyZoomActionPrivate))
35
36 struct _EphyZoomActionPrivate
37 {
38         float zoom;
39         float min_zoom;
40         float max_zoom;
41 };
42
43 enum
44 {
45         PROP_0,
46         PROP_ZOOM,
47         PROP_MIN_ZOOM,
48         PROP_MAX_ZOOM
49 };
50
51
52 static void ephy_zoom_action_init       (EphyZoomAction *action);
53 static void ephy_zoom_action_class_init (EphyZoomActionClass *class);
54
55 enum
56 {
57         ZOOM_TO_LEVEL_SIGNAL,
58         LAST_SIGNAL
59 };
60
61 static guint signals[LAST_SIGNAL] = { 0 };
62
63 G_DEFINE_TYPE (EphyZoomAction, ephy_zoom_action, GTK_TYPE_ACTION)
64
65 static void
66 zoom_to_level_cb (EphyZoomControl *control,
67                   float zoom,
68                   EphyZoomAction *action)
69 {
70         g_signal_emit (action, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);
71 }
72
73 static void
74 sync_zoom_cb (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
75 {
76         EphyZoomAction *zoom_action = EPHY_ZOOM_ACTION (action);
77
78         g_object_set (G_OBJECT (proxy), "zoom", zoom_action->priv->zoom, NULL);
79 }
80
81 static void
82 sync_min_zoom_cb (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
83 {
84         EphyZoomAction *zoom_action = EPHY_ZOOM_ACTION (action);
85
86         g_object_set (G_OBJECT (proxy), "min-zoom", zoom_action->priv->min_zoom, NULL);
87 }
88
89 static void
90 sync_max_zoom_cb (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
91 {
92         EphyZoomAction *zoom_action = EPHY_ZOOM_ACTION (action);
93
94         g_object_set (G_OBJECT (proxy), "max-zoom", zoom_action->priv->max_zoom, NULL);
95 }
96
97 static void
98 connect_proxy (GtkAction *action, GtkWidget *proxy)
99 {
100         if (EPHY_IS_ZOOM_CONTROL (proxy))
101         {
102                 g_signal_connect_object (action, "notify::zoom",
103                                          G_CALLBACK (sync_zoom_cb), proxy, 0);
104                 g_signal_connect_object (action, "notify::min-zoom",
105                                          G_CALLBACK (sync_min_zoom_cb), proxy, 0);
106                 g_signal_connect_object (action, "notify::max-zoom",
107                                          G_CALLBACK (sync_max_zoom_cb), proxy, 0);
108                 g_signal_connect (proxy, "zoom_to_level",
109                                   G_CALLBACK (zoom_to_level_cb), action);
110         }
111
112         GTK_ACTION_CLASS (ephy_zoom_action_parent_class)->connect_proxy (action, proxy);
113 }
114
115 static void
116 proxy_menu_activate_cb (GtkMenuItem *menu_item, EphyZoomAction *action)
117 {
118         gint index;
119         float zoom;
120
121         /* menu item was toggled OFF */
122         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item))) return;
123
124         index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "zoom-level"));
125         zoom = zoom_levels[index].level;
126
127         if (zoom != action->priv->zoom)
128         {
129                 g_signal_emit (action, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);
130         }
131 }
132
133 static GtkWidget *
134 create_menu_item (GtkAction *action)
135 {
136         EphyZoomActionPrivate *p = EPHY_ZOOM_ACTION (action)->priv;
137         GtkWidget *menu, *menu_item;
138         GSList *group = NULL;
139         int i;
140
141         menu = gtk_menu_new ();
142
143         for (i = 0; i < n_zoom_levels; i++)
144         {
145                 if (zoom_levels[i].level == EPHY_ZOOM_SEPARATOR) 
146                 {
147                         menu_item = gtk_separator_menu_item_new ();
148                 } 
149                 else 
150                 {
151                         menu_item = gtk_radio_menu_item_new_with_label (group, 
152                                                                         _(zoom_levels[i].name));
153                         group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
154
155                         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
156                                                         p->zoom == zoom_levels[i].level);
157         
158                         g_object_set_data (G_OBJECT (menu_item), "zoom-level", GINT_TO_POINTER (i));
159                         g_signal_connect_object (G_OBJECT (menu_item), "activate",
160                                                 G_CALLBACK (proxy_menu_activate_cb), action, 0);
161                 }
162         
163                 gtk_widget_show (menu_item);
164                 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
165         }
166
167         gtk_widget_show (menu);
168
169         menu_item = GTK_ACTION_CLASS (ephy_zoom_action_parent_class)->create_menu_item (action);
170
171         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
172
173         gtk_widget_show (menu_item);
174
175         return menu_item;
176 }
177
178 static void
179 ephy_zoom_action_set_property (GObject *object,
180                                guint prop_id,
181                                const GValue *value,
182                                GParamSpec *pspec)
183 {
184         EphyZoomAction *action;
185
186         action = EPHY_ZOOM_ACTION (object);
187
188         switch (prop_id)
189         {
190                 case PROP_ZOOM:
191                         action->priv->zoom = g_value_get_float (value);
192                         break;
193                 case PROP_MIN_ZOOM:
194                         action->priv->min_zoom = g_value_get_float (value);
195                         break;
196                 case PROP_MAX_ZOOM:
197                         action->priv->max_zoom = g_value_get_float (value);
198                         break;
199         }
200 }
201
202 static void
203 ephy_zoom_action_get_property (GObject *object,
204                                guint prop_id,
205                                GValue *value,
206                                GParamSpec *pspec)
207 {
208         EphyZoomAction *action;
209
210         action = EPHY_ZOOM_ACTION (object);
211
212         switch (prop_id)
213         {
214                 case PROP_ZOOM:
215                         g_value_set_float (value, action->priv->zoom);
216                         break;
217                 case PROP_MIN_ZOOM:
218                         g_value_set_float (value, action->priv->min_zoom);
219                         break;
220                 case PROP_MAX_ZOOM:
221                         g_value_set_float (value, action->priv->max_zoom);
222                         break;
223         }
224 }
225
226 static void
227 ephy_zoom_action_class_init (EphyZoomActionClass *class)
228 {
229         GObjectClass *object_class = G_OBJECT_CLASS (class);
230         GtkActionClass *action_class = GTK_ACTION_CLASS (class);
231
232         object_class->set_property = ephy_zoom_action_set_property;
233         object_class->get_property = ephy_zoom_action_get_property;
234
235         action_class->toolbar_item_type = EPHY_TYPE_ZOOM_CONTROL;
236         action_class->connect_proxy = connect_proxy;
237         action_class->create_menu_item = create_menu_item;
238
239         g_object_class_install_property (object_class,
240                                          PROP_ZOOM,
241                                          g_param_spec_float ("zoom",
242                                                              "Zoom",
243                                                              "Zoom",
244                                                              ZOOM_MINIMAL,
245                                                              ZOOM_MAXIMAL,
246                                                              1.0,
247                                                              G_PARAM_READWRITE));
248         g_object_class_install_property (object_class,
249                                          PROP_MIN_ZOOM,
250                                          g_param_spec_float ("min-zoom",
251                                                              "MinZoom",
252                                                              "The minimum zoom",
253                                                              ZOOM_MINIMAL,
254                                                              ZOOM_MAXIMAL,
255                                                              ZOOM_MINIMAL,
256                                                              G_PARAM_READWRITE));
257         g_object_class_install_property (object_class,
258                                          PROP_MAX_ZOOM,
259                                          g_param_spec_float ("max-zoom",
260                                                              "MaxZoom",
261                                                              "The maximum zoom",
262                                                              ZOOM_MINIMAL,
263                                                              ZOOM_MAXIMAL,
264                                                              ZOOM_MAXIMAL,
265                                                              G_PARAM_READWRITE));
266
267         signals[ZOOM_TO_LEVEL_SIGNAL] =
268                 g_signal_new ("zoom_to_level",
269                               G_OBJECT_CLASS_TYPE (object_class),
270                               G_SIGNAL_RUN_FIRST,
271                               G_STRUCT_OFFSET (EphyZoomActionClass, zoom_to_level),
272                               NULL, NULL,
273                               g_cclosure_marshal_VOID__FLOAT,
274                               G_TYPE_NONE,
275                               1,
276                               G_TYPE_FLOAT);
277
278         g_type_class_add_private (object_class, sizeof (EphyZoomActionPrivate));
279 }
280
281 static void
282 ephy_zoom_action_init (EphyZoomAction *action)
283 {
284         action->priv = EPHY_ZOOM_ACTION_GET_PRIVATE (action);
285
286         action->priv->zoom = 1.0;
287 }
288
289 void
290 ephy_zoom_action_set_zoom_level (EphyZoomAction *action, float zoom)
291 {
292         g_return_if_fail (EPHY_IS_ZOOM_ACTION (action));
293
294         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
295
296         action->priv->zoom = zoom;
297         g_object_notify (G_OBJECT (action), "zoom");
298 }
299
300 float
301 ephy_zoom_action_get_zoom_level (EphyZoomAction *action)
302 {
303         g_return_val_if_fail (EPHY_IS_ZOOM_ACTION (action), 1.0);
304         
305         return action->priv->zoom;
306 }
307
308 void
309 ephy_zoom_action_set_min_zoom_level (EphyZoomAction *action,
310                                      float           zoom)
311 {
312         g_return_if_fail (EPHY_IS_ZOOM_ACTION (action));
313
314         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
315
316         action->priv->min_zoom = zoom;
317         if (action->priv->zoom > 0 && action->priv->zoom < zoom)
318                 ephy_zoom_action_set_zoom_level (action, zoom);
319
320         g_object_notify (G_OBJECT (action), "min-zoom");
321 }
322
323 void
324 ephy_zoom_action_set_max_zoom_level (EphyZoomAction *action,
325                                      float           zoom)
326 {
327         g_return_if_fail (EPHY_IS_ZOOM_ACTION (action));
328
329         if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
330
331         action->priv->max_zoom = zoom;
332         if (action->priv->zoom > 0 && action->priv->zoom > zoom)
333                 ephy_zoom_action_set_zoom_level (action, zoom);
334
335         g_object_notify (G_OBJECT (action), "max-zoom");
336 }