1/* GTK - The GIMP Toolkit
2 * Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19#include "gtk/gtk.h"
20#include "gtkmagnifierprivate.h"
21#include "gtkwidgetprivate.h"
22#include "gtksnapshot.h"
23#include "gtkintl.h"
24
25enum {
26 PROP_INSPECTED = 1,
27 PROP_RESIZE,
28 PROP_MAGNIFICATION
29};
30
31struct _GtkMagnifier
32{
33 GtkWidget parent_instance;
34
35 GdkPaintable *paintable;
36 double magnification;
37 int x;
38 int y;
39 gboolean resize;
40};
41
42typedef struct
43{
44 GtkWidgetClass parent_class;
45} GtkMagnifierClass;
46
47G_DEFINE_TYPE (GtkMagnifier, gtk_magnifier, GTK_TYPE_WIDGET)
48
49static void
50_gtk_magnifier_set_property (GObject *object,
51 guint param_id,
52 const GValue *value,
53 GParamSpec *pspec)
54{
55 GtkMagnifier *magnifier = GTK_MAGNIFIER (object);
56
57 switch (param_id)
58 {
59 case PROP_INSPECTED:
60 _gtk_magnifier_set_inspected (magnifier, inspected: g_value_get_object (value));
61 break;
62
63 case PROP_MAGNIFICATION:
64 _gtk_magnifier_set_magnification (magnifier, magnification: g_value_get_double (value));
65 break;
66
67 case PROP_RESIZE:
68 _gtk_magnifier_set_resize (magnifier, resize: g_value_get_boolean (value));
69 break;
70
71 default:
72 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
73 }
74}
75
76static void
77_gtk_magnifier_get_property (GObject *object,
78 guint param_id,
79 GValue *value,
80 GParamSpec *pspec)
81{
82 GtkMagnifier *magnifier = GTK_MAGNIFIER (object);
83
84 switch (param_id)
85 {
86 case PROP_INSPECTED:
87 g_value_set_object (value, v_object: gtk_widget_paintable_get_widget (self: GTK_WIDGET_PAINTABLE (ptr: magnifier->paintable)));
88 break;
89
90 case PROP_MAGNIFICATION:
91 g_value_set_double (value, v_double: magnifier->magnification);
92 break;
93
94 case PROP_RESIZE:
95 g_value_set_boolean (value, v_boolean: magnifier->resize);
96 break;
97
98 default:
99 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
100 }
101}
102
103static void
104gtk_magnifier_snapshot (GtkWidget *widget,
105 GtkSnapshot *snapshot)
106{
107 GtkMagnifier *magnifier = GTK_MAGNIFIER (widget);
108 double width, height, paintable_width, paintable_height;
109
110 if (gtk_widget_paintable_get_widget (self: GTK_WIDGET_PAINTABLE (ptr: magnifier->paintable)) == NULL)
111 return;
112
113 width = gtk_widget_get_width (widget);
114 height = gtk_widget_get_height (widget);
115 paintable_width = gdk_paintable_get_intrinsic_width (paintable: magnifier->paintable);
116 paintable_height = gdk_paintable_get_intrinsic_height (paintable: magnifier->paintable);
117 if (paintable_width <= 0.0 || paintable_height <= 0.0)
118 return;
119
120 gtk_snapshot_save (snapshot);
121 if (!magnifier->resize)
122 gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (width / 2, height / 2));
123 gtk_snapshot_scale (snapshot, factor_x: magnifier->magnification, factor_y: magnifier->magnification);
124 gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (
125 - CLAMP (magnifier->x, 0, paintable_width),
126 - CLAMP (magnifier->y, 0, paintable_height)));
127
128 gdk_paintable_snapshot (paintable: magnifier->paintable, snapshot, width: paintable_width, height: paintable_height);
129 gtk_snapshot_restore (snapshot);
130}
131
132static void
133gtk_magnifier_measure (GtkWidget *widget,
134 GtkOrientation orientation,
135 int for_size,
136 int *minimum,
137 int *natural,
138 int *minimum_baseline,
139 int *natural_baseline)
140{
141 GtkMagnifier *magnifier = GTK_MAGNIFIER (widget);
142 int size;
143
144 if (magnifier->resize)
145 {
146 if (orientation == GTK_ORIENTATION_HORIZONTAL)
147 size = magnifier->magnification * gdk_paintable_get_intrinsic_width (paintable: magnifier->paintable);
148 else
149 size = magnifier->magnification * gdk_paintable_get_intrinsic_height (paintable: magnifier->paintable);
150 }
151 else
152 size = 0;
153
154 *minimum = size;
155 *natural = size;
156}
157
158static void
159gtk_magnifier_dispose (GObject *object)
160{
161 GtkMagnifier *magnifier = GTK_MAGNIFIER (object);
162
163 if (magnifier->paintable)
164 _gtk_magnifier_set_inspected (magnifier, NULL);
165
166 g_clear_object (&magnifier->paintable);
167
168 G_OBJECT_CLASS (gtk_magnifier_parent_class)->dispose (object);
169}
170
171static void
172gtk_magnifier_class_init (GtkMagnifierClass *klass)
173{
174 GObjectClass *object_class = G_OBJECT_CLASS (klass);
175 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
176
177 object_class->set_property = _gtk_magnifier_set_property;
178 object_class->get_property = _gtk_magnifier_get_property;
179 object_class->dispose = gtk_magnifier_dispose;
180
181 widget_class->snapshot = gtk_magnifier_snapshot;
182 widget_class->measure = gtk_magnifier_measure;
183
184 g_object_class_install_property (oclass: object_class,
185 property_id: PROP_INSPECTED,
186 pspec: g_param_spec_object (name: "inspected",
187 P_("Inspected"),
188 P_("Inspected widget"),
189 GTK_TYPE_WIDGET,
190 flags: G_PARAM_READWRITE));
191 g_object_class_install_property (oclass: object_class,
192 property_id: PROP_MAGNIFICATION,
193 pspec: g_param_spec_double (name: "magnification",
194 P_("magnification"),
195 P_("magnification"),
196 minimum: 1, G_MAXDOUBLE, default_value: 1,
197 flags: G_PARAM_READWRITE));
198 g_object_class_install_property (oclass: object_class,
199 property_id: PROP_RESIZE,
200 pspec: g_param_spec_boolean (name: "resize",
201 P_("resize"),
202 P_("resize"),
203 FALSE,
204 flags: G_PARAM_READWRITE));
205
206 gtk_widget_class_set_css_name (widget_class, name: "magnifier");
207}
208
209static void
210gtk_magnifier_init (GtkMagnifier *magnifier)
211{
212 GtkWidget *widget = GTK_WIDGET (magnifier);
213
214 gtk_widget_set_overflow (widget, overflow: GTK_OVERFLOW_HIDDEN);
215
216 magnifier->magnification = 1;
217 magnifier->resize = FALSE;
218 magnifier->paintable = gtk_widget_paintable_new (NULL);
219 g_signal_connect_swapped (magnifier->paintable, "invalidate-contents", G_CALLBACK (gtk_widget_queue_draw), magnifier);
220 g_signal_connect_swapped (magnifier->paintable, "invalidate-size", G_CALLBACK (gtk_widget_queue_resize), magnifier);
221}
222
223GtkWidget *
224_gtk_magnifier_new (GtkWidget *inspected)
225{
226 g_return_val_if_fail (GTK_IS_WIDGET (inspected), NULL);
227
228 return g_object_new (GTK_TYPE_MAGNIFIER,
229 first_property_name: "inspected", inspected,
230 NULL);
231}
232
233GtkWidget *
234_gtk_magnifier_get_inspected (GtkMagnifier *magnifier)
235{
236 g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), NULL);
237
238 return gtk_widget_paintable_get_widget (self: GTK_WIDGET_PAINTABLE (ptr: magnifier->paintable));
239}
240
241void
242_gtk_magnifier_set_inspected (GtkMagnifier *magnifier,
243 GtkWidget *inspected)
244{
245 g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
246 g_return_if_fail (inspected == NULL || GTK_IS_WIDGET (inspected));
247
248 gtk_widget_paintable_set_widget (self: GTK_WIDGET_PAINTABLE (ptr: magnifier->paintable), widget: inspected);
249
250 g_object_notify (G_OBJECT (magnifier), property_name: "inspected");
251}
252
253void
254_gtk_magnifier_set_coords (GtkMagnifier *magnifier,
255 double x,
256 double y)
257{
258 g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
259
260 if (magnifier->x == x && magnifier->y == y)
261 return;
262
263 magnifier->x = x;
264 magnifier->y = y;
265
266 if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
267 gtk_widget_queue_draw (GTK_WIDGET (magnifier));
268}
269
270void
271_gtk_magnifier_get_coords (GtkMagnifier *magnifier,
272 double *x,
273 double *y)
274{
275 g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
276
277 if (x)
278 *x = magnifier->x;
279
280 if (y)
281 *y = magnifier->y;
282}
283
284void
285_gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
286 double magnification)
287{
288 g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
289
290 if (magnifier->magnification == magnification)
291 return;
292
293 magnifier->magnification = magnification;
294 g_object_notify (G_OBJECT (magnifier), property_name: "magnification");
295
296 if (magnifier->resize)
297 gtk_widget_queue_resize (GTK_WIDGET (magnifier));
298
299 if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
300 gtk_widget_queue_draw (GTK_WIDGET (magnifier));
301}
302
303double
304_gtk_magnifier_get_magnification (GtkMagnifier *magnifier)
305{
306 g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), 1);
307
308 return magnifier->magnification;
309}
310
311void
312_gtk_magnifier_set_resize (GtkMagnifier *magnifier,
313 gboolean resize)
314{
315 g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
316
317 if (magnifier->resize == resize)
318 return;
319
320 magnifier->resize = resize;
321
322 gtk_widget_queue_resize (GTK_WIDGET (magnifier));
323}
324
325gboolean
326_gtk_magnifier_get_resize (GtkMagnifier *magnifier)
327{
328 g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), FALSE);
329
330 return magnifier->resize;
331}
332

source code of gtk/gtk/gtkmagnifier.c