]> git.sur5r.net Git - glabels/blob - glabels2/src/label.c
498dc5261c2238ee45b20b459ccfaea6413bdd18
[glabels] / glabels2 / src / label.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label.c:  GLabels label 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 <gnome.h>
26
27 #include "label.h"
28 #include "label-object.h"
29 #include "label-text.h"
30 #include "label-box.h"
31 #include "label-line.h"
32 #include "label-ellipse.h"
33 #include "label-image.h"
34 #include "label-barcode.h"
35 #include "template.h"
36 #include "marshal.h"
37 #include "util.h"
38
39 #include "debug.h"
40
41 /*========================================================*/
42 /* Private macros and constants.                          */
43 /*========================================================*/
44
45 /*========================================================*/
46 /* Private types.                                         */
47 /*========================================================*/
48
49 struct _glLabelPrivate {
50
51         glTemplate *template;
52         gboolean rotate_flag;
53
54         gchar *filename;
55         gboolean modified_flag;
56         gint untitled_instance;
57
58         glMerge *merge;
59 };
60
61 enum {
62         CHANGED,
63         NAME_CHANGED,
64         MODIFIED_CHANGED,
65         MERGE_CHANGED,
66         LAST_SIGNAL
67 };
68
69 /*========================================================*/
70 /* Private globals.                                       */
71 /*========================================================*/
72
73 static GObjectClass *parent_class = NULL;
74
75 static guint signals[LAST_SIGNAL] = {0};
76
77 static guint untitled = 0;
78
79 /*========================================================*/
80 /* Private function prototypes.                           */
81 /*========================================================*/
82
83 static void gl_label_class_init    (glLabelClass *klass);
84 static void gl_label_instance_init (glLabel      *label);
85 static void gl_label_finalize      (GObject      *object);
86
87 static void object_changed_cb      (glLabelObject *object,
88                                     glLabel       *label);
89
90 static void object_moved_cb        (glLabelObject *object,
91                                     gdouble        x,
92                                     gdouble        y,
93                                     glLabel       *label);
94
95 \f
96 /*****************************************************************************/
97 /* Boilerplate object stuff.                                                 */
98 /*****************************************************************************/
99 GType
100 gl_label_get_type (void)
101 {
102         static GType type = 0;
103
104         if (!type) {
105                 GTypeInfo info = {
106                         sizeof (glLabelClass),
107                         NULL,
108                         NULL,
109                         (GClassInitFunc) gl_label_class_init,
110                         NULL,
111                         NULL,
112                         sizeof (glLabel),
113                         0,
114                         (GInstanceInitFunc) gl_label_instance_init,
115                 };
116
117                 type = g_type_register_static (G_TYPE_OBJECT,
118                                                "glLabel", &info, 0);
119         }
120
121         return type;
122 }
123
124 static void
125 gl_label_class_init (glLabelClass *klass)
126 {
127         GObjectClass *object_class = (GObjectClass *) klass;
128
129         gl_debug (DEBUG_LABEL, "START");
130
131         parent_class = g_type_class_peek_parent (klass);
132
133         object_class->finalize = gl_label_finalize;
134
135         signals[CHANGED] =
136                 g_signal_new ("changed",
137                               G_OBJECT_CLASS_TYPE (object_class),
138                               G_SIGNAL_RUN_LAST,
139                               G_STRUCT_OFFSET (glLabelClass, changed),
140                               NULL, NULL,
141                               gl_marshal_VOID__VOID,
142                               G_TYPE_NONE,
143                               0);
144         signals[NAME_CHANGED] =
145                 g_signal_new ("name_changed",
146                               G_OBJECT_CLASS_TYPE (object_class),
147                               G_SIGNAL_RUN_LAST,
148                               G_STRUCT_OFFSET (glLabelClass, name_changed),
149                               NULL, NULL,
150                               gl_marshal_VOID__VOID,
151                               G_TYPE_NONE,
152                               0);
153         signals[MODIFIED_CHANGED] =
154                 g_signal_new ("modified_changed",
155                               G_OBJECT_CLASS_TYPE (object_class),
156                               G_SIGNAL_RUN_LAST,
157                               G_STRUCT_OFFSET (glLabelClass, modified_changed),
158                               NULL, NULL,
159                               gl_marshal_VOID__VOID,
160                               G_TYPE_NONE,
161                               0);
162         signals[MERGE_CHANGED] =
163                 g_signal_new ("merge_changed",
164                               G_OBJECT_CLASS_TYPE (object_class),
165                               G_SIGNAL_RUN_LAST,
166                               G_STRUCT_OFFSET (glLabelClass, merge_changed),
167                               NULL, NULL,
168                               gl_marshal_VOID__VOID,
169                               G_TYPE_NONE,
170                               0);
171
172         gl_debug (DEBUG_LABEL, "END");
173 }
174
175 static void
176 gl_label_instance_init (glLabel *label)
177 {
178         gl_debug (DEBUG_LABEL, "START");
179
180         label->private = g_new0 (glLabelPrivate, 1);
181         label->private->merge = gl_merge_new();
182
183         gl_debug (DEBUG_LABEL, "END");
184 }
185
186 static void
187 gl_label_finalize (GObject *object)
188 {
189         glLabel *label;
190         GList   *p, *p_next;
191
192         gl_debug (DEBUG_LABEL, "START");
193
194         g_return_if_fail (object && GL_IS_LABEL (object));
195
196         label = GL_LABEL (object);
197
198         gl_template_free (&label->private->template);
199
200         for (p = label->objects; p != NULL; p = p_next) {
201                 p_next = p->next;       /* NOTE: p will be left dangling */
202                 g_object_unref (G_OBJECT(p->data));
203         }
204
205         gl_merge_free (&label->private->merge);
206
207         g_free (label->private);
208
209         G_OBJECT_CLASS (parent_class)->finalize (object);
210
211         gl_debug (DEBUG_LABEL, "END");
212 }
213
214 GObject *
215 gl_label_new (void)
216 {
217         glLabel *label;
218
219         gl_debug (DEBUG_LABEL, "START");
220
221         label = g_object_new (gl_label_get_type(), NULL);
222
223         label->private->modified_flag = FALSE;
224
225         gl_debug (DEBUG_LABEL, "END");
226
227         return G_OBJECT (label);
228 }
229
230
231 /*****************************************************************************/
232 /* Add object to label.                                                      */
233 /*****************************************************************************/
234 void
235 gl_label_add_object (glLabel       *label,
236                      glLabelObject *object)
237 {
238         gl_debug (DEBUG_LABEL, "START");
239
240         g_return_if_fail (label && GL_IS_LABEL (label));
241         g_return_if_fail (GL_IS_LABEL_OBJECT (object));
242
243         object->parent = label;
244         label->objects = g_list_append (label->objects, object);
245
246         label->private->modified_flag = TRUE;
247
248         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
249         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
250
251         g_signal_connect (G_OBJECT(object), "changed",
252                           G_CALLBACK(object_changed_cb), label);
253
254         g_signal_connect (G_OBJECT(object), "moved",
255                           G_CALLBACK(object_moved_cb), label);
256
257         gl_debug (DEBUG_LABEL, "END");
258 }
259
260 /*****************************************************************************/
261 /* Remove object from label.                                                 */
262 /*****************************************************************************/
263 void
264 gl_label_remove_object (glLabel       *label,
265                         glLabelObject *object)
266 {
267         gl_debug (DEBUG_LABEL, "START");
268
269         g_return_if_fail (label && GL_IS_LABEL (label));
270         g_return_if_fail (GL_IS_LABEL_OBJECT (object));
271
272         object->parent = NULL;
273         label->objects = g_list_remove (label->objects, object);
274
275         if ( G_OBJECT(label)->ref_count /* not finalized */ ) {
276
277                 g_signal_handlers_disconnect_by_func (object,
278                                                       G_CALLBACK(object_changed_cb),
279                                                       label);
280                 g_signal_handlers_disconnect_by_func (object,
281                                                       G_CALLBACK(object_moved_cb),
282                                                       label);
283
284                 label->private->modified_flag = TRUE;
285
286                 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
287                 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
288
289         }
290
291         gl_debug (DEBUG_LABEL, "END");
292 }
293
294 /*---------------------------------------------------------------------------*/
295 /* PRIVATE.  Object changed callback.                                        */
296 /*---------------------------------------------------------------------------*/
297 static void
298 object_changed_cb (glLabelObject *object,
299                    glLabel       *label)
300 {
301
302         if ( !label->private->modified_flag ) {
303
304                 label->private->modified_flag = TRUE;
305
306                 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
307         }
308
309         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
310 }
311
312 /*---------------------------------------------------------------------------*/
313 /* PRIVATE.  Object moved callback.                                          */
314 /*---------------------------------------------------------------------------*/
315 static void
316 object_moved_cb (glLabelObject *object,
317                  gdouble        x,
318                  gdouble        y,
319                  glLabel       *label)
320 {
321
322         if ( !label->private->modified_flag ) {
323
324                 label->private->modified_flag = TRUE;
325
326                 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
327         }
328
329         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
330 }
331
332 /****************************************************************************/
333 /* Bring label object to front/top.                                         */
334 /****************************************************************************/
335 void
336 gl_label_raise_object_to_top (glLabel       *label,
337                               glLabelObject *object)
338 {
339         gl_debug (DEBUG_LABEL, "START");
340
341         /* Move to end of list, representing front most object */
342         label->objects = g_list_remove (label->objects, object);
343         label->objects = g_list_append (label->objects, object);
344
345         label->private->modified_flag = TRUE;
346
347         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
348         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
349
350         gl_debug (DEBUG_LABEL, "END");
351 }
352
353 /****************************************************************************/
354 /* Send label object to rear/bottom.                                        */
355 /****************************************************************************/
356 void
357 gl_label_lower_object_to_bottom (glLabel       *label,
358                                  glLabelObject *object)
359 {
360         gl_debug (DEBUG_LABEL, "START");
361
362         /* Move to front of list, representing rear most object */
363         label->objects = g_list_remove (label->objects, object);
364         label->objects = g_list_prepend (label->objects, object);
365
366         label->private->modified_flag = TRUE;
367
368         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
369         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
370
371         gl_debug (DEBUG_LABEL, "END");
372 }
373
374 /****************************************************************************/
375 /* set template.                                                            */
376 /****************************************************************************/
377 extern void
378 gl_label_set_template (glLabel    *label,
379                        glTemplate *template)
380 {
381         gl_debug (DEBUG_LABEL, "START");
382
383         g_return_if_fail (label && GL_IS_LABEL (label));
384
385         gl_template_free (&label->private->template);
386         label->private->template = gl_template_dup (template);
387
388         label->private->modified_flag = TRUE;
389
390         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
391         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
392
393         gl_debug (DEBUG_LABEL, "END");
394 }
395
396 /****************************************************************************/
397 /* set rotate flag.                                                         */
398 /****************************************************************************/
399 extern void
400 gl_label_set_rotate_flag (glLabel *label,
401                           gboolean rotate_flag)
402 {
403         gl_debug (DEBUG_LABEL, "START");
404
405         g_return_if_fail (label && GL_IS_LABEL (label));
406
407         label->private->rotate_flag = rotate_flag;
408
409         label->private->modified_flag = TRUE;
410
411         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
412         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
413
414         gl_debug (DEBUG_LABEL, "END");
415 }
416
417 /****************************************************************************/
418 /* Get template.                                                            */
419 /****************************************************************************/
420 glTemplate *
421 gl_label_get_template (glLabel *label)
422 {
423         gl_debug (DEBUG_LABEL, "START");
424
425         g_return_if_fail (label && GL_IS_LABEL (label));
426
427         gl_debug (DEBUG_LABEL, "END");
428
429         return gl_template_dup (label->private->template);
430 }
431
432 /****************************************************************************/
433 /* Get rotate flag.                                                         */
434 /****************************************************************************/
435 gboolean
436 gl_label_get_rotate_flag (glLabel *label)
437 {
438         gl_debug (DEBUG_LABEL, "START");
439
440         g_return_if_fail (label && GL_IS_LABEL (label));
441
442         gl_debug (DEBUG_LABEL, "END");
443
444         return label->private->rotate_flag;
445 }
446
447 /****************************************************************************/
448 /* Get label size.                                                          */
449 /****************************************************************************/
450 void
451 gl_label_get_size (glLabel *label,
452                    gdouble *w,
453                    gdouble *h)
454 {
455         glTemplate *template;
456
457         gl_debug (DEBUG_LABEL, "START");
458
459         g_return_if_fail (label && GL_IS_LABEL (label));
460
461         template = label->private->template;
462         if ( !template ) {
463                 gl_debug (DEBUG_LABEL, "END -- template NULL");
464                 *w = *h = 0;
465                 return;
466         }
467
468         switch (template->label.style) {
469
470         case GL_TEMPLATE_STYLE_RECT:
471                 if (!label->private->rotate_flag) {
472                         *w = template->label.rect.w;
473                         *h = template->label.rect.h;
474                 } else {
475                         *w = template->label.rect.h;
476                         *h = template->label.rect.w;
477                 }
478                 break;
479
480         case GL_TEMPLATE_STYLE_ROUND:
481                 *w = *h = 2.0 * template->label.round.r;
482                 break;
483
484         case GL_TEMPLATE_STYLE_CD:
485                 *w = *h = 2.0 * template->label.cd.r1;
486                 break;
487
488         default:
489                 g_warning ("Unknown template label style %d",
490                            template->label.style);
491                 *w = *h = 0;
492                 break;
493         }
494
495         gl_debug (DEBUG_LABEL, "END");
496 }
497
498 /****************************************************************************/
499 /* set merge information structure.                                         */
500 /****************************************************************************/
501 extern void
502 gl_label_set_merge (glLabel *label,
503                     glMerge *merge)
504 {
505         gl_debug (DEBUG_LABEL, "START");
506
507         g_return_if_fail (label && GL_IS_LABEL (label));
508
509         gl_merge_free (&label->private->merge);
510         label->private->merge = gl_merge_dup (merge);
511
512         label->private->modified_flag = TRUE;
513
514         g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0);
515         g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
516         g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
517
518         gl_debug (DEBUG_LABEL, "END");
519 }
520
521 /****************************************************************************/
522 /* Get merge information structure.                                         */
523 /****************************************************************************/
524 glMerge *
525 gl_label_get_merge (glLabel *label)
526 {
527         gl_debug (DEBUG_LABEL, "START");
528
529         g_return_if_fail (label && GL_IS_LABEL (label));
530
531         gl_debug (DEBUG_LABEL, "END");
532
533         return gl_merge_dup (label->private->merge);
534 }
535
536 /****************************************************************************/
537 /* return filename.                                                         */
538 /****************************************************************************/
539 gchar *
540 gl_label_get_filename (glLabel *label)
541 {
542         gl_debug (DEBUG_LABEL, "");
543
544         return g_strdup ( label->private->filename );
545 }
546
547 /****************************************************************************/
548 /* return short filename.                                                   */
549 /****************************************************************************/
550 gchar *
551 gl_label_get_short_name (glLabel *label)
552 {
553         gl_debug (DEBUG_LABEL, "");
554
555         if ( label->private->filename == NULL ) {
556
557                 if ( label->private->untitled_instance == 0 ) {
558                         label->private->untitled_instance = ++untitled;
559                 }
560
561                 return g_strdup_printf ( "%s %d", _("Untitled"),
562                                          label->private->untitled_instance );
563
564         } else {
565                 gchar *temp_name, *short_name;
566
567                 temp_name = g_path_get_basename ( label->private->filename );
568                 short_name = gl_util_remove_extension (temp_name);
569                 g_free (temp_name);
570
571                 return short_name;
572         }
573 }
574
575 /****************************************************************************/
576 /* Is label modified?                                                       */
577 /****************************************************************************/
578 gboolean
579 gl_label_is_modified (glLabel *label)
580 {
581         gl_debug (DEBUG_LABEL, "return %d", label->private->modified_flag);
582         return label->private->modified_flag;
583 }
584
585 /****************************************************************************/
586 /* Is label untitled?                                                       */
587 /****************************************************************************/
588 gboolean
589 gl_label_is_untitled (glLabel *label)
590 {
591         gl_debug (DEBUG_LABEL, "return %d",(label->private->filename == NULL));
592         return (label->private->filename == NULL);
593 }
594
595 /****************************************************************************/
596 /* Can undo?                                                                */
597 /****************************************************************************/
598 gboolean
599 gl_label_can_undo (glLabel *label)
600 {
601         return FALSE;
602 }
603
604
605 /****************************************************************************/
606 /* Can redo?                                                                */
607 /****************************************************************************/
608 gboolean
609 gl_label_can_redo (glLabel *label)
610 {
611         return FALSE;
612 }
613
614
615 /****************************************************************************/
616 /* Set filename.                                                            */
617 /****************************************************************************/
618 void
619 gl_label_set_filename (glLabel     *label,
620                        const gchar *filename)
621 {
622         label->private->filename = g_strdup (filename);
623
624         g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
625 }
626
627 /****************************************************************************/
628 /* Clear modified flag.                                                     */
629 /****************************************************************************/
630 void
631 gl_label_clear_modified (glLabel *label)
632 {
633
634         if ( label->private->modified_flag ) {
635
636                 label->private->modified_flag = FALSE;
637
638                 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
639         }
640
641 }
642
643
644