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