2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * label.c: GLabels label module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
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.
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.
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
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"
41 /*========================================================*/
42 /* Private macros and constants. */
43 /*========================================================*/
45 /*========================================================*/
47 /*========================================================*/
49 struct _glLabelPrivate {
55 gboolean modified_flag;
56 gint untitled_instance;
69 /*========================================================*/
70 /* Private globals. */
71 /*========================================================*/
73 static GObjectClass *parent_class = NULL;
75 static guint signals[LAST_SIGNAL] = {0};
77 static guint untitled = 0;
79 /*========================================================*/
80 /* Private function prototypes. */
81 /*========================================================*/
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);
87 static void object_changed_cb (glLabelObject *object,
90 static void object_moved_cb (glLabelObject *object,
96 /*****************************************************************************/
97 /* Boilerplate object stuff. */
98 /*****************************************************************************/
100 gl_label_get_type (void)
102 static GType type = 0;
106 sizeof (glLabelClass),
109 (GClassInitFunc) gl_label_class_init,
114 (GInstanceInitFunc) gl_label_instance_init,
117 type = g_type_register_static (G_TYPE_OBJECT,
118 "glLabel", &info, 0);
125 gl_label_class_init (glLabelClass *klass)
127 GObjectClass *object_class = (GObjectClass *) klass;
129 gl_debug (DEBUG_LABEL, "START");
131 parent_class = g_type_class_peek_parent (klass);
133 object_class->finalize = gl_label_finalize;
136 g_signal_new ("changed",
137 G_OBJECT_CLASS_TYPE (object_class),
139 G_STRUCT_OFFSET (glLabelClass, changed),
141 gl_marshal_VOID__VOID,
144 signals[NAME_CHANGED] =
145 g_signal_new ("name_changed",
146 G_OBJECT_CLASS_TYPE (object_class),
148 G_STRUCT_OFFSET (glLabelClass, name_changed),
150 gl_marshal_VOID__VOID,
153 signals[MODIFIED_CHANGED] =
154 g_signal_new ("modified_changed",
155 G_OBJECT_CLASS_TYPE (object_class),
157 G_STRUCT_OFFSET (glLabelClass, modified_changed),
159 gl_marshal_VOID__VOID,
162 signals[MERGE_CHANGED] =
163 g_signal_new ("merge_changed",
164 G_OBJECT_CLASS_TYPE (object_class),
166 G_STRUCT_OFFSET (glLabelClass, merge_changed),
168 gl_marshal_VOID__VOID,
172 gl_debug (DEBUG_LABEL, "END");
176 gl_label_instance_init (glLabel *label)
178 gl_debug (DEBUG_LABEL, "START");
180 label->private = g_new0 (glLabelPrivate, 1);
181 label->private->merge = NULL;
183 gl_debug (DEBUG_LABEL, "END");
187 gl_label_finalize (GObject *object)
192 gl_debug (DEBUG_LABEL, "START");
194 g_return_if_fail (object && GL_IS_LABEL (object));
196 label = GL_LABEL (object);
198 gl_template_free (&label->private->template);
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));
205 g_object_unref (G_OBJECT(label->private->merge));
207 g_free (label->private);
209 G_OBJECT_CLASS (parent_class)->finalize (object);
211 gl_debug (DEBUG_LABEL, "END");
219 gl_debug (DEBUG_LABEL, "START");
221 label = g_object_new (gl_label_get_type(), NULL);
223 label->private->modified_flag = FALSE;
225 gl_debug (DEBUG_LABEL, "END");
227 return G_OBJECT (label);
231 /*****************************************************************************/
232 /* Add object to label. */
233 /*****************************************************************************/
235 gl_label_add_object (glLabel *label,
236 glLabelObject *object)
238 gl_debug (DEBUG_LABEL, "START");
240 g_return_if_fail (label && GL_IS_LABEL (label));
241 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
243 object->parent = label;
244 label->objects = g_list_append (label->objects, object);
246 label->private->modified_flag = TRUE;
248 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
249 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
251 g_signal_connect (G_OBJECT(object), "changed",
252 G_CALLBACK(object_changed_cb), label);
254 g_signal_connect (G_OBJECT(object), "moved",
255 G_CALLBACK(object_moved_cb), label);
257 gl_debug (DEBUG_LABEL, "END");
260 /*****************************************************************************/
261 /* Remove object from label. */
262 /*****************************************************************************/
264 gl_label_remove_object (glLabel *label,
265 glLabelObject *object)
267 gl_debug (DEBUG_LABEL, "START");
269 g_return_if_fail (label && GL_IS_LABEL (label));
270 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
272 object->parent = NULL;
273 label->objects = g_list_remove (label->objects, object);
275 if ( G_OBJECT(label)->ref_count /* not finalized */ ) {
277 g_signal_handlers_disconnect_by_func (object,
278 G_CALLBACK(object_changed_cb),
280 g_signal_handlers_disconnect_by_func (object,
281 G_CALLBACK(object_moved_cb),
284 label->private->modified_flag = TRUE;
286 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
287 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
291 gl_debug (DEBUG_LABEL, "END");
294 /*---------------------------------------------------------------------------*/
295 /* PRIVATE. Object changed callback. */
296 /*---------------------------------------------------------------------------*/
298 object_changed_cb (glLabelObject *object,
302 if ( !label->private->modified_flag ) {
304 label->private->modified_flag = TRUE;
306 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
309 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
312 /*---------------------------------------------------------------------------*/
313 /* PRIVATE. Object moved callback. */
314 /*---------------------------------------------------------------------------*/
316 object_moved_cb (glLabelObject *object,
322 if ( !label->private->modified_flag ) {
324 label->private->modified_flag = TRUE;
326 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
329 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
332 /****************************************************************************/
333 /* Bring label object to front/top. */
334 /****************************************************************************/
336 gl_label_raise_object_to_top (glLabel *label,
337 glLabelObject *object)
339 gl_debug (DEBUG_LABEL, "START");
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);
345 label->private->modified_flag = TRUE;
347 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
348 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
350 gl_debug (DEBUG_LABEL, "END");
353 /****************************************************************************/
354 /* Send label object to rear/bottom. */
355 /****************************************************************************/
357 gl_label_lower_object_to_bottom (glLabel *label,
358 glLabelObject *object)
360 gl_debug (DEBUG_LABEL, "START");
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);
366 label->private->modified_flag = TRUE;
368 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
369 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
371 gl_debug (DEBUG_LABEL, "END");
374 /****************************************************************************/
376 /****************************************************************************/
378 gl_label_set_template (glLabel *label,
379 glTemplate *template)
381 gl_debug (DEBUG_LABEL, "START");
383 g_return_if_fail (label && GL_IS_LABEL (label));
385 gl_template_free (&label->private->template);
386 label->private->template = gl_template_dup (template);
388 label->private->modified_flag = TRUE;
390 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
391 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
393 gl_debug (DEBUG_LABEL, "END");
396 /****************************************************************************/
397 /* set rotate flag. */
398 /****************************************************************************/
400 gl_label_set_rotate_flag (glLabel *label,
401 gboolean rotate_flag)
403 gl_debug (DEBUG_LABEL, "START");
405 g_return_if_fail (label && GL_IS_LABEL (label));
407 label->private->rotate_flag = rotate_flag;
409 label->private->modified_flag = TRUE;
411 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
412 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
414 gl_debug (DEBUG_LABEL, "END");
417 /****************************************************************************/
419 /****************************************************************************/
421 gl_label_get_template (glLabel *label)
423 gl_debug (DEBUG_LABEL, "START");
425 g_return_if_fail (label && GL_IS_LABEL (label));
427 gl_debug (DEBUG_LABEL, "END");
429 return gl_template_dup (label->private->template);
432 /****************************************************************************/
433 /* Get rotate flag. */
434 /****************************************************************************/
436 gl_label_get_rotate_flag (glLabel *label)
438 gl_debug (DEBUG_LABEL, "START");
440 g_return_if_fail (label && GL_IS_LABEL (label));
442 gl_debug (DEBUG_LABEL, "END");
444 return label->private->rotate_flag;
447 /****************************************************************************/
448 /* Get label size. */
449 /****************************************************************************/
451 gl_label_get_size (glLabel *label,
455 glTemplate *template;
457 gl_debug (DEBUG_LABEL, "START");
459 g_return_if_fail (label && GL_IS_LABEL (label));
461 template = label->private->template;
463 gl_debug (DEBUG_LABEL, "END -- template NULL");
468 switch (template->label.style) {
470 case GL_TEMPLATE_STYLE_RECT:
471 if (!label->private->rotate_flag) {
472 *w = template->label.rect.w;
473 *h = template->label.rect.h;
475 *w = template->label.rect.h;
476 *h = template->label.rect.w;
480 case GL_TEMPLATE_STYLE_ROUND:
481 *w = *h = 2.0 * template->label.round.r;
484 case GL_TEMPLATE_STYLE_CD:
485 *w = *h = 2.0 * template->label.cd.r1;
489 g_warning ("Unknown template label style %d",
490 template->label.style);
495 gl_debug (DEBUG_LABEL, "END");
498 /****************************************************************************/
499 /* set merge information structure. */
500 /****************************************************************************/
502 gl_label_set_merge (glLabel *label,
505 gl_debug (DEBUG_LABEL, "START");
507 g_return_if_fail (label && GL_IS_LABEL (label));
509 g_object_unref (G_OBJECT(label->private->merge));
510 label->private->merge = gl_merge_dup (merge);
512 label->private->modified_flag = TRUE;
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);
518 gl_debug (DEBUG_LABEL, "END");
521 /****************************************************************************/
522 /* Get merge information structure. */
523 /****************************************************************************/
525 gl_label_get_merge (glLabel *label)
527 gl_debug (DEBUG_LABEL, "START");
529 g_return_if_fail (label && GL_IS_LABEL (label));
531 gl_debug (DEBUG_LABEL, "END");
533 return gl_merge_dup (label->private->merge);
536 /****************************************************************************/
537 /* return filename. */
538 /****************************************************************************/
540 gl_label_get_filename (glLabel *label)
542 gl_debug (DEBUG_LABEL, "");
544 return g_strdup ( label->private->filename );
547 /****************************************************************************/
548 /* return short filename. */
549 /****************************************************************************/
551 gl_label_get_short_name (glLabel *label)
553 gl_debug (DEBUG_LABEL, "");
555 if ( label->private->filename == NULL ) {
557 if ( label->private->untitled_instance == 0 ) {
558 label->private->untitled_instance = ++untitled;
561 return g_strdup_printf ( "%s %d", _("Untitled"),
562 label->private->untitled_instance );
565 gchar *temp_name, *short_name;
567 temp_name = g_path_get_basename ( label->private->filename );
568 short_name = gl_util_remove_extension (temp_name);
575 /****************************************************************************/
576 /* Is label modified? */
577 /****************************************************************************/
579 gl_label_is_modified (glLabel *label)
581 gl_debug (DEBUG_LABEL, "return %d", label->private->modified_flag);
582 return label->private->modified_flag;
585 /****************************************************************************/
586 /* Is label untitled? */
587 /****************************************************************************/
589 gl_label_is_untitled (glLabel *label)
591 gl_debug (DEBUG_LABEL, "return %d",(label->private->filename == NULL));
592 return (label->private->filename == NULL);
595 /****************************************************************************/
597 /****************************************************************************/
599 gl_label_can_undo (glLabel *label)
605 /****************************************************************************/
607 /****************************************************************************/
609 gl_label_can_redo (glLabel *label)
615 /****************************************************************************/
617 /****************************************************************************/
619 gl_label_set_filename (glLabel *label,
620 const gchar *filename)
622 label->private->filename = g_strdup (filename);
624 g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
627 /****************************************************************************/
628 /* Clear modified flag. */
629 /****************************************************************************/
631 gl_label_clear_modified (glLabel *label)
634 if ( label->private->modified_flag ) {
636 label->private->modified_flag = FALSE;
638 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);