]> git.sur5r.net Git - glabels/blob - glabels2/src/view-barcode.c
Created generic "get" methods for text, fill and line properties for all label object...
[glabels] / glabels2 / src / view-barcode.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view_text.c:  GLabels label text object widget
5  *
6  *  Copyright (C) 2001-2003  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 <glib.h>
24
25 #include <libgnomeprint/gnome-glyphlist.h>
26
27 #include "view-barcode.h"
28 #include "canvas-hacktext.h"
29 #include "view-highlight.h"
30
31 #include "color.h"
32 #include "object-editor.h"
33 #include "stock.h"
34
35 #include "pixmaps/cursor_barcode.xbm"
36 #include "pixmaps/cursor_barcode_mask.xbm"
37
38 #include "debug.h"
39
40 /*========================================================*/
41 /* Private macros and constants.                          */
42 /*========================================================*/
43
44 /*========================================================*/
45 /* Private types.                                         */
46 /*========================================================*/
47
48 struct _glViewBarcodePrivate {
49
50         GList           *item_list;
51
52 };
53
54 /*========================================================*/
55 /* Private globals.                                       */
56 /*========================================================*/
57
58 static glViewObjectClass *parent_class = NULL;
59
60
61 /*========================================================*/
62 /* Private function prototypes.                           */
63 /*========================================================*/
64
65 static void       gl_view_barcode_class_init            (glViewBarcodeClass  *klass);
66 static void       gl_view_barcode_instance_init         (glViewBarcode       *view_bc);
67 static void       gl_view_barcode_finalize              (GObject             *object);
68
69 static GtkWidget *construct_properties_editor           (glViewObject        *view_object);
70
71 static void       update_canvas_item_from_object_cb     (glLabelObject       *object,
72                                                          glViewBarcode       *view_bc);
73
74 static void       update_object_from_editor_cb          (glObjectEditor      *editor,
75                                                          glLabelObject       *object);
76
77 static void       update_editor_from_object_cb          (glLabelObject       *object,
78                                                          glObjectEditor      *editor);
79
80 static void       update_editor_from_move_cb            (glLabelObject       *object,
81                                                          gdouble              dx,
82                                                          gdouble              dy,
83                                                          glObjectEditor      *editor);
84
85 static void       update_editor_from_label_cb           (glLabel             *label,
86                                                          glObjectEditor      *editor);
87
88 static void       draw_barcode                          (glViewBarcode       *view_bc);
89
90
91 \f
92 /*****************************************************************************/
93 /* Boilerplate object stuff.                                                 */
94 /*****************************************************************************/
95 GType
96 gl_view_barcode_get_type (void)
97 {
98         static GType type = 0;
99
100         if (!type) {
101                 GTypeInfo info = {
102                         sizeof (glViewBarcodeClass),
103                         NULL,
104                         NULL,
105                         (GClassInitFunc) gl_view_barcode_class_init,
106                         NULL,
107                         NULL,
108                         sizeof (glViewBarcode),
109                         0,
110                         (GInstanceInitFunc) gl_view_barcode_instance_init,
111                 };
112
113                 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
114                                                "glViewBarcode", &info, 0);
115         }
116
117         return type;
118 }
119
120 static void
121 gl_view_barcode_class_init (glViewBarcodeClass *klass)
122 {
123         GObjectClass      *object_class      = (GObjectClass *) klass;
124         glViewObjectClass *view_object_class = (glViewObjectClass *) klass;
125
126         gl_debug (DEBUG_VIEW, "START");
127
128         parent_class = g_type_class_peek_parent (klass);
129
130         object_class->finalize = gl_view_barcode_finalize;
131
132         view_object_class->construct_editor = construct_properties_editor;
133
134         gl_debug (DEBUG_VIEW, "END");
135 }
136
137 static void
138 gl_view_barcode_instance_init (glViewBarcode *view_bc)
139 {
140         gl_debug (DEBUG_VIEW, "START");
141
142         view_bc->private = g_new0 (glViewBarcodePrivate, 1);
143
144         gl_debug (DEBUG_VIEW, "END");
145 }
146
147 static void
148 gl_view_barcode_finalize (GObject *object)
149 {
150         glLabel       *parent;
151
152         gl_debug (DEBUG_VIEW, "START");
153
154         g_return_if_fail (object && GL_IS_VIEW_BARCODE (object));
155
156         G_OBJECT_CLASS (parent_class)->finalize (object);
157
158         gl_debug (DEBUG_VIEW, "END");
159 }
160
161 /*****************************************************************************/
162 /* NEW barcode object view.                                                  */
163 /*****************************************************************************/
164 glViewObject *
165 gl_view_barcode_new (glLabelBarcode *object,
166                      glView         *view)
167 {
168         glViewBarcode      *view_bc;
169         GtkMenu            *menu;
170
171         gl_debug (DEBUG_VIEW, "START");
172         g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
173         g_return_if_fail (view && GL_IS_VIEW (view));
174         
175         view_bc = g_object_new (gl_view_barcode_get_type(), NULL);
176
177         gl_view_object_set_view (GL_VIEW_OBJECT(view_bc), view);
178         gl_view_object_set_object (GL_VIEW_OBJECT(view_bc),
179                                    GL_LABEL_OBJECT(object),
180                                    GL_VIEW_HIGHLIGHT_BOX_RESIZABLE);
181
182         /* Create analogous canvas items. */
183         draw_barcode (view_bc);
184
185         g_signal_connect (G_OBJECT (object), "changed",
186                           G_CALLBACK (update_canvas_item_from_object_cb), view_bc);
187
188         gl_debug (DEBUG_VIEW, "END");
189
190         return GL_VIEW_OBJECT (view_bc);
191 }
192
193 /*****************************************************************************/
194 /* Create a properties editor for a barcode object.                          */
195 /*****************************************************************************/
196 static GtkWidget *
197 construct_properties_editor (glViewObject *view_object)
198 {
199         GtkWidget          *editor;
200         glViewBarcode      *view_bc = (glViewBarcode *)view_object;
201         glLabelObject      *object;
202
203         gl_debug (DEBUG_VIEW, "START");
204
205         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_bc));
206
207         /* Build editor. */
208         editor = gl_object_editor_new (GL_STOCK_BARCODE, _("Barcode object properties"),
209                                        GL_OBJECT_EDITOR_POSITION_PAGE,
210                                        GL_OBJECT_EDITOR_SIZE_PAGE,
211                                        GL_OBJECT_EDITOR_BC_PAGE,
212                                        GL_OBJECT_EDITOR_DATA_PAGE,
213                                        0);
214
215         /* Update */
216         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
217         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
218         update_editor_from_label_cb (object->parent, GL_OBJECT_EDITOR(editor));
219
220         /* Connect signals. */
221         g_signal_connect (G_OBJECT (editor), "changed",
222                           G_CALLBACK(update_object_from_editor_cb), object);
223         g_signal_connect (G_OBJECT (object), "changed",
224                           G_CALLBACK (update_editor_from_object_cb), editor);
225         g_signal_connect (G_OBJECT (object), "moved",
226                           G_CALLBACK (update_editor_from_move_cb), editor);
227         g_signal_connect (G_OBJECT (object->parent), "size_changed",
228                           G_CALLBACK (update_editor_from_label_cb), editor);
229         g_signal_connect (G_OBJECT (object->parent), "merge_changed",
230                           G_CALLBACK (update_editor_from_label_cb), editor);
231
232         gl_debug (DEBUG_VIEW, "END");
233
234         return editor;
235 }
236
237 /*---------------------------------------------------------------------------*/
238 /* PRIVATE. label object "changed" callback.                                 */
239 /*---------------------------------------------------------------------------*/
240 static void
241 update_canvas_item_from_object_cb (glLabelObject *object,
242                                    glViewBarcode *view_bc)
243 {
244         gl_debug (DEBUG_VIEW, "START");
245
246         /* Adjust appearance of analogous canvas item. */
247         draw_barcode (view_bc);
248
249         gl_debug (DEBUG_VIEW, "END");
250 }
251
252 /*---------------------------------------------------------------------------*/
253 /* PRIVATE.  editor "changed" callback.                                      */
254 /*---------------------------------------------------------------------------*/
255 static void
256 update_object_from_editor_cb (glObjectEditor *editor,
257                               glLabelObject  *object)
258 {
259         gdouble            x, y, w, h;
260         glTextNode        *text_node;
261         glBarcodeStyle     style;
262         gboolean           text_flag, cs_flag;
263         guint              color;
264
265         gl_debug (DEBUG_VIEW, "START");
266
267         g_signal_handlers_block_by_func (G_OBJECT(object),
268                                          update_editor_from_object_cb,
269                                          editor);
270         g_signal_handlers_block_by_func (G_OBJECT(object),
271                                          update_editor_from_move_cb,
272                                          editor);
273
274
275         gl_object_editor_get_position (editor, &x, &y);
276         gl_label_object_set_position (object, x, y);
277
278         gl_object_editor_get_size (editor, &w, &h);
279         gl_label_object_set_size (object, w, h);
280
281         text_node = gl_object_editor_get_data (editor);
282         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
283         gl_text_node_free (&text_node);
284
285         gl_object_editor_get_bc_style (editor, &style, &text_flag, &cs_flag);
286         color = gl_object_editor_get_bc_color (editor);
287         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
288                                     style, text_flag, cs_flag);
289         gl_label_object_set_line_color (object, color);
290
291         g_signal_handlers_unblock_by_func (G_OBJECT(object),
292                                            update_editor_from_object_cb,
293                                            editor);
294         g_signal_handlers_unblock_by_func (G_OBJECT(object),
295                                            update_editor_from_move_cb,
296                                            editor);
297
298         gl_debug (DEBUG_VIEW, "END");
299 }
300
301 /*---------------------------------------------------------------------------*/
302 /* PRIVATE. label object "changed" callback.                                 */
303 /*---------------------------------------------------------------------------*/
304 static void
305 update_editor_from_object_cb (glLabelObject  *object,
306                               glObjectEditor *editor)
307 {
308         gdouble            w, h;
309         glTextNode        *text_node;
310         glBarcodeStyle     style;
311         gboolean           text_flag, cs_flag;
312         guint              color;
313         glMerge           *merge;
314
315         gl_debug (DEBUG_VIEW, "START");
316
317         gl_label_object_get_size (object, &w, &h);
318         gl_object_editor_set_size (editor, w, h);
319
320         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
321                                     &style, &text_flag, &cs_flag);
322         color = gl_label_object_get_line_color (object);
323         gl_object_editor_set_bc_style (editor, style, text_flag, cs_flag);
324         gl_object_editor_set_bc_color (editor, color);
325
326         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
327         merge = gl_label_get_merge (GL_LABEL(object->parent));
328         gl_object_editor_set_data (editor, (merge != NULL), text_node);
329         gl_text_node_free (&text_node);
330
331
332         gl_debug (DEBUG_VIEW, "END");
333 }
334
335 /*---------------------------------------------------------------------------*/
336 /* PRIVATE. label object "moved" callback.                                   */
337 /*---------------------------------------------------------------------------*/
338 static void
339 update_editor_from_move_cb (glLabelObject    *object,
340                             gdouble           dx,
341                             gdouble           dy,
342                             glObjectEditor   *editor)
343 {
344         gdouble            x, y;
345
346         gl_debug (DEBUG_VIEW, "START");
347
348         gl_label_object_get_position (object, &x, &y);
349         gl_object_editor_set_position (editor, x, y);
350
351         gl_debug (DEBUG_VIEW, "END");
352 }
353
354 /*---------------------------------------------------------------------------*/
355 /* PRIVATE. label "changed" callback.                                        */
356 /*---------------------------------------------------------------------------*/
357 static void
358 update_editor_from_label_cb (glLabel        *label,
359                              glObjectEditor *editor)
360 {
361         gdouble            label_width, label_height;
362         glMerge           *merge;
363
364         gl_debug (DEBUG_VIEW, "START");
365
366         gl_label_get_size (label, &label_width, &label_height);
367         gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
368                                            label_width, label_height);
369         gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
370                                        label_width, label_height);
371
372         merge = gl_label_get_merge (label);
373         gl_object_editor_set_key_names (editor, merge);
374
375         gl_debug (DEBUG_VIEW, "END");
376 }
377
378 /*****************************************************************************/
379 /* Return apropos cursor for create object mode.                             */
380 /*****************************************************************************/
381 GdkCursor *
382 gl_view_barcode_get_create_cursor (void)
383 {
384         static GdkCursor *cursor = NULL;
385         GdkPixmap        *pixmap_data, *pixmap_mask;
386         GdkColor         fg = { 0, 0, 0, 0 };
387         GdkColor         bg = { 0, 65535, 65535, 65535 };
388
389         gl_debug (DEBUG_VIEW, "START");
390
391         if (!cursor) {
392                 pixmap_data = gdk_bitmap_create_from_data (NULL,
393                                                            cursor_barcode_bits,
394                                                            cursor_barcode_width,
395                                                            cursor_barcode_height);
396                 pixmap_mask = gdk_bitmap_create_from_data (NULL,
397                                                            cursor_barcode_mask_bits,
398                                                            cursor_barcode_mask_width,
399                                                            cursor_barcode_mask_height);
400                 cursor =
401                     gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
402                                                 &bg, cursor_barcode_x_hot,
403                                                 cursor_barcode_y_hot);
404         }
405
406         gl_debug (DEBUG_VIEW, "END");
407
408         return cursor;
409 }
410
411 /*****************************************************************************/
412 /* Canvas event handler for creating barcode objects.                            */
413 /*****************************************************************************/
414 int
415 gl_view_barcode_create_event_handler (GnomeCanvas *canvas,
416                                       GdkEvent    *event,
417                                       glView      *view)
418 {
419         static gdouble      x0, y0;
420         static gboolean     dragging = FALSE;
421         static glViewObject *view_barcode;
422         static GObject      *object;
423         gdouble             x, y;
424         glTextNode          *text_node;
425
426         gl_debug (DEBUG_VIEW, "");
427
428         switch (event->type) {
429
430         case GDK_BUTTON_PRESS:
431                 gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
432                 switch (event->button.button) {
433                 case 1:
434                         dragging = TRUE;
435                         gnome_canvas_item_grab (canvas->root,
436                                                 GDK_POINTER_MOTION_MASK |
437                                                 GDK_BUTTON_RELEASE_MASK |
438                                                 GDK_BUTTON_PRESS_MASK,
439                                                 NULL, event->button.time);
440                         gnome_canvas_window_to_world (canvas,
441                                                       event->button.x,
442                                                       event->button.y, &x, &y);
443                         object = gl_label_barcode_new (view->label);
444                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
445                                                      x, y);
446                         text_node = gl_text_node_new_from_text ("123456789");
447                         gl_label_barcode_set_data (GL_LABEL_BARCODE(object),
448                                                    text_node);
449                         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
450                                                     GL_BARCODE_STYLE_POSTNET,
451                                                     FALSE,
452                                                     TRUE);
453                         gl_label_object_set_line_color (GL_LABEL_OBJECT(object),
454                                                     gl_color_set_opacity (
455                                                       gl_view_get_default_line_color(view),
456                                                       0.5));
457                         view_barcode = gl_view_barcode_new (GL_LABEL_BARCODE(object),
458                                                             view);
459                         x0 = x;
460                         y0 = y;
461                         return TRUE;
462
463                 default:
464                         return FALSE;
465                 }
466
467         case GDK_BUTTON_RELEASE:
468                 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
469                 switch (event->button.button) {
470                 case 1:
471                         dragging = FALSE;
472                         gnome_canvas_item_ungrab (canvas->root, event->button.time);
473                         gnome_canvas_window_to_world (canvas,
474                                                       event->button.x,
475                                                       event->button.y, &x, &y);
476                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
477                                                       x, y);
478                         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
479                                                     GL_BARCODE_STYLE_POSTNET,
480                                                     FALSE,
481                                                     TRUE);
482                         gl_label_object_set_line_color (GL_LABEL_OBJECT(object),
483                                                         gl_view_get_default_line_color(view));
484                         gl_view_unselect_all (view);
485                         gl_view_object_select (GL_VIEW_OBJECT(view_barcode));
486                         gl_view_arrow_mode (view);
487                         return TRUE;
488
489                 default:
490                         return FALSE;
491                 }
492
493         case GDK_MOTION_NOTIFY:
494                 gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
495                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
496                         gnome_canvas_window_to_world (canvas,
497                                                       event->motion.x,
498                                                       event->motion.y, &x, &y);
499                         gl_label_object_set_position (GL_LABEL_OBJECT(object),
500                                                       x, y);
501                         return TRUE;
502                 } else {
503                         return FALSE;
504                 }
505
506         default:
507                 return FALSE;
508         }
509
510 }
511
512 /*--------------------------------------------------------------------------*/
513 /* PRIVATE.  Draw barcode to item (group).                                  */
514 /*--------------------------------------------------------------------------*/
515 static void
516 draw_barcode (glViewBarcode *view_barcode)
517 {
518         glLabelObject    *object;
519         GnomeCanvasItem  *item;
520         glTextNode *text_node;
521         glBarcodeStyle style;
522         gboolean text_flag;
523         gboolean checksum_flag;
524         guint color;
525         gdouble w, h;
526         glBarcodeLine *line;
527         glBarcodeChar *bchar;
528         glBarcode *gbc;
529         GList *li;
530         GList *item_list = NULL;
531         GnomeCanvasPoints *points;
532         gchar *digits, *cstring;
533         GnomeFont *font;
534         GnomeGlyphList *glyphlist;
535         gdouble y_offset;
536
537         gl_debug (DEBUG_VIEW, "START");
538
539         /* Query label object and properties */
540         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_barcode));
541         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
542                                     &style, &text_flag, &checksum_flag);
543         color = gl_label_object_get_line_color (object);
544         gl_label_object_get_size (object, &w, &h);
545         text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
546         if (text_node->field_flag) {
547                 digits = gl_barcode_default_digits (style);
548         } else {
549                 digits = gl_text_node_expand (text_node, NULL);
550         }
551
552         /* remove previous items from group. */
553         for (li = view_barcode->private->item_list; li!=NULL; li = li->next) {
554                 gl_debug (DEBUG_VIEW, "in loop");
555                 gtk_object_destroy (GTK_OBJECT (li->data));
556         }
557         gl_debug (DEBUG_VIEW, "1");
558         g_list_free (view_barcode->private->item_list);
559         view_barcode->private->item_list = NULL;
560         gl_debug (DEBUG_VIEW, "2");
561
562         /* get Gnome Font */
563         font = gnome_font_find_closest_from_weight_slant (GL_BARCODE_FONT_FAMILY,
564                                                           GL_BARCODE_FONT_WEIGHT,
565                                                           FALSE,
566                                                           10.0);
567
568         gbc = gl_barcode_new (style, text_flag, checksum_flag, w, h, digits);
569         if (gbc == NULL) {
570
571                 cstring = _("Invalid barcode");
572                 glyphlist = gnome_glyphlist_from_text_sized_dumb (font,
573                                                                   color,
574                                                                   0.0, 0.0,
575                                                                   cstring,
576                                                                   strlen
577                                                                   (cstring));
578                 y_offset = 10.0 - gnome_font_get_descender (font);
579                 item = gl_view_object_item_new (GL_VIEW_OBJECT(view_barcode),
580                                                 gl_canvas_hacktext_get_type (),
581                                                 "x", 0.0,
582                                                 "y", y_offset,
583                                                 "glyphlist", glyphlist, NULL);
584
585                 view_barcode->private->item_list =
586                         g_list_prepend (view_barcode->private->item_list, item);
587         } else {
588
589                 points = gnome_canvas_points_new (2);
590                 for (li = gbc->lines; li != NULL; li = li->next) {
591                         line = (glBarcodeLine *) li->data;
592
593                         points->coords[0] = line->x;
594                         points->coords[1] = line->y;
595                         points->coords[2] = line->x;
596                         points->coords[3] = line->y + line->length;
597
598                         item = gl_view_object_item_new (GL_VIEW_OBJECT(view_barcode),
599                                                         gnome_canvas_line_get_type (),
600                                                         "points", points,
601                                                         "width_units", line->width,
602                                                         "fill_color_rgba", color,
603                                                         NULL);
604                         view_barcode->private->item_list =
605                                 g_list_prepend (view_barcode->private->item_list, item);
606                 }
607                 gnome_canvas_points_free (points);
608
609                 for (li = gbc->chars; li != NULL; li = li->next) {
610                         bchar = (glBarcodeChar *) li->data;
611
612                         font = gnome_font_find_closest_from_weight_slant (
613                                                        GL_BARCODE_FONT_FAMILY,
614                                                        GL_BARCODE_FONT_WEIGHT,
615                                                        FALSE, bchar->fsize);
616                         glyphlist = gnome_glyphlist_from_text_sized_dumb (font,
617                                                                           color,
618                                                                           0.0,
619                                                                           0.0,
620                                                                           &
621                                                                           (bchar->
622                                                                            c),
623                                                                           1);
624                         y_offset =
625                             bchar->fsize - gnome_font_get_descender (font);
626                         item = gl_view_object_item_new (GL_VIEW_OBJECT(view_barcode),
627                                                         gl_canvas_hacktext_get_type (),
628                                                         "x", bchar->x,
629                                                         "y", bchar->y + y_offset,
630                                                         "glyphlist", glyphlist,
631                                                         NULL);
632
633                         view_barcode->private->item_list =
634                                 g_list_prepend (view_barcode->private->item_list, item);
635
636                 }
637
638         }
639
640         /* clean up */
641         gl_barcode_free (&gbc);
642         g_free (digits);
643
644         gl_debug (DEBUG_VIEW, "END");
645 }
646