2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * prop_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 "prop_size.h"
30 /*===========================================*/
32 /*===========================================*/
39 typedef void (*glPropSizeSignal) (GtkObject * object, gpointer data);
41 /*===========================================*/
43 /*===========================================*/
45 static GtkContainerClass *parent_class;
47 static gint prop_size_signals[LAST_SIGNAL] = { 0 };
49 /*===========================================*/
50 /* Local function prototypes */
51 /*===========================================*/
53 static void gl_prop_size_class_init (glPropSizeClass * class);
54 static void gl_prop_size_init (glPropSize * size);
55 static void gl_prop_size_destroy (GtkObject * object);
56 static void gl_prop_size_construct (glPropSize * size, gchar * label);
58 static void aspect_toggle_cb (GtkToggleButton * togglebutton,
60 static void w_spin_cb (GtkSpinButton * spinbutton, gpointer user_data);
61 static void h_spin_cb (GtkSpinButton * spinbutton, gpointer user_data);
63 /*================================================================*/
64 /* Boilerplate Object stuff. */
65 /*================================================================*/
67 gl_prop_size_get_type (void)
69 static guint prop_size_type = 0;
71 if (!prop_size_type) {
72 GtkTypeInfo prop_size_info = {
75 sizeof (glPropSizeClass),
76 (GtkClassInitFunc) gl_prop_size_class_init,
77 (GtkObjectInitFunc) gl_prop_size_init,
83 gtk_type_unique (gtk_vbox_get_type (), &prop_size_info);
86 return prop_size_type;
90 gl_prop_size_class_init (glPropSizeClass * class)
92 GtkObjectClass *object_class;
93 GtkWidgetClass *widget_class;
95 object_class = (GtkObjectClass *) class;
96 widget_class = (GtkWidgetClass *) class;
98 parent_class = gtk_type_class (gtk_vbox_get_type ());
100 object_class->destroy = gl_prop_size_destroy;
102 prop_size_signals[CHANGED] =
103 gtk_signal_new ("changed", GTK_RUN_LAST, object_class->type,
104 GTK_SIGNAL_OFFSET (glPropSizeClass, changed),
105 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
106 gtk_object_class_add_signals (object_class, prop_size_signals,
109 class->changed = NULL;
113 gl_prop_size_init (glPropSize * size)
115 size->aspect_ratio = 1.0;
120 size->units_label = NULL;
122 size->aspect_checkbox = NULL;
126 gl_prop_size_destroy (GtkObject * object)
129 glPropSizeClass *class;
131 g_return_if_fail (object != NULL);
132 g_return_if_fail (GL_IS_PROP_SIZE (object));
134 size = GL_PROP_SIZE (object);
135 class = GL_PROP_SIZE_CLASS (GTK_OBJECT (size)->klass);
137 GTK_OBJECT_CLASS (parent_class)->destroy (object);
141 gl_prop_size_new (gchar * label)
145 size = gtk_type_new (gl_prop_size_get_type ());
147 gl_prop_size_construct (size, label);
149 return GTK_WIDGET (size);
152 /*============================================================*/
153 /* Construct composite widget. */
154 /*============================================================*/
156 gl_prop_size_construct (glPropSize * size,
159 GtkWidget *wvbox, *wframe, *wtable, *wlabel;
160 GtkObject *w_adjust, *h_adjust;
161 const gchar *units_string;
162 gdouble units_per_point, climb_rate;
165 units_string = gl_prefs_get_units_string ();
166 units_per_point = gl_prefs_get_units_per_point ();
167 climb_rate = gl_prefs_get_units_step_size ();
168 digits = gl_prefs_get_units_precision ();
170 wvbox = GTK_WIDGET (size);
172 wframe = gtk_frame_new (label);
173 gtk_box_pack_start (GTK_BOX (wvbox), wframe, FALSE, FALSE, 0);
175 wtable = gtk_table_new (3, 3, TRUE);
176 gtk_container_set_border_width (GTK_CONTAINER (wtable), 10);
177 gtk_table_set_row_spacings (GTK_TABLE (wtable), 5);
178 gtk_table_set_col_spacings (GTK_TABLE (wtable), 5);
179 gtk_container_add (GTK_CONTAINER (wframe), wtable);
182 wlabel = gtk_label_new (_("Width:"));
183 gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
184 gtk_label_set_justify (GTK_LABEL (wlabel), GTK_JUSTIFY_RIGHT);
185 gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 0, 1);
187 w_adjust = gtk_adjustment_new (climb_rate, climb_rate, 100.0,
188 climb_rate, 10.0, 10.0);
189 size->w_spin = gtk_spin_button_new (GTK_ADJUSTMENT (w_adjust),
191 gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (size->w_spin),
193 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (size->w_spin), TRUE);
194 gtk_table_attach_defaults (GTK_TABLE (wtable), size->w_spin,
198 wlabel = gtk_label_new (_("Height:"));
199 gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
200 gtk_label_set_justify (GTK_LABEL (wlabel), GTK_JUSTIFY_RIGHT);
201 gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 1, 2);
203 h_adjust = gtk_adjustment_new (climb_rate, climb_rate,
204 100.0, climb_rate, 10.0, 10.0);
205 size->h_spin = gtk_spin_button_new (GTK_ADJUSTMENT (h_adjust),
207 gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (size->h_spin),
209 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (size->h_spin), TRUE);
210 gtk_table_attach_defaults (GTK_TABLE (wtable), size->h_spin,
214 size->units_label = gtk_label_new (units_string);
215 gtk_misc_set_alignment (GTK_MISC (size->units_label), 0, 0.5);
216 gtk_table_attach_defaults (GTK_TABLE (wtable),
217 size->units_label, 2, 3, 1, 2);
219 /* Maintain aspect ratio checkbox */
220 size->aspect_checkbox =
221 gtk_check_button_new_with_label (_
222 ("Maintain current aspect ratio"));
223 gtk_table_attach_defaults (GTK_TABLE (wtable), size->aspect_checkbox, 0,
226 /* Connect signals to controls */
227 gtk_signal_connect (GTK_OBJECT (size->aspect_checkbox), "toggled",
228 GTK_SIGNAL_FUNC (aspect_toggle_cb), size);
229 gtk_signal_connect (GTK_OBJECT (size->w_spin), "changed",
230 GTK_SIGNAL_FUNC (w_spin_cb), size);
231 gtk_signal_connect (GTK_OBJECT (size->h_spin), "changed",
232 GTK_SIGNAL_FUNC (h_spin_cb), size);
235 /*--------------------------------------------------------------------------*/
236 /* PRIVATE. Maintain aspect ratio checkbox callback. */
237 /*--------------------------------------------------------------------------*/
239 aspect_toggle_cb (GtkToggleButton * togglebutton,
242 glPropSize *size = GL_PROP_SIZE (user_data);
243 GtkAdjustment *w_adjust, *h_adjust;
245 if (gtk_toggle_button_get_active (togglebutton)) {
248 gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON
251 gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON
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 gtk_signal_handler_block_by_func (GTK_OBJECT (size->w_spin),
274 GTK_SIGNAL_FUNC (w_spin_cb),
276 gtk_signal_handler_block_by_func (GTK_OBJECT (size->h_spin),
277 GTK_SIGNAL_FUNC (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 gtk_signal_handler_unblock_by_func (GTK_OBJECT (size->w_spin),
288 GTK_SIGNAL_FUNC (w_spin_cb),
290 gtk_signal_handler_unblock_by_func (GTK_OBJECT (size->h_spin),
291 GTK_SIGNAL_FUNC (h_spin_cb),
294 /* Emit our "changed" signal */
295 gtk_signal_emit (GTK_OBJECT (size), prop_size_signals[CHANGED]);
299 /*--------------------------------------------------------------------------*/
300 /* PRIVATE. W spin button changed callback. */
301 /*--------------------------------------------------------------------------*/
303 w_spin_cb (GtkSpinButton * spinbutton,
306 glPropSize *size = GL_PROP_SIZE (user_data);
307 GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (size->aspect_checkbox);
310 gtk_spin_button_get_value_as_float (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 gtk_signal_handler_block_by_func (GTK_OBJECT (size->h_spin),
318 GTK_SIGNAL_FUNC (h_spin_cb),
320 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->h_spin),
322 gtk_signal_handler_unblock_by_func (GTK_OBJECT (size->h_spin),
323 GTK_SIGNAL_FUNC (h_spin_cb),
327 /* Emit our "changed" signal */
328 gtk_signal_emit (GTK_OBJECT (size), prop_size_signals[CHANGED]);
332 /*--------------------------------------------------------------------------*/
333 /* PRIVATE. H spin button changed callback. */
334 /*--------------------------------------------------------------------------*/
336 h_spin_cb (GtkSpinButton * spinbutton,
339 glPropSize *size = GL_PROP_SIZE (user_data);
340 GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (size->aspect_checkbox);
343 gtk_spin_button_get_value_as_float (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 gtk_signal_handler_block_by_func (GTK_OBJECT (size->w_spin),
351 GTK_SIGNAL_FUNC (w_spin_cb),
353 gtk_spin_button_set_value (GTK_SPIN_BUTTON (size->w_spin),
355 gtk_signal_handler_unblock_by_func (GTK_OBJECT (size->w_spin),
356 GTK_SIGNAL_FUNC (w_spin_cb),
360 /* Emit our "changed" signal */
361 gtk_signal_emit (GTK_OBJECT (size), prop_size_signals[CHANGED]);
365 /*====================================================================*/
366 /* query values from controls. */
367 /*====================================================================*/
369 gl_prop_size_get_size (glPropSize * 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_as_float (GTK_SPIN_BUTTON
380 *h = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON
383 *keep_aspect_ratio_flag =
384 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
385 (size->aspect_checkbox));
387 /* convert everything back to our internal units (points) */
388 *w /= units_per_point;
389 *h /= units_per_point;
392 /*====================================================================*/
393 /* set values and ranges for controls. */
394 /*====================================================================*/
396 gl_prop_size_set_params (glPropSize * size,
399 gboolean keep_aspect_ratio_flag,
403 GtkObject *w_adjust, *h_adjust;
404 const gchar *units_string;
405 gdouble units_per_point, climb_rate;
408 units_string = gl_prefs_get_units_string ();
409 units_per_point = gl_prefs_get_units_per_point ();
410 climb_rate = gl_prefs_get_units_step_size ();
411 digits = gl_prefs_get_units_precision ();
413 /* Put everything into our display units */
414 size->w = w * units_per_point;
415 size->h = h * units_per_point;
416 size->w_max = w_max * units_per_point;
417 size->h_max = h_max * units_per_point;
419 /* Squirrel away copies of our original maximums */
420 size->w_max_orig = size->w_max;
421 size->h_max_orig = size->h_max;
423 size->aspect_ratio = size->h / size->w;
424 if (keep_aspect_ratio_flag) {
426 /* When tracking aspect ratio, adjust one of the maxes */
427 if ((size->h_max / size->w_max) < size->aspect_ratio) {
428 size->w_max = size->h_max / size->aspect_ratio;
430 size->h_max = size->w_max * size->aspect_ratio;
433 /* before adjusting w & h, limit to max values */
434 if (size->w > size->w_max)
435 size->w = size->w_max;
436 if (size->h > size->h_max)
437 size->h = size->h_max;
441 /* update W/H spin controls */
442 w_adjust = gtk_adjustment_new (size->w, climb_rate, size->w_max,
443 climb_rate, 10.0, 10.0);
444 gtk_spin_button_configure (GTK_SPIN_BUTTON (size->w_spin),
445 GTK_ADJUSTMENT (w_adjust), climb_rate,
448 gtk_adjustment_new (size->h, climb_rate, size->h_max, climb_rate,
450 gtk_spin_button_configure (GTK_SPIN_BUTTON (size->h_spin),
451 GTK_ADJUSTMENT (h_adjust), climb_rate,
454 gtk_label_set_text (GTK_LABEL (size->units_label), units_string);
456 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size->aspect_checkbox),
457 keep_aspect_ratio_flag);