1 /*
2 * object-editor-size-page.c
3 * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
4 *
5 * This file is part of gLabels.
6 *
7 * gLabels 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 3 of the License, or
10 * (at your option) any later version.
11 *
12 * gLabels 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 gLabels. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22
23 #include "object-editor.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27 #include <math.h>
28
29 #include "prefs.h"
30 #include "wdgt-chain-button.h"
31 #include "builder-util.h"
32 #include "units-util.h"
33
34 #include "object-editor-private.h"
35
36 #include "debug.h"
37
38
39 /*===========================================*/
40 /* Private macros */
41 /*===========================================*/
42
43
44 /*===========================================*/
45 /* Private data types */
46 /*===========================================*/
47
48
49 /*===========================================*/
50 /* Private globals */
51 /*===========================================*/
52
53
54 /*===========================================*/
55 /* Local function prototypes */
56 /*===========================================*/
57
58 static void aspect_toggle_cb (glObjectEditor *editor);
59 static void size_reset_cb (glObjectEditor *editor);
60 static void w_spin_cb (glObjectEditor *editor);
61 static void h_spin_cb (glObjectEditor *editor);
62
63
64 /*--------------------------------------------------------------------------*/
65 /* PRIVATE. Prepare size page. */
66 /*--------------------------------------------------------------------------*/
67 void
gl_object_editor_prepare_size_page(glObjectEditor * editor)68 gl_object_editor_prepare_size_page (glObjectEditor *editor)
69 {
70 lglUnits units;
71 const gchar *units_string;
72 gdouble climb_rate;
73 gint digits;
74
75 gl_debug (DEBUG_EDITOR, "START");
76
77 /* Extract widgets from XML tree. */
78 gl_builder_util_get_widgets (editor->priv->builder,
79 "size_page_vbox", &editor->priv->size_page_vbox,
80 "size_w_spin", &editor->priv->size_w_spin,
81 "size_h_spin", &editor->priv->size_h_spin,
82 "size_w_units_label", &editor->priv->size_w_units_label,
83 "size_h_units_label", &editor->priv->size_h_units_label,
84 "size_aspect_vbox", &editor->priv->size_aspect_vbox,
85 "size_reset_image_button", &editor->priv->size_reset_image_button,
86 NULL);
87
88 editor->priv->size_aspect_checkbutton = gl_wdgt_chain_button_new (GL_WDGT_CHAIN_RIGHT);
89 gtk_widget_set_tooltip_text (editor->priv->size_aspect_checkbutton, _("Lock aspect ratio."));
90 gl_wdgt_chain_button_set_active (GL_WDGT_CHAIN_BUTTON(editor->priv->size_aspect_checkbutton),
91 TRUE);
92 gtk_box_pack_start (GTK_BOX (editor->priv->size_aspect_vbox),
93 editor->priv->size_aspect_checkbutton,
94 TRUE, TRUE, 0);
95
96
97 /* Get configuration information */
98 units = gl_prefs_model_get_units (gl_prefs);
99 units_string = lgl_units_get_name (units);
100 editor->priv->units_per_point = lgl_units_get_units_per_point (units);
101 climb_rate = gl_units_util_get_step_size (units);
102 digits = gl_units_util_get_precision (units);
103
104 /* Modify widgets based on configuration */
105 gtk_spin_button_set_digits (GTK_SPIN_BUTTON(editor->priv->size_w_spin), digits);
106 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(editor->priv->size_w_spin),
107 climb_rate, 10.0*climb_rate);
108 gtk_label_set_text (GTK_LABEL(editor->priv->size_w_units_label), units_string);
109 gtk_spin_button_set_digits (GTK_SPIN_BUTTON(editor->priv->size_h_spin), digits);
110 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(editor->priv->size_h_spin),
111 climb_rate, 10.0*climb_rate);
112 gtk_label_set_text (GTK_LABEL(editor->priv->size_h_units_label), units_string);
113
114
115 /* Connect signals */
116 g_signal_connect_swapped (G_OBJECT (editor->priv->size_aspect_checkbutton),
117 "toggled",
118 G_CALLBACK (aspect_toggle_cb),
119 G_OBJECT (editor));
120 g_signal_connect_swapped (G_OBJECT (editor->priv->size_w_spin),
121 "value-changed",
122 G_CALLBACK (w_spin_cb),
123 G_OBJECT (editor));
124 g_signal_connect_swapped (G_OBJECT (editor->priv->size_h_spin),
125 "value-changed",
126 G_CALLBACK (h_spin_cb),
127 G_OBJECT (editor));
128 g_signal_connect_swapped (G_OBJECT (editor->priv->size_reset_image_button),
129 "clicked",
130 G_CALLBACK (size_reset_cb),
131 G_OBJECT (editor));
132
133 gl_debug (DEBUG_EDITOR, "END");
134 }
135
136
137 /*--------------------------------------------------------------------------*/
138 /* PRIVATE. Maintain aspect ratio checkbox callback. */
139 /*--------------------------------------------------------------------------*/
140 static void
aspect_toggle_cb(glObjectEditor * editor)141 aspect_toggle_cb (glObjectEditor *editor)
142 {
143 glWdgtChainButton *toggle;
144 gdouble w, h;
145
146 gl_debug (DEBUG_EDITOR, "START");
147
148 toggle = GL_WDGT_CHAIN_BUTTON (editor->priv->size_aspect_checkbutton);
149
150 if (gl_wdgt_chain_button_get_active (toggle)) {
151
152 w = gtk_spin_button_get_value (GTK_SPIN_BUTTON(editor->priv->size_w_spin));
153 h = gtk_spin_button_get_value (GTK_SPIN_BUTTON(editor->priv->size_h_spin));
154
155 editor->priv->size_aspect_ratio = h / w;
156
157 }
158
159 gl_debug (DEBUG_EDITOR, "END");
160 }
161
162
163 /*--------------------------------------------------------------------------*/
164 /* PRIVATE. W spin button changed callback. */
165 /*--------------------------------------------------------------------------*/
166 static void
w_spin_cb(glObjectEditor * editor)167 w_spin_cb (glObjectEditor *editor)
168 {
169 gdouble w, h;
170 glWdgtChainButton *toggle;
171
172 gl_debug (DEBUG_EDITOR, "START");
173
174 toggle = GL_WDGT_CHAIN_BUTTON (editor->priv->size_aspect_checkbutton);
175
176 if (gl_wdgt_chain_button_get_active (toggle)) {
177
178 w = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin));
179
180 h = w * editor->priv->size_aspect_ratio;
181
182 /* Update our sibling control, blocking recursion. */
183 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
184 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin), h);
185 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
186 }
187
188 gl_object_editor_size_changed_cb (editor);
189
190 gl_debug (DEBUG_EDITOR, "END");
191 }
192
193
194 /*--------------------------------------------------------------------------*/
195 /* PRIVATE. H spin button changed callback. */
196 /*--------------------------------------------------------------------------*/
197 static void
h_spin_cb(glObjectEditor * editor)198 h_spin_cb (glObjectEditor *editor)
199 {
200 gdouble w, h;
201 glWdgtChainButton *toggle;
202
203 gl_debug (DEBUG_EDITOR, "START");
204
205 toggle = GL_WDGT_CHAIN_BUTTON (editor->priv->size_aspect_checkbutton);
206
207 if (gl_wdgt_chain_button_get_active (toggle)) {
208
209 h = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin));
210
211 w = h / editor->priv->size_aspect_ratio;
212
213 /* Update our sibling control, blocking recursion. */
214 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
215 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin), w);
216 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
217 }
218
219 gl_object_editor_size_changed_cb (editor);
220
221 gl_debug (DEBUG_EDITOR, "END");
222 }
223
224
225 /*--------------------------------------------------------------------------*/
226 /* PRIVATE. Reset image size callback. */
227 /*--------------------------------------------------------------------------*/
228 static void
size_reset_cb(glObjectEditor * editor)229 size_reset_cb (glObjectEditor *editor)
230 {
231 gdouble w_base, h_base;
232 gdouble w_max, h_max, wh_max;
233 gdouble aspect_ratio;
234
235 gl_debug (DEBUG_EDITOR, "START");
236
237
238 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
239 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
240
241
242 w_base = editor->priv->w_base;
243 h_base = editor->priv->h_base;
244
245 w_max = editor->priv->w_max;
246 h_max = editor->priv->h_max;
247 wh_max = MAX( w_max, h_max );
248
249 if ( (w_base > wh_max) || (h_base > wh_max) ) {
250
251 aspect_ratio = h_base / w_base;
252
253 if ( aspect_ratio < 1.0 ) {
254 w_base = wh_max;
255 h_base = wh_max * aspect_ratio;
256
257 } else {
258 w_base = wh_max / aspect_ratio;
259 h_base = wh_max;
260 }
261 }
262
263 w_base *= editor->priv->units_per_point;
264 h_base *= editor->priv->units_per_point;
265
266 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin),
267 w_base);
268 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin),
269 h_base);
270
271
272 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
273 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
274
275
276 gl_object_editor_size_changed_cb (editor);
277
278 gl_debug (DEBUG_EDITOR, "END");
279 }
280
281
282 /*****************************************************************************/
283 /* Set size. */
284 /*****************************************************************************/
285 void
gl_object_editor_set_size(glObjectEditor * editor,gdouble w,gdouble h)286 gl_object_editor_set_size (glObjectEditor *editor,
287 gdouble w,
288 gdouble h)
289 {
290 gl_debug (DEBUG_EDITOR, "START");
291
292
293 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
294 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
295
296
297 /* save a copy in internal units */
298 editor->priv->w = w;
299 editor->priv->h = h;
300
301 /* convert internal units to displayed units */
302 gl_debug (DEBUG_EDITOR, "internal w,h = %g, %g", w, h);
303 w *= editor->priv->units_per_point;
304 h *= editor->priv->units_per_point;
305 gl_debug (DEBUG_EDITOR, "display w,h = %g, %g", w, h);
306
307 /* Set widget values */
308 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin), w);
309 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin), h);
310
311 /* Update aspect ratio */
312 editor->priv->size_aspect_ratio = h / w;
313
314
315 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
316 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
317
318
319 gl_debug (DEBUG_EDITOR, "END");
320 }
321
322
323 /*****************************************************************************/
324 /* Set maximum size. */
325 /*****************************************************************************/
326 void
gl_object_editor_set_max_size(glObjectEditor * editor,gdouble w_max,gdouble h_max)327 gl_object_editor_set_max_size (glObjectEditor *editor,
328 gdouble w_max,
329 gdouble h_max)
330 {
331 gdouble tmp;
332 gdouble wh_max;
333
334 gl_debug (DEBUG_EDITOR, "START");
335
336
337 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
338 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
339
340
341 /* save a copy in internal units */
342 editor->priv->w_max = w_max;
343 editor->priv->h_max = h_max;
344
345 /* convert internal units to displayed units */
346 gl_debug (DEBUG_EDITOR, "internal w_max,h_max = %g, %g", w_max, h_max);
347 w_max *= editor->priv->units_per_point;
348 h_max *= editor->priv->units_per_point;
349 wh_max = MAX( w_max, h_max );
350 gl_debug (DEBUG_EDITOR, "display w_max,h_max = %g, %g", w_max, h_max);
351
352 /* Set widget values */
353 tmp = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin));
354 gtk_spin_button_set_range (GTK_SPIN_BUTTON (editor->priv->size_w_spin),
355 0.0, 2.0*wh_max);
356 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin), tmp);
357 tmp = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin));
358 gtk_spin_button_set_range (GTK_SPIN_BUTTON (editor->priv->size_h_spin),
359 0.0, 2.0*wh_max);
360 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin), tmp);
361
362
363 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
364 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
365
366
367 gl_debug (DEBUG_EDITOR, "END");
368 }
369
370
371 /*****************************************************************************/
372 /* Set base or natural size of image. */
373 /*****************************************************************************/
374 void
gl_object_editor_set_base_size(glObjectEditor * editor,gdouble w_base,gdouble h_base)375 gl_object_editor_set_base_size (glObjectEditor *editor,
376 gdouble w_base,
377 gdouble h_base)
378 {
379 gl_debug (DEBUG_EDITOR, "Setting w_base = %g", w_base);
380 gl_debug (DEBUG_EDITOR, "Setting h_base = %g", h_base);
381
382 editor->priv->w_base = w_base;
383 editor->priv->h_base = h_base;
384 }
385
386
387 /*****************************************************************************/
388 /* Query size. */
389 /*****************************************************************************/
390 void
gl_object_editor_get_size(glObjectEditor * editor,gdouble * w,gdouble * h)391 gl_object_editor_get_size (glObjectEditor *editor,
392 gdouble *w,
393 gdouble *h)
394 {
395 gl_debug (DEBUG_EDITOR, "START");
396
397
398 /* Get values from widgets */
399 *w = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_w_spin));
400 *h = gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->priv->size_h_spin));
401
402 /* convert everything back to our internal units (points) */
403 *w /= editor->priv->units_per_point;
404 *h /= editor->priv->units_per_point;
405
406 /* save a copy in internal units */
407 editor->priv->w = *w;
408 editor->priv->h = *h;
409
410 gl_debug (DEBUG_EDITOR, "END");
411 }
412
413
414 /*****************************************************************************/
415 /* PRIVATE. Prefs changed callback. Update units related items. */
416 /*****************************************************************************/
417 void
size_prefs_changed_cb(glObjectEditor * editor)418 size_prefs_changed_cb (glObjectEditor *editor)
419 {
420 lglUnits units;
421 const gchar *units_string;
422 gdouble climb_rate;
423 gint digits;
424
425 gl_debug (DEBUG_EDITOR, "START");
426
427
428 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
429 g_signal_handlers_block_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
430
431
432 /* Get new configuration information */
433 units = gl_prefs_model_get_units (gl_prefs);
434 units_string = lgl_units_get_name (units);
435 editor->priv->units_per_point = lgl_units_get_units_per_point (units);
436 climb_rate = gl_units_util_get_step_size (units);
437 digits = gl_units_util_get_precision (units);
438
439 /* Update characteristics of w_spin/h_spin */
440 gtk_spin_button_set_digits (GTK_SPIN_BUTTON(editor->priv->size_w_spin), digits);
441 gtk_spin_button_set_digits (GTK_SPIN_BUTTON(editor->priv->size_h_spin), digits);
442 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(editor->priv->size_w_spin),
443 climb_rate, 10.0*climb_rate);
444 gtk_spin_button_set_increments (GTK_SPIN_BUTTON(editor->priv->size_h_spin),
445 climb_rate, 10.0*climb_rate);
446
447 /* Update units_labels */
448 gtk_label_set_text (GTK_LABEL(editor->priv->size_w_units_label),
449 units_string);
450 gtk_label_set_text (GTK_LABEL(editor->priv->size_h_units_label),
451 units_string);
452
453 /* Update values of w_spin/h_spin */
454 gl_object_editor_set_size (editor, editor->priv->w, editor->priv->h);
455 gl_object_editor_set_max_size (editor, editor->priv->w_max, editor->priv->h_max);
456
457
458 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_w_spin), w_spin_cb, editor);
459 g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->size_h_spin), h_spin_cb, editor);
460
461
462 gl_debug (DEBUG_EDITOR, "END");
463 }
464
465
466
467 /*
468 * Local Variables: -- emacs
469 * mode: C -- emacs
470 * c-basic-offset: 8 -- emacs
471 * tab-width: 8 -- emacs
472 * indent-tabs-mode: nil -- emacs
473 * End: -- emacs
474 */
475