1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998, 1999 Alexander Larsson
4 * diaunitspinner.[ch] -- a spin button widget for length measurements.
5 * Copyright (C) 1999 James Henstridge
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 of the License, or
10 * (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include <string.h> /* strcmp */
26 #include "diaunitspinner.h"
27 #include "gdk/gdkkeysyms.h"
29 typedef struct _DiaUnitDef DiaUnitDef
;
36 /* from gnome-libs/libgnome/gnome-paper.c */
37 static const DiaUnitDef units
[] =
39 /* XXX does anyone *really* measure paper size in feet? meters? */
41 /* human name, abreviation, points per unit */
42 { "Feet", "ft", 864 },
43 { "Meter", "m", 2834.6457 },
44 { "Decimeter", "dm", 283.46457 },
45 { "Millimeter", "mm", 2.8346457 },
46 { "Point", "pt", 1. },
47 { "Centimeter", "cm", 28.346457 },
53 static GtkObjectClass
*parent_class
;
54 static GtkObjectClass
*entry_class
;
56 static void dia_unit_spinner_class_init(DiaUnitSpinnerClass
*class);
57 static void dia_unit_spinner_init(DiaUnitSpinner
*self
);
60 dia_unit_spinner_get_type(void)
62 static GtkType us_type
= 0;
65 GtkTypeInfo us_info
= {
67 sizeof(DiaUnitSpinner
),
68 sizeof(DiaUnitSpinnerClass
),
69 (GtkClassInitFunc
) dia_unit_spinner_class_init
,
70 (GtkObjectInitFunc
) dia_unit_spinner_init
,
74 us_type
= gtk_type_unique(gtk_spin_button_get_type(), &us_info
);
80 dia_unit_spinner_value_changed(GtkAdjustment
*adjustment
,
81 DiaUnitSpinner
*spinner
)
84 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(spinner
);
86 g_snprintf(buf
, sizeof(buf
), "%0.*f%s", sbutton
->digits
, adjustment
->value
,
87 units
[spinner
->unit_num
].unit
);
88 if (strcmp(buf
, gtk_entry_get_text(GTK_ENTRY(spinner
))))
89 gtk_entry_set_text(GTK_ENTRY(spinner
), buf
);
92 static gint
dia_unit_spinner_focus_out(GtkWidget
*widget
, GdkEventFocus
*ev
);
93 static gint
dia_unit_spinner_button_press(GtkWidget
*widget
,GdkEventButton
*ev
);
94 static gint
dia_unit_spinner_key_press(GtkWidget
*widget
, GdkEventKey
*event
);
95 static void dia_unit_spinner_activate(GtkEditable
*editable
);
98 dia_unit_spinner_class_init(DiaUnitSpinnerClass
*class)
100 GtkObjectClass
*object_class
;
101 GtkWidgetClass
*widget_class
;
102 GtkEditableClass
*editable_class
;
104 object_class
= (GtkObjectClass
*)class;
105 widget_class
= (GtkWidgetClass
*)class;
106 editable_class
= (GtkEditableClass
*)class;
108 widget_class
->focus_out_event
= dia_unit_spinner_focus_out
;
109 widget_class
->button_press_event
= dia_unit_spinner_button_press
;
110 widget_class
->key_press_event
= dia_unit_spinner_key_press
;
111 editable_class
->activate
= dia_unit_spinner_activate
;
113 parent_class
= gtk_type_class(GTK_TYPE_SPIN_BUTTON
);
114 entry_class
= gtk_type_class(GTK_TYPE_ENTRY
);
118 dia_unit_spinner_init(DiaUnitSpinner
*self
)
120 /* change over to our own print function that appends the unit name on the
122 if (self
->parent
.adjustment
) {
123 gtk_signal_disconnect_by_data(GTK_OBJECT(self
->parent
.adjustment
),
125 gtk_signal_connect(GTK_OBJECT(self
->parent
.adjustment
), "value_changed",
126 GTK_SIGNAL_FUNC(dia_unit_spinner_value_changed
),
130 self
->unit_num
= DIA_UNIT_CENTIMETER
;
134 dia_unit_spinner_new(GtkAdjustment
*adjustment
, guint digits
, DiaUnit adj_unit
)
136 DiaUnitSpinner
*self
= gtk_type_new(dia_unit_spinner_get_type());
138 gtk_spin_button_configure(GTK_SPIN_BUTTON(self
), adjustment
, 0.0, digits
);
141 gtk_signal_disconnect_by_data(GTK_OBJECT(adjustment
),
143 gtk_signal_connect(GTK_OBJECT(adjustment
), "value_changed",
144 GTK_SIGNAL_FUNC(dia_unit_spinner_value_changed
),
148 self
->unit_num
= adj_unit
;
150 return GTK_WIDGET(self
);
154 dia_unit_spinner_set_value(DiaUnitSpinner
*self
, gfloat val
)
156 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
158 if (val
< sbutton
->adjustment
->lower
)
159 val
= sbutton
->adjustment
->lower
;
160 else if (val
> sbutton
->adjustment
->upper
)
161 val
= sbutton
->adjustment
->upper
;
162 if (val
!= sbutton
->adjustment
->value
) {
163 sbutton
->adjustment
->value
= val
;
164 gtk_adjustment_value_changed(sbutton
->adjustment
);
169 dia_unit_spinner_get_value(DiaUnitSpinner
*self
)
171 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
173 return sbutton
->adjustment
->value
;
177 dia_unit_spinner_update(DiaUnitSpinner
*self
)
179 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
180 gfloat val
, factor
= 1.0;
183 val
= g_strtod(gtk_entry_get_text(GTK_ENTRY(self
)), &extra
);
185 /* get rid of extra white space after number */
186 while (*extra
&& isspace(*extra
)) extra
++;
190 for (i
= 0; units
[i
].name
!= NULL
; i
++)
191 if (!g_strcasecmp(units
[i
].unit
, extra
)) {
192 factor
= units
[i
].factor
/ units
[self
->unit_num
].factor
;
196 /* convert to prefered units */
198 if (val
< sbutton
->adjustment
->lower
)
199 val
= sbutton
->adjustment
->lower
;
200 else if (val
> sbutton
->adjustment
->upper
)
201 val
= sbutton
->adjustment
->upper
;
202 gtk_adjustment_set_value(sbutton
->adjustment
, val
);
206 dia_unit_spinner_focus_out(GtkWidget
*widget
, GdkEventFocus
*event
)
208 if (GTK_EDITABLE(widget
)->editable
)
209 dia_unit_spinner_update(DIA_UNIT_SPINNER(widget
));
210 return GTK_WIDGET_CLASS(entry_class
)->focus_out_event(widget
, event
);
214 dia_unit_spinner_button_press(GtkWidget
*widget
, GdkEventButton
*event
)
216 dia_unit_spinner_update(DIA_UNIT_SPINNER(widget
));
217 return GTK_WIDGET_CLASS(parent_class
)->button_press_event(widget
, event
);
221 dia_unit_spinner_key_press(GtkWidget
*widget
, GdkEventKey
*event
)
223 gint key
= event
->keyval
;
225 if (GTK_EDITABLE (widget
)->editable
&&
226 (key
== GDK_Up
|| key
== GDK_Down
||
227 key
== GDK_Page_Up
|| key
== GDK_Page_Down
))
228 dia_unit_spinner_update (DIA_UNIT_SPINNER(widget
));
229 return GTK_WIDGET_CLASS(parent_class
)->key_press_event(widget
, event
);
233 dia_unit_spinner_activate(GtkEditable
*editable
)
235 if (editable
->editable
)
236 dia_unit_spinner_update(DIA_UNIT_SPINNER(editable
));