]> git.sur5r.net Git - glabels/blob - glabels1/src/item_barcode.c
2009-09-22 Jim Evins <evins@snaught.com>
[glabels] / glabels1 / src / item_barcode.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  item_barcode.c:  GLabels Barcode Object (canvas item) 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 <string.h>
26
27 #include "display.h"
28 #include "item_barcode.h"
29 #include "bc.h"
30
31 #include "highlight.h"
32
33 #include "mdi.h"
34 #include "propertybox.h"
35 #include "prop_bc_data.h"
36 #include "prop_bc.h"
37 #include "prop_bc_style.h"
38 #include "prop_position.h"
39
40 #include "pixmaps/cursor_barcode.xbm"
41 #include "pixmaps/cursor_barcode_mask.xbm"
42
43 #ifdef HACKTEXT
44 #include "gnome-canvas-hacktext.h"
45 #include <libgnomeprint/gnome-glyphlist.h>
46 #endif
47
48 #include "debug.h"
49
50 #define Y_FONT_ADJUST (-1.0)    /* Adjust font vertical position */
51
52 /*===========================================*/
53 /* Private data types                        */
54 /*===========================================*/
55
56 typedef struct {
57         GnomeCanvasItem *item;
58
59         /* Page 0 widgets */
60         GtkWidget *data_entry;
61
62         /* Page 1 widgets */
63         GtkWidget *bcprop;
64         GtkWidget *style;
65
66         /* Page 2 widgets */
67         GtkWidget *position;
68 } PropertyDialogPassback;
69
70 /*===========================================*/
71 /* Private globals                           */
72 /*===========================================*/
73 \f
74 /*===========================================*/
75 /* Local function prototypes                 */
76 /*===========================================*/
77
78 static void item_barcode_update (GnomeCanvasItem * item);
79
80 static void changed_cb (glPropertyBox * propertybox);
81 static void apply_cb (glPropertyBox * propertybox, gint page,
82                       PropertyDialogPassback * data);
83
84 static void draw_barcode (GnomeCanvasItem * item,
85                           glBarcodeStyle style,
86                           guint color,
87                           gboolean text_flag,
88                           gdouble scale,
89                           gchar * digits,
90                           gdouble canvas_scale);
91 \f
92 /*****************************************************************************/
93 /* Create a barcode object                                                   */
94 /*****************************************************************************/
95 GnomeCanvasItem *
96 gl_item_barcode_new (glLabelObject * object,
97                      glDisplay * display)
98 {
99         GnomeCanvasGroup *group;
100         GnomeCanvasItem *item;
101         gchar *text;
102
103         group = gnome_canvas_root (GNOME_CANVAS (display->canvas));
104         item = gnome_canvas_item_new (group, gnome_canvas_group_get_type (),
105                                       "x", object->x, "y", object->y, NULL);
106
107         if (object->arg.barcode.text_node->field_flag) {
108                 text = gl_barcode_default_digits (object->arg.barcode.style);
109         } else {
110                 text =
111                     gl_text_node_expand (object->arg.barcode.text_node, NULL);
112         }
113         draw_barcode (item,
114                       object->arg.barcode.style,
115                       object->arg.barcode.color,
116                       object->arg.barcode.text_flag,
117                       object->arg.barcode.scale, text, display->scale);
118         g_free (text);
119
120         /* Squirrel away pointers to object and display in the canvas item. */
121         gtk_object_set_data (GTK_OBJECT (item), "label_object", object);
122         gtk_object_set_data (GTK_OBJECT (item), "display", display);
123         gtk_object_set_data (GTK_OBJECT (item), "highlight", NULL);
124
125         gtk_signal_connect (GTK_OBJECT (item), "event",
126                             GTK_SIGNAL_FUNC (gl_display_item_event_handler),
127                             display);
128
129         gl_display_new_item_menu (item);
130
131         gl_display_set_modified (display);
132
133         return item;
134 }
135
136 /*---------------------------------------------------------------------------*/
137 /* PRIVATE.  Update a barcode object                                         */
138 /*---------------------------------------------------------------------------*/
139 static void
140 item_barcode_update (GnomeCanvasItem * item)
141 {
142         glLabelObject *object;
143         glDisplay *display;
144         GList *item_list, *li;
145         gdouble affine[6];
146         gchar *text;
147
148         display = gtk_object_get_data (GTK_OBJECT (item), "display");
149         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
150
151         item_list = gtk_object_get_data (GTK_OBJECT (item), "item_list");
152         for (li = item_list; li != NULL; li = li->next) {
153                 gtk_object_destroy (GTK_OBJECT (li->data));
154         }
155         g_list_free (item_list);
156         gtk_object_set_data (GTK_OBJECT (item), "item_list", NULL);
157
158         if (object->arg.barcode.text_node->field_flag) {
159                 text = gl_barcode_default_digits (object->arg.barcode.style);
160         } else {
161                 text =
162                     gl_text_node_expand (object->arg.barcode.text_node, NULL);
163         }
164         draw_barcode (item,
165                       object->arg.barcode.style,
166                       object->arg.barcode.color,
167                       object->arg.barcode.text_flag,
168                       object->arg.barcode.scale, text, display->scale);
169         g_free (text);
170
171         art_affine_identity (affine);
172         gnome_canvas_item_affine_absolute (item, affine);
173         gnome_canvas_item_set (item, "x", object->x, "y", object->y, NULL);
174
175         gl_display_set_modified (display);
176 }
177
178 /*****************************************************************************/
179 /* Highlight given canvas item.                                              */
180 /*****************************************************************************/
181 void
182 gl_item_barcode_highlight (GnomeCanvasItem * item)
183 {
184         gl_highlight (item, GL_HIGHLIGHT_SIMPLE);
185 }
186
187 /*****************************************************************************/
188 /* Get position and size of object.                                          */
189 /*****************************************************************************/
190 void
191 gl_item_barcode_get_position_size (GnomeCanvasItem * item,
192                                    gdouble * x,
193                                    gdouble * y,
194                                    gdouble * w,
195                                    gdouble * h)
196 {
197         glLabelObject *object;
198         glBarcode *gbc;
199
200         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
201
202         *x = object->x;
203         *y = object->y;
204
205         gbc = gtk_object_get_data (GTK_OBJECT (item), "bc");
206         *w = gbc->width;
207         *h = gbc->height;
208
209 }
210
211 /*****************************************************************************/
212 /* Get position and size of object.                                          */
213 /*****************************************************************************/
214 void
215 gl_item_barcode_set_position_size (GnomeCanvasItem * item,
216                                    gdouble x,
217                                    gdouble y,
218                                    gdouble w,
219                                    gdouble h)
220 {
221         glLabelObject *object;
222
223         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
224
225         object->x = x;
226         object->y = y;
227
228         /* Currently ignore w, h */
229
230         item_barcode_update (item);
231 }
232
233 /*****************************************************************************/
234 /* Get barcode item bounds.                                                  */
235 /*****************************************************************************/
236 void
237 gl_item_barcode_get_bounds (GnomeCanvasItem * item,
238                             gdouble * x1,
239                             gdouble * y1,
240                             gdouble * x2,
241                             gdouble * y2)
242 {
243         glBarcode *gbc;
244         glLabelObject *object;
245
246         gbc = gtk_object_get_data (GTK_OBJECT (item), "bc");
247         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
248
249         if (gbc == NULL) {
250                 gnome_canvas_item_get_bounds (item, x1, y1, x2, y2);
251         } else {
252                 *x1 = object->x;
253                 *y1 = object->y;
254                 *x2 = *x1 + gbc->width;
255                 *y2 = *y1 + gbc->height;
256         }
257 }
258
259 /*****************************************************************************/
260 /* Create and run an edit dialog on a barcode object.                        */
261 /*****************************************************************************/
262 void
263 gl_item_barcode_edit_dialog (GnomeCanvasItem * item)
264 {
265         GtkWidget *dialog;
266         static PropertyDialogPassback *data = NULL;
267         glLabelObject *object;
268         glDisplay *display;
269         GtkWidget *wvbox;
270
271         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
272         display = gtk_object_get_data (GTK_OBJECT (item), "display");
273
274         /*-----------------------------------------------------------------*/
275         /* Build dialog with notebook.                                     */
276         /*-----------------------------------------------------------------*/
277         if (data == NULL) {
278                 data = g_new0 (PropertyDialogPassback, 1);
279         }
280         data->item = item;
281
282         dialog = gl_property_box_new ();
283         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
284         gtk_window_set_transient_for (GTK_WINDOW (dialog),
285                                       GTK_WINDOW (gl_mdi_get_active_window ()));
286         gtk_window_set_title (GTK_WINDOW (dialog),
287                               _("Edit barcode object properties"));
288         gtk_signal_connect (GTK_OBJECT (dialog), "apply",
289                             GTK_SIGNAL_FUNC (apply_cb), data);
290
291         /*---------------------------*/
292         /* Data Notebook Tab         */
293         /*---------------------------*/
294         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
295         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
296         gl_property_box_append_page (GL_PROPERTY_BOX (dialog),
297                                      wvbox, gtk_label_new (_("Data")));
298
299         data->data_entry = gl_prop_bc_data_new (_("Barcode data"),
300                                                 object->parent->merge_fields);
301         gl_prop_bc_data_set_data (GL_PROP_BC_DATA (data->data_entry),
302                                   (object->parent->merge_type != GL_MERGE_NONE),
303                                   object->arg.barcode.text_node->field_flag,
304                                   object->arg.barcode.text_node->data,
305                                   object->arg.barcode.text_node->data);
306         gtk_box_pack_start (GTK_BOX (wvbox), data->data_entry, FALSE, FALSE, 0);
307         gtk_signal_connect_object (GTK_OBJECT (data->data_entry), "changed",
308                                    GTK_SIGNAL_FUNC (changed_cb),
309                                    GTK_OBJECT (dialog));
310
311         /*---------------------------*/
312         /* Appearance Notebook Tab   */
313         /*---------------------------*/
314         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
315         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
316         gl_property_box_append_page (GL_PROPERTY_BOX (dialog),
317                                      wvbox, gtk_label_new (_("Appearance")));
318
319         /* ------ Begin Barcode Properties Frame ------ */
320         data->bcprop = gl_prop_bc_new (_("General"));
321         gl_prop_bc_set_params (GL_PROP_BC (data->bcprop),
322                                object->arg.barcode.scale,
323                                object->arg.barcode.color);
324         gtk_box_pack_start (GTK_BOX (wvbox), data->bcprop, FALSE, FALSE, 0);
325         gtk_signal_connect_object (GTK_OBJECT (data->bcprop), "changed",
326                                    GTK_SIGNAL_FUNC (changed_cb),
327                                    GTK_OBJECT (dialog));
328
329         /* ------ Barcode Style Frame ------ */
330         data->style = gl_prop_bc_style_new (_("Style"));
331         gl_prop_bc_style_set_params (GL_PROP_BC_STYLE (data->style),
332                                      object->arg.barcode.style,
333                                      object->arg.barcode.text_flag);
334         gtk_box_pack_start (GTK_BOX (wvbox), data->style, FALSE, FALSE, 0);
335         gtk_signal_connect_object (GTK_OBJECT (data->style), "changed",
336                                    GTK_SIGNAL_FUNC (changed_cb),
337                                    GTK_OBJECT (dialog));
338
339         /*----------------------------*/
340         /* Position Notebook Tab      */
341         /*----------------------------*/
342         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
343         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
344         gl_property_box_append_page (GL_PROPERTY_BOX (dialog),
345                                      wvbox, gtk_label_new (_("Position")));
346
347         /* ------ Position Frame ------ */
348         data->position = gl_prop_position_new (_("Position"));
349         gl_prop_position_set_params (GL_PROP_POSITION (data->position),
350                                      object->x, object->y,
351                                      display->label->width,
352                                      display->label->height);
353         gtk_box_pack_start (GTK_BOX (wvbox), data->position, FALSE, FALSE, 0);
354         gtk_signal_connect_object (GTK_OBJECT (data->position), "changed",
355                                    GTK_SIGNAL_FUNC (changed_cb),
356                                    GTK_OBJECT (dialog));
357
358         /*-----------------------------------------------------------------*/
359         /* Run dialog, and update state of object if "Applied."            */
360         /*-----------------------------------------------------------------*/
361         gtk_widget_show_all (GTK_WIDGET (dialog));
362 }
363
364 /*---------------------------------------------------------------------------*/
365 /* PRIVATE.  Callback for when any control in the dialog has changed.        */
366 /*---------------------------------------------------------------------------*/
367 static void
368 changed_cb (glPropertyBox * propertybox)
369 {
370         gl_property_box_changed (propertybox);
371 }
372
373 /*---------------------------------------------------------------------------*/
374 /* PRIVATE.  "Apply" callback.                                               */
375 /*---------------------------------------------------------------------------*/
376 static void
377 apply_cb (glPropertyBox * propertybox,
378           gint page,
379           PropertyDialogPassback * data)
380 {
381         glLabelObject *object;
382         glDisplay *display;
383         gboolean flag;
384         gchar *tmp1, *tmp2;
385
386         object = gtk_object_get_data (GTK_OBJECT (data->item), "label_object");
387         display = gtk_object_get_data (GTK_OBJECT (data->item), "display");
388
389         switch (page) {
390
391         case 0:
392                 /* ------- Get updated digit data ------ */
393                 gl_prop_bc_data_get_data (GL_PROP_BC_DATA (data->data_entry),
394                                           &flag, &tmp1, &tmp2);
395                 object->arg.barcode.text_node->field_flag = flag;
396                 if (!flag) {
397                         object->arg.barcode.text_node->data = tmp1;
398                         g_free (tmp2);
399                 } else {
400                         object->arg.barcode.text_node->data = tmp2;
401                         g_free (tmp1);
402                 }
403                 break;
404
405         case 1:
406                 /* ------- Get updated scale/color ------ */
407                 gl_prop_bc_get_params (GL_PROP_BC (data->bcprop),
408                                        &object->arg.barcode.scale,
409                                        &object->arg.barcode.color);
410                 /* ------ Get updated style ------ */
411                 gl_prop_bc_style_get_params (GL_PROP_BC_STYLE (data->style),
412                                              &object->arg.barcode.style,
413                                              &object->arg.barcode.text_flag);
414                 break;
415
416         case 2:
417                 /* ------ get updated position ------ */
418                 gl_prop_position_get_position (GL_PROP_POSITION
419                                                (data->position), &object->x,
420                                                &object->y);
421                 break;
422
423         default:
424                 return;
425         }
426
427         /* ------ Udate state of object ------ */
428         item_barcode_update (data->item);
429         gl_display_select_item (display, data->item);
430
431 }
432
433 /*****************************************************************************/
434 /* Return apropos cursor for create object mode.                             */
435 /*****************************************************************************/
436 GdkCursor *
437 gl_item_barcode_get_create_cursor (void)
438 {
439         static GdkCursor *cursor = NULL;
440         GdkPixmap *pixmap_data, *pixmap_mask;
441         GdkColor fg = { 0, 0, 0, 0 };
442         GdkColor bg = { 0, 65535, 65535, 65535 };
443
444         if (!cursor) {
445                 pixmap_data = gdk_bitmap_create_from_data (NULL,
446                                                            cursor_barcode_bits,
447                                                            cursor_barcode_width,
448                                                            cursor_barcode_height);
449                 pixmap_mask = gdk_bitmap_create_from_data (NULL,
450                                                            cursor_barcode_mask_bits,
451                                                            cursor_barcode_mask_width,
452                                                            cursor_barcode_mask_height);
453                 cursor =
454                     gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
455                                                 &bg, cursor_barcode_x_hot,
456                                                 cursor_barcode_y_hot);
457         }
458
459         return cursor;
460 }
461
462 /*****************************************************************************/
463 /* Canvas event handler (barcode mode)                                       */
464 /*****************************************************************************/
465 int
466 gl_item_barcode_create_event_handler (GnomeCanvas * canvas,
467                                       GdkEvent * event,
468                                       gpointer data)
469 {
470         glDisplay *display = GL_DISPLAY (data);
471         gdouble x, y;
472         glLabelObject *object;
473         GnomeCanvasItem *item;
474
475         switch (event->type) {
476
477         case GDK_BUTTON_PRESS:
478                 switch (event->button.button) {
479                 case 1:
480                         gnome_canvas_window_to_world (canvas,
481                                                       event->button.x,
482                                                       event->button.y, &x, &y);
483                         object =
484                             gl_label_object_new (display->label,
485                                                  GL_LABEL_OBJECT_BARCODE);
486                         object->x = x;
487                         object->y = y;
488                         object->arg.barcode.text_node =
489                             gl_text_node_new_from_text ("123456789");
490                         object->arg.barcode.style = GL_BARCODE_STYLE_POSTNET;
491                         object->arg.barcode.color =
492                             GNOME_CANVAS_COLOR_A (0, 0, 0, 255);
493                         object->arg.barcode.text_flag = TRUE;
494                         object->arg.barcode.scale = 1.0;
495                         item = gl_item_barcode_new (object, display);
496                         gl_display_add_item (display, item);
497                         gl_display_unselect_all (display);
498                         gl_display_select_item (display, item);
499                         gl_display_arrow_mode (display);
500                         return TRUE;
501
502                 default:
503                         return FALSE;
504                 }
505
506         default:
507                 return FALSE;
508         }
509
510 }
511
512 /*---------------------------------------------------------------------------*/
513 /* PRIVATE.  Draw barcode to canvas item (group).                            */
514 /*---------------------------------------------------------------------------*/
515 static void
516 draw_barcode (GnomeCanvasItem * group,
517               glBarcodeStyle style,
518               guint color,
519               gboolean text_flag,
520               gdouble scale,
521               gchar * digits,
522               gdouble canvas_scale)
523 {
524         glBarcodeLine *line;
525         glBarcodeChar *bchar;
526         glBarcode *gbc;
527         GList *li;
528         GnomeCanvasItem *item;
529         GList *item_list = NULL;
530         GnomeCanvasPoints *points;
531         gchar *cstring;
532 #ifdef HACKTEXT
533         GnomeFont *font;
534         GnomeGlyphList *glyphlist;
535         gdouble y_offset;
536 #else
537         GdkFont *gdk_font;
538         GnomeDisplayFont *display_font;
539 #endif
540
541         gbc = gtk_object_get_data (GTK_OBJECT (group), "bc");
542         gl_barcode_free (&gbc);
543         gbc = gl_barcode (style, text_flag, scale, digits);
544         if (gbc == NULL) {
545 #ifdef HACKTEXT
546                 font = gnome_font_new_closest (GL_BARCODE_FONT_FAMILY,
547                                                GL_BARCODE_FONT_WEIGHT,
548                                                FALSE, 10.0);
549                 cstring = _("Invalid barcode");
550                 glyphlist = gnome_glyphlist_from_text_sized_dumb (font,
551                                                                   color,
552                                                                   0.0, 0.0,
553                                                                   cstring,
554                                                                   strlen
555                                                                   (cstring));
556                 y_offset = 10.0 - gnome_font_get_descender (font);
557                 item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
558                                               gnome_canvas_hacktext_get_type (),
559                                               "x", 0.0,
560                                               "y", y_offset,
561                                               "glyphlist", glyphlist, NULL);
562 #else
563                 display_font = gnome_get_display_font (GL_BARCODE_FONT_FAMILY,
564                                                        GL_BARCODE_FONT_WEIGHT,
565                                                        FALSE,
566                                                        10.0, canvas_scale);
567                 gdk_font = gnome_display_font_get_gdk_font (display_font);
568                 item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
569                                               gnome_canvas_text_get_type (),
570                                               "x", 0.0,
571                                               "y", 0.0,
572                                               "text", _("Invalid barcode"),
573                                               "font_gdk", gdk_font,
574                                               "anchor", GTK_ANCHOR_NW,
575                                               "fill_color_rgba", color, NULL);
576 #endif
577                 item_list = g_list_prepend (item_list, item);
578         } else {
579
580                 points = gnome_canvas_points_new (2);
581                 for (li = gbc->lines; li != NULL; li = li->next) {
582                         line = (glBarcodeLine *) li->data;
583
584                         points->coords[0] = line->x;
585                         points->coords[1] = line->y;
586                         points->coords[2] = line->x;
587                         points->coords[3] = line->y + line->length;
588
589                         item =
590                             gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
591                                                    gnome_canvas_line_get_type
592                                                    (), "points", points,
593                                                    "width_units", line->width,
594                                                    "fill_color_rgba", color,
595                                                    NULL);
596                         item_list = g_list_prepend (item_list, item);
597                 }
598                 gnome_canvas_points_free (points);
599
600                 for (li = gbc->chars; li != NULL; li = li->next) {
601                         bchar = (glBarcodeChar *) li->data;
602
603 #ifdef HACKTEXT
604                         font = gnome_font_new_closest (GL_BARCODE_FONT_FAMILY,
605                                                        GL_BARCODE_FONT_WEIGHT,
606                                                        FALSE, bchar->fsize);
607                         glyphlist = gnome_glyphlist_from_text_sized_dumb (font,
608                                                                           color,
609                                                                           0.0,
610                                                                           0.0,
611                                                                           &
612                                                                           (bchar->
613                                                                            c),
614                                                                           1);
615                         y_offset =
616                             bchar->fsize - gnome_font_get_descender (font);
617                         item =
618                             gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
619                                                    gnome_canvas_hacktext_get_type
620                                                    (), "x", bchar->x, "y",
621                                                    bchar->y + y_offset,
622                                                    "glyphlist", glyphlist,
623                                                    NULL);
624 #else
625                         display_font =
626                             gnome_get_display_font (GL_BARCODE_FONT_FAMILY,
627                                                     GL_BARCODE_FONT_WEIGHT,
628                                                     FALSE, bchar->fsize,
629                                                     canvas_scale);
630                         gdk_font =
631                             gnome_display_font_get_gdk_font (display_font);
632                         cstring = g_strdup_printf ("%c", bchar->c);
633                         item =
634                             gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
635                                                    gnome_canvas_text_get_type
636                                                    (), "x", bchar->x, "y",
637                                                    bchar->y + Y_FONT_ADJUST,
638                                                    "text", cstring, "font_gdk",
639                                                    gdk_font, "anchor",
640                                                    GTK_ANCHOR_NW,
641                                                    "fill_color_rgba", color,
642                                                    NULL);
643                         g_free (cstring);
644 #endif
645                         item_list = g_list_prepend (item_list, item);
646
647                 }
648
649         }
650
651         /* attach item list to group, so we can get at these again */
652         gtk_object_set_data (GTK_OBJECT (group), "item_list", item_list);
653
654         gtk_object_set_data (GTK_OBJECT (group), "bc", gbc);
655
656 }