]> git.sur5r.net Git - glabels/blob - glabels2/src/wdgt-rotate-label.c
283b2b7527a8f2e9b671470782b2c39d4f896229
[glabels] / glabels2 / src / wdgt-rotate-label.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  wdgt_rotate_label.c:  label rotate selection 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 <math.h>
26
27 #include "wdgt-rotate-label.h"
28 #include "hig.h"
29 #include "template.h"
30 #include "marshal.h"
31 #include "color.h"
32
33 #include "debug.h"
34
35 /*========================================================*/
36 /* Private macros and constants.                          */
37 /*========================================================*/
38 #define MINI_PREVIEW_MAX_PIXELS 48
39 #define MINI_PREVIEW_CANVAS_PIXELS (MINI_PREVIEW_MAX_PIXELS + 8)
40
41 #define LINE_COLOR             GL_COLOR(0,0,0)
42 #define FILL_COLOR             GL_COLOR(255,255,255)
43 #define UNSENSITIVE_LINE_COLOR GL_COLOR(0x66,0x66,0x66)
44 #define UNSENSITIVE_FILL_COLOR GL_COLOR(0xCC,0xCC,0xCC)
45
46 #define RES 5 /* Resolution in degrees for Business Card CD outlines */
47
48 /*===========================================*/
49 /* Private types                             */
50 /*===========================================*/
51
52 enum {
53         CHANGED,
54         LAST_SIGNAL
55 };
56
57 typedef void (*glWdgtRotateLabelSignal) (GObject * object, gpointer data);
58
59 /*===========================================*/
60 /* Private globals                           */
61 /*===========================================*/
62
63 static GObjectClass *parent_class;
64
65 static gint wdgt_rotate_label_signals[LAST_SIGNAL] = { 0 };
66
67 /*===========================================*/
68 /* Local function prototypes                 */
69 /*===========================================*/
70
71 static void gl_wdgt_rotate_label_class_init    (glWdgtRotateLabelClass *class);
72 static void gl_wdgt_rotate_label_instance_init (glWdgtRotateLabel      *rotate_select);
73 static void gl_wdgt_rotate_label_finalize      (GObject                *object);
74
75 static void gl_wdgt_rotate_label_construct     (glWdgtRotateLabel      *rotate_select);
76
77 static void entry_changed_cb                   (GtkToggleButton *toggle,
78                                                 gpointer         user_data);
79
80 static GtkWidget *mini_preview_canvas_new      (void);
81
82 static void mini_preview_canvas_update         (GnomeCanvas      *canvas,
83                                                 glTemplate       *template,
84                                                 gboolean          rotate_flag);
85
86 static GnomeCanvasItem *cdbc_item              (GnomeCanvasGroup *group,
87                                                 gdouble           w,
88                                                 gdouble           h,
89                                                 gdouble           r,
90                                                 guint             line_width,
91                                                 guint             line_color,
92                                                 guint             fill_color);
93
94 /****************************************************************************/
95 /* Boilerplate Object stuff.                                                */
96 /****************************************************************************/
97 guint
98 gl_wdgt_rotate_label_get_type (void)
99 {
100         static guint wdgt_rotate_label_type = 0;
101
102         if (!wdgt_rotate_label_type) {
103                 GTypeInfo wdgt_rotate_label_info = {
104                         sizeof (glWdgtRotateLabelClass),
105                         NULL,
106                         NULL,
107                         (GClassInitFunc) gl_wdgt_rotate_label_class_init,
108                         NULL,
109                         NULL,
110                         sizeof (glWdgtRotateLabel),
111                         0,
112                         (GInstanceInitFunc) gl_wdgt_rotate_label_instance_init,
113
114                 };
115
116                 wdgt_rotate_label_type =
117                         g_type_register_static (gl_hig_hbox_get_type (),
118                                                 "glWdgtRotateLabel",
119                                                 &wdgt_rotate_label_info, 0);
120         }
121
122         return wdgt_rotate_label_type;
123 }
124
125 static void
126 gl_wdgt_rotate_label_class_init (glWdgtRotateLabelClass *class)
127 {
128         GObjectClass *object_class;
129
130         object_class = (GObjectClass *) class;
131
132         parent_class = g_type_class_peek_parent (class);
133
134         object_class->finalize = gl_wdgt_rotate_label_finalize;
135
136         wdgt_rotate_label_signals[CHANGED] =
137             g_signal_new ("changed",
138                           G_OBJECT_CLASS_TYPE(object_class),
139                           G_SIGNAL_RUN_LAST,
140                           G_STRUCT_OFFSET (glWdgtRotateLabelClass, changed),
141                           NULL, NULL,
142                           gl_marshal_VOID__VOID,
143                           G_TYPE_NONE, 0);
144
145 }
146
147 static void
148 gl_wdgt_rotate_label_instance_init (glWdgtRotateLabel *rotate_select)
149 {
150         rotate_select->rotate_check = NULL;
151
152         rotate_select->canvas = NULL;
153
154         rotate_select->template = NULL;
155 }
156
157 static void
158 gl_wdgt_rotate_label_finalize (GObject *object)
159 {
160         glWdgtRotateLabel      *rotate_select;
161         glWdgtRotateLabelClass *class;
162
163         g_return_if_fail (object != NULL);
164         g_return_if_fail (GL_IS_WDGT_ROTATE_LABEL (object));
165
166         rotate_select = GL_WDGT_ROTATE_LABEL (object);
167
168         G_OBJECT_CLASS (parent_class)->finalize (object);
169 }
170
171 GtkWidget *
172 gl_wdgt_rotate_label_new (void)
173 {
174         glWdgtRotateLabel *rotate_select;
175
176         rotate_select = g_object_new (gl_wdgt_rotate_label_get_type (), NULL);
177
178         gl_wdgt_rotate_label_construct (rotate_select);
179
180         return GTK_WIDGET (rotate_select);
181 }
182
183 /*--------------------------------------------------------------------------*/
184 /* Construct composite widget.                                              */
185 /*--------------------------------------------------------------------------*/
186 static void
187 gl_wdgt_rotate_label_construct (glWdgtRotateLabel *rotate_select)
188 {
189         GtkWidget *whbox;
190
191         whbox = GTK_WIDGET (rotate_select);
192
193         /* Actual selection control */
194         rotate_select->rotate_check =
195             gtk_check_button_new_with_label (_("Rotate"));
196         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox),
197                                 rotate_select->rotate_check);
198
199         /* mini_preview canvas */
200         rotate_select->canvas = mini_preview_canvas_new ();
201         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), rotate_select->canvas);
202
203         /* Connect signals to controls */
204         g_signal_connect (G_OBJECT (rotate_select->rotate_check), "toggled",
205                           G_CALLBACK (entry_changed_cb), rotate_select);
206 }
207
208 /*--------------------------------------------------------------------------*/
209 /* PRIVATE.  modify widget due to change of check button                    */
210 /*--------------------------------------------------------------------------*/
211 static void
212 entry_changed_cb (GtkToggleButton *toggle,
213                   gpointer         user_data)
214 {
215         glWdgtRotateLabel *rotate_select = GL_WDGT_ROTATE_LABEL (user_data);
216
217         if (rotate_select->template != NULL) {
218                 /* Update mini_preview canvas & details with template */
219                 mini_preview_canvas_update (GNOME_CANVAS
220                                             (rotate_select->canvas),
221                                             rotate_select->template,
222                                             gtk_toggle_button_get_active
223                                             (toggle));
224         }
225
226         /* Emit our "changed" signal */
227         g_signal_emit (G_OBJECT (user_data),
228                        wdgt_rotate_label_signals[CHANGED], 0);
229
230 }
231
232 /*--------------------------------------------------------------------------*/
233 /* PRIVATE.  Draw a mini-preview canvas.                                    */
234 /*--------------------------------------------------------------------------*/
235 static GtkWidget *
236 mini_preview_canvas_new (void)
237 {
238         GtkWidget *wcanvas = NULL;
239
240         /* Create a canvas */
241         gtk_widget_push_colormap (gdk_rgb_get_colormap ());
242         wcanvas = gnome_canvas_new_aa ();
243         gtk_widget_pop_colormap ();
244
245         gtk_widget_set_size_request (GTK_WIDGET (wcanvas),
246                                      MINI_PREVIEW_CANVAS_PIXELS,
247                                      MINI_PREVIEW_CANVAS_PIXELS);
248
249         gtk_object_set_data (GTK_OBJECT (wcanvas), "label_item", NULL);
250
251         return wcanvas;
252 }
253
254 /*--------------------------------------------------------------------------*/
255 /* PRIVATE.  Update mini-preview canvas from new template.                  */
256 /*--------------------------------------------------------------------------*/
257 static void
258 mini_preview_canvas_update (GnomeCanvas *canvas,
259                             glTemplate  *template,
260                             gboolean     rotate_flag)
261 {
262         gdouble           canvas_scale;
263         GnomeCanvasGroup *group = NULL;
264         GnomeCanvasItem  *label_item = NULL;
265         gdouble           m, m_canvas, w, h;
266         guint             line_color, fill_color;
267
268         /* Fetch our data from canvas */
269         label_item = g_object_get_data (G_OBJECT (canvas), "label_item");
270
271         gl_template_get_label_size (template, &w, &h);
272         m = MAX (w, h);
273         canvas_scale = MINI_PREVIEW_MAX_PIXELS / m;
274         m_canvas = MINI_PREVIEW_CANVAS_PIXELS / canvas_scale;
275
276         /* scale and size canvas */
277         gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (canvas), canvas_scale);
278         group = gnome_canvas_root (GNOME_CANVAS (canvas));
279         gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),
280                                         -m_canvas / 2.0, -m_canvas / 2.0,
281                                         +m_canvas / 2.0, +m_canvas / 2.0);
282
283         /* remove old label outline */
284         if (label_item != NULL) {
285                 gtk_object_destroy (GTK_OBJECT (label_item));
286         }
287
288         /* Adjust sensitivity (should the canvas be grayed?) */
289         if (w != h) {
290                 line_color = LINE_COLOR;
291                 fill_color = FILL_COLOR;
292         } else {
293                 line_color = UNSENSITIVE_LINE_COLOR;
294                 fill_color = UNSENSITIVE_FILL_COLOR;
295         }
296
297         /* draw mini label outline */
298         switch (template->label.style) {
299         case GL_TEMPLATE_STYLE_RECT:
300                 label_item = gnome_canvas_item_new (group,
301                                                     gnome_canvas_rect_get_type(),
302                                                     "x1", -w / 2.0,
303                                                     "y1", -h / 2.0,
304                                                     "x2", +w / 2.0,
305                                                     "y2", +h / 2.0,
306                                                     "width_pixels", 1,
307                                                     "outline_color_rgba", line_color,
308                                                     "fill_color_rgba", fill_color,
309                                                     NULL);
310                 break;
311         case GL_TEMPLATE_STYLE_ROUND:
312                 label_item = gnome_canvas_item_new (group,
313                                                     gnome_canvas_ellipse_get_type(),
314                                                     "x1", -w / 2.0,
315                                                     "y1", -h / 2.0,
316                                                     "x2", +w / 2.0,
317                                                     "y2", +h / 2.0,
318                                                     "width_pixels", 1,
319                                                     "outline_color_rgba", line_color,
320                                                     "fill_color_rgba", fill_color,
321                                                     NULL);
322                 break;
323         case GL_TEMPLATE_STYLE_CD:
324                 if ( w == h ) {
325                         label_item = gnome_canvas_item_new (group,
326                                                             gnome_canvas_ellipse_get_type(),
327                                                             "x1", -w / 2.0,
328                                                             "y1", -h / 2.0,
329                                                             "x2", +w / 2.0,
330                                                             "y2", +h / 2.0,
331                                                             "width_pixels", 1,
332                                                             "outline_color_rgba", line_color,
333                                                             "fill_color_rgba", fill_color,
334                                                             NULL);
335                 } else {
336                         label_item = cdbc_item (group,
337                                                 w, h, template->label.cd.r1,
338                                                 1, line_color, fill_color);
339                 }
340                 break;
341         default:
342                 g_warning ("Unknown label style");
343                 break;
344         }
345
346         if (rotate_flag) {
347                 gdouble affine[6];
348
349                 art_affine_rotate (affine, 90);
350                 gnome_canvas_item_affine_absolute (label_item, affine);
351         }
352
353         gtk_object_set_data (GTK_OBJECT (canvas), "label_item", label_item);
354
355 }
356
357 /****************************************************************************/
358 /* query state of widget.                                                   */
359 /****************************************************************************/
360 gboolean
361 gl_wdgt_rotate_label_get_state (glWdgtRotateLabel *rotate_select)
362 {
363         return
364             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
365                                           (rotate_select->rotate_check));
366 }
367
368 /****************************************************************************/
369 /* set state of widget.                                                     */
370 /****************************************************************************/
371 void
372 gl_wdgt_rotate_label_set_state (glWdgtRotateLabel *rotate_select,
373                                 gboolean state)
374 {
375         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
376                                       (rotate_select->rotate_check), state);
377 }
378
379 /****************************************************************************/
380 /* set template for widget.                                                 */
381 /****************************************************************************/
382 void
383 gl_wdgt_rotate_label_set_template_name (glWdgtRotateLabel *rotate_select,
384                                         gchar             *name)
385 {
386         glTemplate *template;
387         gdouble     raw_w, raw_h;
388
389         template = gl_template_from_name (name);
390         rotate_select->template = template;
391         gl_template_get_label_size (template, &raw_w, &raw_h);
392
393         gtk_widget_set_sensitive (rotate_select->rotate_check,
394                                   (raw_w != raw_h));
395
396         mini_preview_canvas_update (GNOME_CANVAS (rotate_select->canvas),
397                                     template, FALSE);
398         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
399                                       (rotate_select->rotate_check), FALSE);
400 }
401
402 /*--------------------------------------------------------------------------*/
403 /* PRIVATE.  Draw CD business card item (cut-off in w and/or h).            */
404 /*--------------------------------------------------------------------------*/
405 static GnomeCanvasItem *
406 cdbc_item (GnomeCanvasGroup *group,
407            gdouble           w,
408            gdouble           h,
409            gdouble           r,
410            guint             line_width,
411            guint             line_color,
412            guint             fill_color)
413 {
414         GnomeCanvasPoints *points;
415         gint               i_coords, i_theta;
416         gdouble            theta1, theta2;
417         GnomeCanvasItem   *item;
418
419         theta1 = (180.0/G_PI) * acos (w / (2.0*r));
420         theta2 = (180.0/G_PI) * asin (h / (2.0*r));
421
422         points = gnome_canvas_points_new (360/RES + 1);
423         i_coords = 0;
424
425         points->coords[i_coords++] = r * cos (theta1 * G_PI / 180.0);
426         points->coords[i_coords++] = r * sin (theta1 * G_PI / 180.0);
427
428         for ( i_theta = theta1 + RES; i_theta < theta2; i_theta +=RES ) {
429                 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
430                 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
431         }
432
433         points->coords[i_coords++] = r * cos (theta2 * G_PI / 180.0);
434         points->coords[i_coords++] = r * sin (theta2 * G_PI / 180.0);
435
436
437         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
438                 points->coords[i_coords++] = r * cos ((180-theta2) * G_PI / 180.0);
439                 points->coords[i_coords++] = r * sin ((180-theta2) * G_PI / 180.0);
440         }
441
442         for ( i_theta = 180-theta2+RES; i_theta < (180-theta1); i_theta +=RES ) {
443                 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
444                 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
445         }
446
447         points->coords[i_coords++] = r * cos ((180-theta1) * G_PI / 180.0);
448         points->coords[i_coords++] = r * sin ((180-theta1) * G_PI / 180.0);
449
450         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
451                 points->coords[i_coords++] = r * cos ((180+theta1) * G_PI / 180.0);
452                 points->coords[i_coords++] = r * sin ((180+theta1) * G_PI / 180.0);
453         }
454
455         for ( i_theta = 180+theta1+RES; i_theta < (180+theta2); i_theta +=RES ) {
456                 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
457                 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
458         }
459
460         points->coords[i_coords++] = r * cos ((180+theta2) * G_PI / 180.0);
461         points->coords[i_coords++] = r * sin ((180+theta2) * G_PI / 180.0);
462
463         if ( fabs (theta2 - 90.0) > GNOME_CANVAS_EPSILON ) {
464                 points->coords[i_coords++] = r * cos ((360-theta2) * G_PI / 180.0);
465                 points->coords[i_coords++] = r * sin ((360-theta2) * G_PI / 180.0);
466         }
467
468         for ( i_theta = 360-theta2+RES; i_theta < (360-theta1); i_theta +=RES ) {
469                 points->coords[i_coords++] = r * cos (i_theta * G_PI / 180.0);
470                 points->coords[i_coords++] = r * sin (i_theta * G_PI / 180.0);
471         }
472
473         if ( fabs (theta1) > GNOME_CANVAS_EPSILON ) {
474                 points->coords[i_coords++] = r * cos ((360-theta1) * G_PI / 180.0);
475                 points->coords[i_coords++] = r * sin ((360-theta1) * G_PI / 180.0);
476         }
477
478         points->num_points = i_coords / 2;
479
480
481         item = gnome_canvas_item_new (group,
482                                       gnome_canvas_polygon_get_type (),
483                                       "points", points,
484                                       "width_pixels", line_width,
485                                       "outline_color_rgba", line_color,
486                                       "fill_color_rgba", fill_color,
487                                       NULL);
488
489         gnome_canvas_points_free (points);
490
491         return item;
492 }
493