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"
40 /*========================================================*/
41 /* Private macros and constants. */
42 /*========================================================*/
44 /*========================================================*/
46 /*========================================================*/
48 struct _glLabelPrivate {
54 gboolean modified_flag;
55 gint untitled_instance;
67 /*========================================================*/
68 /* Private globals. */
69 /*========================================================*/
71 static GObjectClass *parent_class = NULL;
73 static guint signals[LAST_SIGNAL] = {0};
75 static guint untitled = 0;
77 /*========================================================*/
78 /* Private function prototypes. */
79 /*========================================================*/
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);
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);
90 /*****************************************************************************/
91 /* Boilerplate object stuff. */
92 /*****************************************************************************/
94 gl_label_get_type (void)
96 static GType type = 0;
100 sizeof (glLabelClass),
103 (GClassInitFunc) gl_label_class_init,
108 (GInstanceInitFunc) gl_label_instance_init,
111 type = g_type_register_static (G_TYPE_OBJECT,
112 "glLabel", &info, 0);
119 gl_label_class_init (glLabelClass *klass)
121 GObjectClass *object_class = (GObjectClass *) klass;
123 gl_debug (DEBUG_LABEL, "START");
125 parent_class = g_type_class_peek_parent (klass);
127 object_class->finalize = gl_label_finalize;
130 g_signal_new ("changed",
131 G_OBJECT_CLASS_TYPE (object_class),
133 G_STRUCT_OFFSET (glLabelClass, changed),
135 gl_marshal_VOID__VOID,
138 signals[NAME_CHANGED] =
139 g_signal_new ("name_changed",
140 G_OBJECT_CLASS_TYPE (object_class),
142 G_STRUCT_OFFSET (glLabelClass, name_changed),
144 gl_marshal_VOID__VOID,
147 signals[MODIFIED_CHANGED] =
148 g_signal_new ("modified_changed",
149 G_OBJECT_CLASS_TYPE (object_class),
151 G_STRUCT_OFFSET (glLabelClass, modified_changed),
153 gl_marshal_VOID__VOID,
157 gl_debug (DEBUG_LABEL, "END");
161 gl_label_instance_init (glLabel *label)
163 gl_debug (DEBUG_LABEL, "START");
165 label->private = g_new0 (glLabelPrivate, 1);
166 label->private->merge = gl_merge_new();
168 gl_debug (DEBUG_LABEL, "END");
172 gl_label_finalize (GObject *object)
177 gl_debug (DEBUG_LABEL, "START");
179 g_return_if_fail (object && GL_IS_LABEL (object));
181 label = GL_LABEL (object);
183 gl_template_free (&label->private->template);
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));
190 gl_merge_free (&label->private->merge);
192 g_free (label->private);
194 G_OBJECT_CLASS (parent_class)->finalize (object);
196 gl_debug (DEBUG_LABEL, "END");
204 gl_debug (DEBUG_LABEL, "START");
206 label = g_object_new (gl_label_get_type(), NULL);
208 label->private->modified_flag = FALSE;
210 gl_debug (DEBUG_LABEL, "END");
212 return G_OBJECT (label);
216 /*****************************************************************************/
217 /* Add object to label. */
218 /*****************************************************************************/
220 gl_label_add_object (glLabel *label,
221 glLabelObject *object)
223 gl_debug (DEBUG_LABEL, "START");
225 g_return_if_fail (label && GL_IS_LABEL (label));
226 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
228 object->parent = label;
229 label->objects = g_list_append (label->objects, object);
231 label->private->modified_flag = TRUE;
233 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
234 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
236 g_signal_connect (G_OBJECT(object), "changed",
237 G_CALLBACK(object_changed_cb), label);
239 g_signal_connect (G_OBJECT(object), "moved",
240 G_CALLBACK(object_moved_cb), label);
242 gl_debug (DEBUG_LABEL, "END");
245 /*****************************************************************************/
246 /* Remove object from label. */
247 /*****************************************************************************/
249 gl_label_remove_object (glLabel *label,
250 glLabelObject *object)
252 gl_debug (DEBUG_LABEL, "START");
254 g_return_if_fail (label && GL_IS_LABEL (label));
255 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
257 object->parent = NULL;
258 label->objects = g_list_remove (label->objects, object);
260 if ( G_OBJECT(label)->ref_count /* not finalized */ ) {
262 g_signal_handlers_disconnect_by_func (object,
263 G_CALLBACK(object_changed_cb),
265 g_signal_handlers_disconnect_by_func (object,
266 G_CALLBACK(object_moved_cb),
269 label->private->modified_flag = TRUE;
271 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
272 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
276 gl_debug (DEBUG_LABEL, "END");
279 /*---------------------------------------------------------------------------*/
280 /* PRIVATE. Object changed callback. */
281 /*---------------------------------------------------------------------------*/
283 object_changed_cb (glLabelObject *object, glLabel *label)
286 if ( !label->private->modified_flag ) {
288 label->private->modified_flag = TRUE;
290 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
293 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
296 /*---------------------------------------------------------------------------*/
297 /* PRIVATE. Object moved callback. */
298 /*---------------------------------------------------------------------------*/
300 object_moved_cb (glLabelObject *object, gdouble x, gdouble y, glLabel *label)
303 if ( !label->private->modified_flag ) {
305 label->private->modified_flag = TRUE;
307 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
310 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
313 /****************************************************************************/
314 /* Bring label object to front/top. */
315 /****************************************************************************/
317 gl_label_raise_object_to_top (glLabel *label, glLabelObject *object)
319 gl_debug (DEBUG_LABEL, "START");
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);
325 label->private->modified_flag = TRUE;
327 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
328 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
330 gl_debug (DEBUG_LABEL, "END");
333 /****************************************************************************/
334 /* Send label object to rear/bottom. */
335 /****************************************************************************/
337 gl_label_lower_object_to_bottom (glLabel *label, glLabelObject *object)
339 gl_debug (DEBUG_LABEL, "START");
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);
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 /****************************************************************************/
355 /****************************************************************************/
357 gl_label_set_template (glLabel *label,
358 glTemplate *template)
360 gl_debug (DEBUG_LABEL, "START");
362 g_return_if_fail (label && GL_IS_LABEL (label));
364 gl_template_free (&label->private->template);
365 label->private->template = gl_template_dup (template);
367 label->private->modified_flag = TRUE;
369 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
370 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
372 gl_debug (DEBUG_LABEL, "END");
375 /****************************************************************************/
376 /* set rotate flag. */
377 /****************************************************************************/
379 gl_label_set_rotate_flag (glLabel *label,
380 gboolean rotate_flag)
382 gl_debug (DEBUG_LABEL, "START");
384 g_return_if_fail (label && GL_IS_LABEL (label));
386 label->private->rotate_flag = rotate_flag;
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 /****************************************************************************/
398 /****************************************************************************/
400 gl_label_get_template (glLabel * label)
402 gl_debug (DEBUG_LABEL, "START");
404 g_return_if_fail (label && GL_IS_LABEL (label));
406 gl_debug (DEBUG_LABEL, "END");
408 return gl_template_dup (label->private->template);
411 /****************************************************************************/
412 /* Get rotate flag. */
413 /****************************************************************************/
415 gl_label_get_rotate_flag (glLabel * label)
417 gl_debug (DEBUG_LABEL, "START");
419 g_return_if_fail (label && GL_IS_LABEL (label));
421 gl_debug (DEBUG_LABEL, "END");
423 return label->private->rotate_flag;
426 /****************************************************************************/
427 /* Get label size. */
428 /****************************************************************************/
430 gl_label_get_size (glLabel * label,
434 glTemplate *template;
436 gl_debug (DEBUG_LABEL, "START");
438 g_return_if_fail (label && GL_IS_LABEL (label));
440 template = label->private->template;
442 gl_debug (DEBUG_LABEL, "END -- template NULL");
447 switch (template->style) {
449 case GL_TEMPLATE_STYLE_RECT:
450 if (!label->private->rotate_flag) {
451 *w = template->label_width;
452 *h = template->label_height;
454 *w = template->label_height;
455 *h = template->label_width;
459 case GL_TEMPLATE_STYLE_ROUND:
460 case GL_TEMPLATE_STYLE_CD:
461 *w = *h = 2.0 * template->label_radius;
465 g_warning ("Unknown template label style %d", template->style);
470 gl_debug (DEBUG_LABEL, "END");
473 /****************************************************************************/
474 /* set merge information structure. */
475 /****************************************************************************/
477 gl_label_set_merge (glLabel * label,
480 gl_debug (DEBUG_LABEL, "START");
482 g_return_if_fail (label && GL_IS_LABEL (label));
484 gl_merge_free (&label->private->merge);
485 label->private->merge = gl_merge_dup (merge);
487 label->private->modified_flag = TRUE;
489 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
490 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
492 gl_debug (DEBUG_LABEL, "END");
495 /****************************************************************************/
496 /* Get merge information structure. */
497 /****************************************************************************/
499 gl_label_get_merge (glLabel * label)
501 gl_debug (DEBUG_LABEL, "START");
503 g_return_if_fail (label && GL_IS_LABEL (label));
505 gl_debug (DEBUG_LABEL, "END");
507 return gl_merge_dup (label->private->merge);
510 /****************************************************************************/
511 /* return filename. */
512 /****************************************************************************/
514 gl_label_get_filename (glLabel * label)
516 gl_debug (DEBUG_LABEL, "");
518 return g_strdup ( label->private->filename );
521 /****************************************************************************/
522 /* return short filename. */
523 /****************************************************************************/
525 gl_label_get_short_name (glLabel * label)
527 gl_debug (DEBUG_LABEL, "");
529 if ( label->private->filename == NULL ) {
531 if ( label->private->untitled_instance == 0 ) {
532 label->private->untitled_instance = ++untitled;
535 return g_strdup_printf ( "%s %d", _("Untitled"),
536 label->private->untitled_instance );
539 gchar *temp_name, *short_name;
541 temp_name = g_path_get_basename ( label->private->filename );
542 short_name = gl_util_remove_extension (temp_name);
549 /****************************************************************************/
550 /* Is label modified? */
551 /****************************************************************************/
553 gl_label_is_modified (glLabel * label)
555 gl_debug (DEBUG_LABEL, "return %d", label->private->modified_flag);
556 return label->private->modified_flag;
559 /****************************************************************************/
560 /* Is label untitled? */
561 /****************************************************************************/
563 gl_label_is_untitled (glLabel * label)
565 gl_debug (DEBUG_LABEL, "return %d",(label->private->filename == NULL));
566 return (label->private->filename == NULL);
569 /****************************************************************************/
571 /****************************************************************************/
573 gl_label_can_undo (glLabel * label)
579 /****************************************************************************/
581 /****************************************************************************/
583 gl_label_can_redo (glLabel * label)
589 /****************************************************************************/
591 /****************************************************************************/
593 gl_label_set_filename (glLabel *label,
594 const gchar *filename)
596 label->private->filename = g_strdup (filename);
598 g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
601 /****************************************************************************/
602 /* Clear modified flag. */
603 /****************************************************************************/
605 gl_label_clear_modified (glLabel *label)
608 if ( label->private->modified_flag ) {
610 label->private->modified_flag = FALSE;
612 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);