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
,
73 (GtkClassInitFunc
) NULL
,
75 us_type
= gtk_type_unique(gtk_spin_button_get_type(), &us_info
);
81 dia_unit_spinner_value_changed(GtkAdjustment
*adjustment
,
82 DiaUnitSpinner
*spinner
)
85 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(spinner
);
87 g_snprintf(buf
, sizeof(buf
), "%0.*f%s", sbutton
->digits
, adjustment
->value
,
88 units
[spinner
->unit_num
].unit
);
89 if (strcmp(buf
, gtk_entry_get_text(GTK_ENTRY(spinner
))))
90 gtk_entry_set_text(GTK_ENTRY(spinner
), buf
);
93 static gint
dia_unit_spinner_focus_out(GtkWidget
*widget
, GdkEventFocus
*ev
);
94 static gint
dia_unit_spinner_button_press(GtkWidget
*widget
,GdkEventButton
*ev
);
95 static gint
dia_unit_spinner_key_press(GtkWidget
*widget
, GdkEventKey
*event
);
96 static void dia_unit_spinner_activate(GtkEntry
*editable
);
99 dia_unit_spinner_class_init(DiaUnitSpinnerClass
*class)
101 GtkObjectClass
*object_class
;
102 GtkWidgetClass
*widget_class
;
103 GtkEntryClass
*editable_class
;
105 object_class
= (GtkObjectClass
*)class;
106 widget_class
= (GtkWidgetClass
*)class;
107 editable_class
= (GtkEntryClass
*)class;
109 widget_class
->focus_out_event
= dia_unit_spinner_focus_out
;
110 widget_class
->button_press_event
= dia_unit_spinner_button_press
;
111 widget_class
->key_press_event
= dia_unit_spinner_key_press
;
112 editable_class
->activate
= dia_unit_spinner_activate
;
114 parent_class
= gtk_type_class(GTK_TYPE_SPIN_BUTTON
);
115 entry_class
= gtk_type_class(GTK_TYPE_ENTRY
);
119 dia_unit_spinner_init(DiaUnitSpinner
*self
)
121 /* change over to our own print function that appends the unit name on the
123 if (self
->parent
.adjustment
) {
124 gtk_signal_disconnect_by_data(GTK_OBJECT(self
->parent
.adjustment
),
126 g_signal_connect(GTK_OBJECT(self
->parent
.adjustment
), "value_changed",
127 G_CALLBACK(dia_unit_spinner_value_changed
),
131 self
->unit_num
= DIA_UNIT_CENTIMETER
;
135 dia_unit_spinner_new(GtkAdjustment
*adjustment
, guint digits
, DiaUnit adj_unit
)
137 DiaUnitSpinner
*self
= gtk_type_new(dia_unit_spinner_get_type());
139 gtk_spin_button_configure(GTK_SPIN_BUTTON(self
), adjustment
, 0.0, digits
);
142 gtk_signal_disconnect_by_data(GTK_OBJECT(adjustment
),
144 g_signal_connect(GTK_OBJECT(adjustment
), "value_changed",
145 G_CALLBACK(dia_unit_spinner_value_changed
),
149 self
->unit_num
= adj_unit
;
151 return GTK_WIDGET(self
);
155 dia_unit_spinner_set_value(DiaUnitSpinner
*self
, gfloat val
)
157 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
159 if (val
< sbutton
->adjustment
->lower
)
160 val
= sbutton
->adjustment
->lower
;
161 else if (val
> sbutton
->adjustment
->upper
)
162 val
= sbutton
->adjustment
->upper
;
163 if (val
!= sbutton
->adjustment
->value
) {
164 sbutton
->adjustment
->value
= val
;
165 gtk_adjustment_value_changed(sbutton
->adjustment
);
170 dia_unit_spinner_get_value(DiaUnitSpinner
*self
)
172 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
174 return sbutton
->adjustment
->value
;
178 dia_unit_spinner_update(DiaUnitSpinner
*self
)
180 GtkSpinButton
*sbutton
= GTK_SPIN_BUTTON(self
);
181 gfloat val
, factor
= 1.0;
184 val
= g_strtod(gtk_entry_get_text(GTK_ENTRY(self
)), &extra
);
186 /* get rid of extra white space after number */
187 while (*extra
&& isspace(*extra
)) extra
++;
191 for (i
= 0; units
[i
].name
!= NULL
; i
++)
192 if (!g_strcasecmp(units
[i
].unit
, extra
)) {
193 factor
= units
[i
].factor
/ units
[self
->unit_num
].factor
;
197 /* convert to prefered units */
199 if (val
< sbutton
->adjustment
->lower
)
200 val
= sbutton
->adjustment
->lower
;
201 else if (val
> sbutton
->adjustment
->upper
)
202 val
= sbutton
->adjustment
->upper
;
203 gtk_adjustment_set_value(sbutton
->adjustment
, val
);
207 dia_unit_spinner_focus_out(GtkWidget
*widget
, GdkEventFocus
*event
)
209 if (GTK_ENTRY (widget
)->editable
)
210 dia_unit_spinner_update(DIA_UNIT_SPINNER(widget
));
211 return GTK_WIDGET_CLASS(entry_class
)->focus_out_event(widget
, event
);
215 dia_unit_spinner_button_press(GtkWidget
*widget
, GdkEventButton
*event
)
217 dia_unit_spinner_update(DIA_UNIT_SPINNER(widget
));
218 return GTK_WIDGET_CLASS(parent_class
)->button_press_event(widget
, event
);
222 dia_unit_spinner_key_press(GtkWidget
*widget
, GdkEventKey
*event
)
224 gint key
= event
->keyval
;
226 if (GTK_ENTRY (widget
)->editable
&&
227 (key
== GDK_Up
|| key
== GDK_Down
||
228 key
== GDK_Page_Up
|| key
== GDK_Page_Down
))
229 dia_unit_spinner_update (DIA_UNIT_SPINNER(widget
));
230 return GTK_WIDGET_CLASS(parent_class
)->key_press_event(widget
, event
);
234 dia_unit_spinner_activate(GtkEntry
*editable
)
236 if (editable
->editable
)
237 dia_unit_spinner_update(DIA_UNIT_SPINNER(editable
));