svg text alignment
[dia.git] / app / diaunitspinner.c
blob12868ed846887322114f9ce29106cfb9419826a9
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.
22 #include <config.h>
24 #include <ctype.h>
25 #include <string.h> /* strcmp */
26 #include "diaunitspinner.h"
27 #include "gdk/gdkkeysyms.h"
29 typedef struct _DiaUnitDef DiaUnitDef;
30 struct _DiaUnitDef {
31 char* name;
32 char* unit;
33 float factor;
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 },
48 { "Inch", "in", 72 },
49 { "Pica", "pi", 12 },
50 { 0 }
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);
59 GtkType
60 dia_unit_spinner_get_type(void)
62 static GtkType us_type = 0;
64 if (!us_type) {
65 GtkTypeInfo us_info = {
66 "DiaUnitSpinner",
67 sizeof(DiaUnitSpinner),
68 sizeof(DiaUnitSpinnerClass),
69 (GtkClassInitFunc) dia_unit_spinner_class_init,
70 (GtkObjectInitFunc) dia_unit_spinner_init,
71 (GtkArgSetFunc) NULL,
72 (GtkArgGetFunc) NULL
74 us_type = gtk_type_unique(gtk_spin_button_get_type(), &us_info);
76 return us_type;
79 static void
80 dia_unit_spinner_value_changed(GtkAdjustment *adjustment,
81 DiaUnitSpinner *spinner)
83 char buf[256];
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);
97 static void
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);
117 static void
118 dia_unit_spinner_init(DiaUnitSpinner *self)
120 /* change over to our own print function that appends the unit name on the
121 * end */
122 if (self->parent.adjustment) {
123 gtk_signal_disconnect_by_data(GTK_OBJECT(self->parent.adjustment),
124 (gpointer) self);
125 gtk_signal_connect(GTK_OBJECT(self->parent.adjustment), "value_changed",
126 GTK_SIGNAL_FUNC(dia_unit_spinner_value_changed),
127 (gpointer) self);
130 self->unit_num = DIA_UNIT_CENTIMETER;
133 GtkWidget *
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);
140 if (adjustment) {
141 gtk_signal_disconnect_by_data(GTK_OBJECT(adjustment),
142 (gpointer) self);
143 gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
144 GTK_SIGNAL_FUNC(dia_unit_spinner_value_changed),
145 (gpointer) self);
148 self->unit_num = adj_unit;
150 return GTK_WIDGET(self);
153 void
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);
168 gfloat
169 dia_unit_spinner_get_value(DiaUnitSpinner *self)
171 GtkSpinButton *sbutton = GTK_SPIN_BUTTON(self);
173 return sbutton->adjustment->value;
176 static void
177 dia_unit_spinner_update(DiaUnitSpinner *self)
179 GtkSpinButton *sbutton = GTK_SPIN_BUTTON(self);
180 gfloat val, factor = 1.0;
181 gchar *extra = NULL;
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++;
187 if (*extra) {
188 int i;
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;
193 break;
196 /* convert to prefered units */
197 val *= factor;
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);
205 static gint
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);
213 static gint
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);
220 static gint
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);
232 static void
233 dia_unit_spinner_activate(GtkEditable *editable)
235 if (editable->editable)
236 dia_unit_spinner_update(DIA_UNIT_SPINNER(editable));