]> git.sur5r.net Git - glabels/blob - glabels2/src/wdgt-vector.c
Initial revision
[glabels] / glabels2 / src / wdgt-vector.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  wdgt_vector.c:  vector properties widget module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <config.h>
24
25 #include "wdgt-vector.h"
26 #include "prefs.h"
27 #include "marshal.h"
28
29 #include "debug.h"
30
31 #include <math.h>
32
33 #ifndef M_PI
34 #define M_PI            3.14159265358979323846  /* pi */
35 #endif
36
37 #define LENGTH(x,y) sqrt( (x)*(x) + (y)*(y) )
38 #define ANGLE(x,y)  ( (180.0/M_PI)*atan2( -(y), (x) ) )
39 #define COMP_X(l,a) ( (l) * cos( (M_PI/180.0)*(a) ) )
40 #define COMP_Y(l,a) ( -(l) * sin( (M_PI/180.0)*(a) ) )
41
42 /*===========================================*/
43 /* Private types                             */
44 /*===========================================*/
45
46 enum {
47         CHANGED,
48         LAST_SIGNAL
49 };
50
51 typedef void (*glWdgtVectorSignal) (GObject * object, gpointer data);
52
53 /*===========================================*/
54 /* Private globals                           */
55 /*===========================================*/
56
57 static GtkContainerClass *parent_class;
58
59 static gint wdgt_vector_signals[LAST_SIGNAL] = { 0 };
60 \f
61 /*===========================================*/
62 /* Local function prototypes                 */
63 /*===========================================*/
64
65 static void gl_wdgt_vector_class_init (glWdgtVectorClass * class);
66 static void gl_wdgt_vector_instance_init (glWdgtVector * vector);
67 static void gl_wdgt_vector_finalize (GObject * object);
68 static void gl_wdgt_vector_construct (glWdgtVector * vector, gchar * label);
69 static void changed_cb (glWdgtVector * vector);
70 \f
71 /*================================================================*/
72 /* Boilerplate Object stuff.                                      */
73 /*================================================================*/
74 guint
75 gl_wdgt_vector_get_type (void)
76 {
77         static guint wdgt_vector_type = 0;
78
79         if (!wdgt_vector_type) {
80                 GTypeInfo wdgt_vector_info = {
81                         sizeof (glWdgtVectorClass),
82                         NULL,
83                         NULL,
84                         (GClassInitFunc) gl_wdgt_vector_class_init,
85                         NULL,
86                         NULL,
87                         sizeof (glWdgtVector),
88                         0,
89                         (GInstanceInitFunc) gl_wdgt_vector_instance_init,
90                 };
91
92                 wdgt_vector_type =
93                         g_type_register_static (gtk_vbox_get_type (),
94                                                 "glWdgtVector",
95                                                 &wdgt_vector_info, 0);
96         }
97
98         return wdgt_vector_type;
99 }
100
101 static void
102 gl_wdgt_vector_class_init (glWdgtVectorClass * class)
103 {
104         GObjectClass *object_class;
105
106         object_class = (GObjectClass *) class;
107
108         parent_class = gtk_type_class (gtk_vbox_get_type ());
109
110         object_class->finalize = gl_wdgt_vector_finalize;
111
112         wdgt_vector_signals[CHANGED] =
113             g_signal_new ("changed",
114                           G_OBJECT_CLASS_TYPE(object_class),
115                           G_SIGNAL_RUN_LAST,
116                           G_STRUCT_OFFSET (glWdgtVectorClass, changed),
117                           NULL, NULL,
118                           gl_marshal_VOID__VOID,
119                           G_TYPE_NONE, 0);
120
121 }
122
123 static void
124 gl_wdgt_vector_instance_init (glWdgtVector * vector)
125 {
126         vector->len_spin = NULL;
127         vector->angle_spin = NULL;
128 }
129
130 static void
131 gl_wdgt_vector_finalize (GObject * object)
132 {
133         glWdgtVector *vector;
134         glWdgtVectorClass *class;
135
136         g_return_if_fail (object != NULL);
137         g_return_if_fail (GL_IS_WDGT_VECTOR (object));
138
139         vector = GL_WDGT_VECTOR (object);
140
141         G_OBJECT_CLASS (parent_class)->finalize (object);
142 }
143
144 GtkWidget *
145 gl_wdgt_vector_new (gchar * label)
146 {
147         glWdgtVector *vector;
148
149         vector = g_object_new (gl_wdgt_vector_get_type (), NULL);
150
151         gl_wdgt_vector_construct (vector, label);
152
153         return GTK_WIDGET (vector);
154 }
155 \f
156 /*============================================================*/
157 /* Construct composite widget.                                */
158 /*============================================================*/
159 static void
160 gl_wdgt_vector_construct (glWdgtVector * vector,
161                           gchar * label)
162 {
163         GtkWidget *wvbox, *wframe, *wtable, *wlabel;
164         GtkObject *adjust;
165         const gchar *units_string;
166         gdouble units_per_point, climb_rate;
167         gint digits;
168
169         units_string = gl_prefs_get_units_string ();
170         units_per_point = gl_prefs_get_units_per_point ();
171         climb_rate = gl_prefs_get_units_step_size ();
172         digits = gl_prefs_get_units_precision ();
173
174         wvbox = GTK_WIDGET (vector);
175
176         wframe = gtk_frame_new (label);
177         gtk_box_pack_start (GTK_BOX (wvbox), wframe, FALSE, FALSE, 0);
178
179         wtable = gtk_table_new (2, 3, TRUE);
180         gtk_container_set_border_width (GTK_CONTAINER (wtable), 10);
181         gtk_table_set_row_spacings (GTK_TABLE (wtable), 5);
182         gtk_table_set_col_spacings (GTK_TABLE (wtable), 5);
183         gtk_container_add (GTK_CONTAINER (wframe), wtable);
184
185         /* Length label */
186         wlabel = gtk_label_new (_("Length:"));
187         gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
188         gtk_label_set_justify (GTK_LABEL (wlabel), GTK_JUSTIFY_RIGHT);
189         gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 0, 1);
190         /* Length spin */
191         adjust = gtk_adjustment_new (climb_rate, climb_rate, 100.0, climb_rate,
192                                      10.0, 10.0);
193         vector->len_spin = gtk_spin_button_new (GTK_ADJUSTMENT (adjust),
194                                                 climb_rate, digits);
195         gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (vector->len_spin),
196                                            TRUE);
197         gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (vector->len_spin), TRUE);
198         g_signal_connect_swapped (G_OBJECT (vector->len_spin), "changed",
199                                   G_CALLBACK (changed_cb),
200                                   G_OBJECT (vector));
201         gtk_table_attach_defaults (GTK_TABLE (wtable), vector->len_spin, 1, 2,
202                                    0, 1);
203         /* Length units label */
204         vector->len_units_label = gtk_label_new (units_string);
205         gtk_misc_set_alignment (GTK_MISC (vector->len_units_label), 0, 0.5);
206         gtk_table_attach_defaults (GTK_TABLE (wtable), vector->len_units_label,
207                                    2, 3, 0, 1);
208
209         /* Angle label */
210         wlabel = gtk_label_new (_("Angle:"));
211         gtk_misc_set_alignment (GTK_MISC (wlabel), 0, 0.5);
212         gtk_table_attach_defaults (GTK_TABLE (wtable), wlabel, 0, 1, 1, 2);
213         /* Angle spin */
214         adjust = gtk_adjustment_new (0.0, -180.0, +180.0, 1.0, 10.0, 10.0);
215         vector->angle_spin =
216             gtk_spin_button_new (GTK_ADJUSTMENT (adjust), 1.0, 0);
217         gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (vector->angle_spin),
218                                            TRUE);
219         gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (vector->angle_spin),
220                                      TRUE);
221         g_signal_connect_swapped (G_OBJECT (vector->angle_spin), "changed",
222                                   G_CALLBACK (changed_cb),
223                                   G_OBJECT (vector));
224         gtk_table_attach_defaults (GTK_TABLE (wtable), vector->angle_spin, 1, 2,
225                                    1, 2);
226         /* Angle units label */
227         vector->angle_units_label = gtk_label_new (_("degrees"));
228         gtk_misc_set_alignment (GTK_MISC (vector->angle_units_label), 0, 0.5);
229         gtk_table_attach_defaults (GTK_TABLE (wtable),
230                                    vector->angle_units_label, 2, 3, 1, 2);
231
232 }
233
234 /*--------------------------------------------------------------------------*/
235 /* PRIVATE.  Callback for when any control in the widget has changed.       */
236 /*--------------------------------------------------------------------------*/
237 static void
238 changed_cb (glWdgtVector * vector)
239 {
240         /* Emit our "changed" signal */
241         g_signal_emit (G_OBJECT (vector), wdgt_vector_signals[CHANGED], 0);
242 }
243 \f
244 /*====================================================================*/
245 /* query values from controls.                                        */
246 /*====================================================================*/
247 void
248 gl_wdgt_vector_get_params (glWdgtVector * vector,
249                            gdouble * dx,
250                            gdouble * dy)
251 {
252         gdouble length, angle;
253         gdouble units_per_point;
254
255         units_per_point = gl_prefs_get_units_per_point ();
256
257         length =
258             gtk_spin_button_get_value (GTK_SPIN_BUTTON(vector->len_spin));
259         angle =
260             gtk_spin_button_get_value (GTK_SPIN_BUTTON(vector->angle_spin));
261
262         length /= units_per_point;
263
264         *dx = COMP_X (length, angle);
265         *dy = COMP_Y (length, angle);
266 }
267
268 /*====================================================================*/
269 /* set values and ranges for controls.                                */
270 /*====================================================================*/
271 void
272 gl_wdgt_vector_set_params (glWdgtVector * vector,
273                            gdouble dx,
274                            gdouble dy,
275                            gdouble x_max,
276                            gdouble y_max)
277 {
278         GtkObject *length_adjust;
279         gdouble length, angle;
280         const gchar *units_string;
281         gdouble units_per_point, climb_rate;
282         gint digits;
283
284         units_string = gl_prefs_get_units_string ();
285         units_per_point = gl_prefs_get_units_per_point ();
286         climb_rate = gl_prefs_get_units_step_size ();
287         digits = gl_prefs_get_units_precision ();
288
289         /* Put everything into our display units */
290         dx *= units_per_point;
291         dy *= units_per_point;
292         x_max *= units_per_point;
293         y_max *= units_per_point;
294
295         length = LENGTH (dx, dy);
296         angle = ANGLE (dx, dy);
297
298         length_adjust = gtk_adjustment_new (length, 0.0, LENGTH (x_max, y_max),
299                                             climb_rate, 10.0, 10.0);
300         gtk_spin_button_configure (GTK_SPIN_BUTTON (vector->len_spin),
301                                    GTK_ADJUSTMENT (length_adjust),
302                                    climb_rate, digits);
303         gtk_spin_button_update (GTK_SPIN_BUTTON (vector->len_spin));
304
305         gtk_spin_button_set_value (GTK_SPIN_BUTTON (vector->angle_spin), angle);
306 }