2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * wdgt_size.c: size properties widget module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wdgt-size.h"
31 /*===========================================*/
33 /*===========================================*/
40 typedef void (*glWdgtSizeSignal) (GObject * object, gpointer data);
42 /*===========================================*/
44 /*===========================================*/
46 static GObjectClass *parent_class;
48 static gint wdgt_size_signals[LAST_SIGNAL] = { 0 };
50 /*===========================================*/
51 /* Local function prototypes */
52 /*===========================================*/
54 static void gl_wdgt_size_class_init (glWdgtSizeClass * class);
55 static void gl_wdgt_size_instance_init (glWdgtSize * size);
56 static void gl_wdgt_size_finalize (GObject * object);
57 static void gl_wdgt_size_construct (glWdgtSize * size, gchar * label);
59 static void aspect_toggle_cb (GtkToggleButton * togglebutton,
61 static void w_spin_cb (GtkSpinButton * spinbutton, gpointer user_data);
62 static void h_spin_cb (GtkSpinButton * spinbutton, gpointer user_data);
64 /*================================================================*/
65 /* Boilerplate Object stuff. */
66 /*================================================================*/
68 gl_wdgt_size_get_type (void)
70 static guint wdgt_size_type = 0;
72 if (!wdgt_size_type) {
73 GTypeInfo wdgt_size_info = {
74 sizeof (glWdgtSizeClass),
77 (GClassInitFunc) gl_wdgt_size_class_init,
82 (GInstanceInitFunc) gl_wdgt_size_instance_init,
86 g_type_register_static (gtk_vbox_get_type (),
87 "glWdgtSize", &wdgt_size_info, 0);
90 return wdgt_size_type;
94 gl_wdgt_size_class_init (glWdgtSizeClass * class)
96 GObjectClass *object_class;
98 object_class = (GObjectClass *) class;
100 parent_class = gtk_type_class (gtk_vbox_get_type ());
102 object_class->finalize = gl_wdgt_size_finalize;
104 wdgt_size_signals[CHANGED] =
105 g_signal_new ("changed",
106 G_OBJECT_CLASS_TYPE(object_class),
108 G_STRUCT_OFFSET (glWdgtSizeClass, changed),
110 gl_marshal_VOID__VOID,
116 gl_wdgt_size_instance_init (glWdgtSize * size)
118 size->aspect_ratio = 1.0;
123 size->units_label = NULL;
125 size->aspect_checkbox = NULL;
129 gl_wdgt_size_finalize (GObject * object)
132 glWdgtSizeClass *class;
134 g_return_if_fail (object != NULL);
135 g_return_if_fail (GL_IS_WDGT_SIZE (object));
137 size = GL_WDGT_SIZE (object);
139 G_OBJECT_CLASS (parent_class)->finalize (object);
143 gl_wdgt_size_new (gchar * label)
147 size = g_object_new (gl_wdgt_size_get_type (), NULL);
149 gl_wdgt_size_construct (size, label);
151 return GTK_WIDGET (size);
154 /*============================================================*/
155 /* Construct composite widget. */
156 /*============================================================*/
158 gl_wdgt_size_construct (glWdgtSize * size,
161 GtkWidget *wvbox, *wframe, *wtable, *wlabel;
162 GtkObject *w_adjust, *h_adjust;
163 const gchar *units_string;
164 gdouble units_per_point, climb_rate;
167 units_string = gl_prefs_get_units_string ();
168 units_per_point = gl_prefs_get_units_per_point ();
169 climb_rate = gl_prefs_get_units_step_size ();
170 digits = gl_prefs_get_units_precision ();
172 wvbox = GTK_WIDGET (size);
174 wframe = gtk_frame_new (label);
175 gtk_box_pack_start (GTK_BOX (wvbox), wframe, FALSE, FALSE, 0);
177 wtable = gtk_table_new (3, 3, TRUE);
178 gtk_container_set_border_width (GTK_CONTAINER (wtable), 10);
179 gtk_table_set_row_spacings (GTK_TABLE (wtable), 5);
180 gtk_table_set_col_spacings (GTK_TABLE (wtable), 5);
181 gtk_container_add (GTK_CONTAINER (wframe), wtable);
184 wlabel = gtk_label_new (_("Width:"));
185 gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
186 gtk_label_set_justify (GTK_LABEL (wlabel), GTK_JUSTIFY_RIGHT);
187 gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 0, 1);
189 w_adjust = gtk_adjustment_new (climb_rate, climb_rate, 100.0,
190 climb_rate, 10.0, 10.0);
191 size->w_spin = gtk_spin_button_new (GTK_ADJUSTMENT (w_adjust),
193 gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (size->w_spin),
195 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (size->w_spin), TRUE);
196 gtk_table_attach_defaults (GTK_TABLE (wtable), size->w_spin,
200 wlabel = gtk_label_new (_("Height:"));
201 gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
202 gtk_label_set_justify (GTK_LABEL (wlabel), GTK_JUSTIFY_RIGHT);
203 gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 1, 2);
205 h_adjust = gtk_adjustment_new (climb_rate, climb_rate,
206 100.0, climb_rate, 10.0, 10.0);
207 size->h_spin = gtk_spin_button_new (GTK_ADJUSTMENT (h_adjust),
209 gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (size->h_spin),
211 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (size->h_spin), TRUE);
212 gtk_table_attach_defaults (GTK_TABLE (wtable), size->h_spin,
216 size->units_label = gtk_label_new (units_string);
217 gtk_misc_set_alignment (GTK_MISC (size->units_label), 0, 0.5);
218 gtk_table_attach_defaults (GTK_TABLE (wtable),
219 size->units_label, 2, 3, 1, 2);
221 /* Maintain aspect ratio checkbox */
222 size->aspect_checkbox =
223 gtk_check_button_new_with_label (_
224 ("Maintain current aspect ratio"));
225 gtk_table_attach_defaults (GTK_TABLE (wtable), size->aspect_checkbox, 0,
228 /* Connect signals to controls */
229 g_signal_connect (G_OBJECT (size->aspect_checkbox), "toggled",
230 G_CALLBACK (aspect_toggle_cb), size);
231 g_signal_connect (G_OBJECT (size->w_spin), "changed",
232 G_CALLBACK (w_spin_cb), size);
233 g_signal_connect (G_OBJECT (size->h_spin), "changed",
234 G_CALLBACK (h_spin_cb), size);
237 /*--------------------------------------------------------------------------*/
238 /* PRIVATE. Maintain aspect ratio checkbox callback. */
239 /*--------------------------------------------------------------------------*/
241 aspect_toggle_cb (GtkToggleButton * togglebutton,
244 glWdgtSize *size = GL_WDGT_SIZE (user_data);
245 GtkAdjustment *w_adjust, *h_adjust;
247 if (gtk_toggle_button_get_active (togglebutton)) {
250 gtk_spin_button_get_value (GTK_SPIN_BUTTON(size->w_spin));
252 gtk_spin_button_get_value (GTK_SPIN_BUTTON(size->h_spin));
254 size->aspect_ratio = size->h / size->w;
256 /* We have a new aspect ratio, adjust one of the maxes accordingly */
257 if ((size->h_max_orig / size->w_max_orig) < size->aspect_ratio) {
258 size->w_max = size->h_max_orig / size->aspect_ratio;
259 size->h_max = size->h_max_orig;
261 size->w_max = size->w_max_orig;
262 size->h_max = size->w_max_orig * size->aspect_ratio;
268 size->w_max = size->w_max_orig;
269 size->h_max = size->h_max_orig;
273 g_signal_handlers_block_by_func (GTK_OBJECT (size->w_spin),
274 G_CALLBACK (w_spin_cb),
276 g_signal_handlers_block_by_func (GTK_OBJECT (size->h_spin),
277 G_CALLBACK (h_spin_cb),
280 gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (size->w_spin));
281 w_adjust->upper = size->w_max;
282 gtk_spin_button_update (GTK_SPIN_BUTTON (size->w_spin));
284 gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (size->h_spin));
285 h_adjust->upper = size->h_max;
286 gtk_spin_button_update (GTK_SPIN_BUTTON (size->h_spin));
287 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->w_spin),
288 G_CALLBACK (w_spin_cb),
290 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->h_spin),
291 G_CALLBACK (h_spin_cb),
294 /* Emit our "changed" signal */
295 g_signal_emit (G_OBJECT (size), wdgt_size_signals[CHANGED], 0);
299 /*--------------------------------------------------------------------------*/
300 /* PRIVATE. W spin button changed callback. */
301 /*--------------------------------------------------------------------------*/
303 w_spin_cb (GtkSpinButton * spinbutton,
306 glWdgtSize *size = GL_WDGT_SIZE (user_data);
307 GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (size->aspect_checkbox);
310 gtk_spin_button_get_value (GTK_SPIN_BUTTON (size->w_spin));
312 if (gtk_toggle_button_get_active (toggle)) {
314 size->h = size->w * size->aspect_ratio;
316 /* Update our sibling control, blocking recursion. */
317 g_signal_handlers_block_by_func (GTK_OBJECT (size->h_spin),
318 G_CALLBACK (h_spin_cb),
320 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->h_spin),
322 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->h_spin),
323 G_CALLBACK (h_spin_cb),
327 /* Emit our "changed" signal */
328 g_signal_emit (G_OBJECT (size), wdgt_size_signals[CHANGED], 0);
332 /*--------------------------------------------------------------------------*/
333 /* PRIVATE. H spin button changed callback. */
334 /*--------------------------------------------------------------------------*/
336 h_spin_cb (GtkSpinButton * spinbutton,
339 glWdgtSize *size = GL_WDGT_SIZE (user_data);
340 GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (size->aspect_checkbox);
343 gtk_spin_button_get_value (GTK_SPIN_BUTTON (size->h_spin));
345 if (gtk_toggle_button_get_active (toggle)) {
347 size->w = size->h / size->aspect_ratio;
349 /* Update our sibling control, blocking recursion. */
350 g_signal_handlers_block_by_func (GTK_OBJECT (size->w_spin),
351 G_CALLBACK (w_spin_cb),
353 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->w_spin),
355 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->w_spin),
356 G_CALLBACK (w_spin_cb),
360 /* Emit our "changed" signal */
361 g_signal_emit (G_OBJECT (size), wdgt_size_signals[CHANGED], 0);
365 /*====================================================================*/
366 /* query values from controls. */
367 /*====================================================================*/
369 gl_wdgt_size_get_size (glWdgtSize * size,
372 gboolean * keep_aspect_ratio_flag)
374 gdouble units_per_point;
376 units_per_point = gl_prefs_get_units_per_point ();
378 *w = gtk_spin_button_get_value (GTK_SPIN_BUTTON(size->w_spin));
379 *h = gtk_spin_button_get_value (GTK_SPIN_BUTTON(size->h_spin));
381 *keep_aspect_ratio_flag =
382 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
383 (size->aspect_checkbox));
385 /* convert everything back to our internal units (points) */
386 *w /= units_per_point;
387 *h /= units_per_point;
390 /*====================================================================*/
391 /* set values and ranges for controls. */
392 /*====================================================================*/
394 gl_wdgt_size_set_params (glWdgtSize * size,
397 gboolean keep_aspect_ratio_flag,
401 GtkObject *w_adjust, *h_adjust;
402 const gchar *units_string;
403 gdouble units_per_point, climb_rate;
406 units_string = gl_prefs_get_units_string ();
407 units_per_point = gl_prefs_get_units_per_point ();
408 climb_rate = gl_prefs_get_units_step_size ();
409 digits = gl_prefs_get_units_precision ();
411 /* Put everything into our display units */
412 size->w = w * units_per_point;
413 size->h = h * units_per_point;
414 size->w_max = w_max * units_per_point;
415 size->h_max = h_max * units_per_point;
417 /* Squirrel away copies of our original maximums */
418 size->w_max_orig = size->w_max;
419 size->h_max_orig = size->h_max;
421 size->aspect_ratio = size->h / size->w;
422 if (keep_aspect_ratio_flag) {
424 /* When tracking aspect ratio, adjust one of the maxes */
425 if ((size->h_max / size->w_max) < size->aspect_ratio) {
426 size->w_max = size->h_max / size->aspect_ratio;
428 size->h_max = size->w_max * size->aspect_ratio;
431 /* before adjusting w & h, limit to max values */
432 if (size->w > size->w_max)
433 size->w = size->w_max;
434 if (size->h > size->h_max)
435 size->h = size->h_max;
439 /* update W/H spin controls */
440 w_adjust = gtk_adjustment_new (size->w, climb_rate, size->w_max,
441 climb_rate, 10.0, 10.0);
442 gtk_spin_button_configure (GTK_SPIN_BUTTON (size->w_spin),
443 GTK_ADJUSTMENT (w_adjust), climb_rate,
446 gtk_adjustment_new (size->h, climb_rate, size->h_max, climb_rate,
448 gtk_spin_button_configure (GTK_SPIN_BUTTON (size->h_spin),
449 GTK_ADJUSTMENT (h_adjust), climb_rate,
452 gtk_label_set_text (GTK_LABEL (size->units_label), units_string);
454 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size->aspect_checkbox),
455 keep_aspect_ratio_flag);
459 /*====================================================================*/
461 /*====================================================================*/
463 gl_wdgt_size_set_size (glWdgtSize * size,
467 gdouble units_per_point;
469 units_per_point = gl_prefs_get_units_per_point ();
471 /* Put everything into our display units */
472 size->w = w * units_per_point;
473 size->h = h * units_per_point;
475 /* update aspect ratio */
476 size->aspect_ratio = size->h / size->w;
478 /* update W/H spin controls */
479 g_signal_handlers_block_by_func (GTK_OBJECT (size->w_spin),
480 G_CALLBACK (w_spin_cb),
482 g_signal_handlers_block_by_func (GTK_OBJECT (size->h_spin),
483 G_CALLBACK (h_spin_cb),
485 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->w_spin), size->w);
486 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->h_spin), size->h);
487 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->w_spin),
488 G_CALLBACK (w_spin_cb),
490 g_signal_handlers_unblock_by_func (GTK_OBJECT (size->h_spin),
491 G_CALLBACK (h_spin_cb),