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