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"
34 /*========================================================*/
35 /* Private macros and constants. */
36 /*========================================================*/
38 /*========================================================*/
40 /*========================================================*/
42 struct _glLabelPrivate {
48 gboolean modified_flag;
49 gint untitled_instance;
53 GHashTable *pixbuf_cache;
65 /*========================================================*/
66 /* Private globals. */
67 /*========================================================*/
69 static GObjectClass *parent_class = NULL;
71 static guint signals[LAST_SIGNAL] = {0};
73 static guint untitled = 0;
75 /*========================================================*/
76 /* Private function prototypes. */
77 /*========================================================*/
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);
83 static void object_changed_cb (glLabelObject *object,
86 static void object_moved_cb (glLabelObject *object,
92 /*****************************************************************************/
93 /* Boilerplate object stuff. */
94 /*****************************************************************************/
96 gl_label_get_type (void)
98 static GType type = 0;
102 sizeof (glLabelClass),
105 (GClassInitFunc) gl_label_class_init,
110 (GInstanceInitFunc) gl_label_instance_init,
113 type = g_type_register_static (G_TYPE_OBJECT,
114 "glLabel", &info, 0);
121 gl_label_class_init (glLabelClass *klass)
123 GObjectClass *object_class = (GObjectClass *) klass;
125 gl_debug (DEBUG_LABEL, "START");
127 parent_class = g_type_class_peek_parent (klass);
129 object_class->finalize = gl_label_finalize;
132 g_signal_new ("changed",
133 G_OBJECT_CLASS_TYPE (object_class),
135 G_STRUCT_OFFSET (glLabelClass, changed),
137 gl_marshal_VOID__VOID,
140 signals[NAME_CHANGED] =
141 g_signal_new ("name_changed",
142 G_OBJECT_CLASS_TYPE (object_class),
144 G_STRUCT_OFFSET (glLabelClass, name_changed),
146 gl_marshal_VOID__VOID,
149 signals[MODIFIED_CHANGED] =
150 g_signal_new ("modified_changed",
151 G_OBJECT_CLASS_TYPE (object_class),
153 G_STRUCT_OFFSET (glLabelClass, modified_changed),
155 gl_marshal_VOID__VOID,
158 signals[MERGE_CHANGED] =
159 g_signal_new ("merge_changed",
160 G_OBJECT_CLASS_TYPE (object_class),
162 G_STRUCT_OFFSET (glLabelClass, merge_changed),
164 gl_marshal_VOID__VOID,
167 signals[SIZE_CHANGED] =
168 g_signal_new ("size_changed",
169 G_OBJECT_CLASS_TYPE (object_class),
171 G_STRUCT_OFFSET (glLabelClass, size_changed),
173 gl_marshal_VOID__VOID,
177 gl_debug (DEBUG_LABEL, "END");
181 gl_label_instance_init (glLabel *label)
183 gl_debug (DEBUG_LABEL, "START");
185 label->private = g_new0 (glLabelPrivate, 1);
186 label->private->merge = NULL;
187 label->private->pixbuf_cache = gl_pixbuf_cache_new ();
189 gl_debug (DEBUG_LABEL, "END");
193 gl_label_finalize (GObject *object)
198 gl_debug (DEBUG_LABEL, "START");
200 g_return_if_fail (object && GL_IS_LABEL (object));
202 label = GL_LABEL (object);
204 gl_template_free (&label->private->template);
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));
211 if (label->private->merge != NULL) {
212 g_object_unref (G_OBJECT(label->private->merge));
215 gl_pixbuf_cache_free (label->private->pixbuf_cache);
217 g_free (label->private);
219 G_OBJECT_CLASS (parent_class)->finalize (object);
221 gl_debug (DEBUG_LABEL, "END");
229 gl_debug (DEBUG_LABEL, "START");
231 label = g_object_new (gl_label_get_type(), NULL);
233 label->private->modified_flag = FALSE;
235 gl_debug (DEBUG_LABEL, "END");
237 return G_OBJECT (label);
241 /*****************************************************************************/
242 /* Add object to label. */
243 /*****************************************************************************/
245 gl_label_add_object (glLabel *label,
246 glLabelObject *object)
248 gl_debug (DEBUG_LABEL, "START");
250 g_return_if_fail (label && GL_IS_LABEL (label));
251 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
253 object->parent = label;
254 label->objects = g_list_append (label->objects, object);
256 label->private->modified_flag = TRUE;
258 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
259 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
261 g_signal_connect (G_OBJECT(object), "changed",
262 G_CALLBACK(object_changed_cb), label);
264 g_signal_connect (G_OBJECT(object), "moved",
265 G_CALLBACK(object_moved_cb), label);
267 gl_debug (DEBUG_LABEL, "END");
270 /*****************************************************************************/
271 /* Remove object from label. */
272 /*****************************************************************************/
274 gl_label_remove_object (glLabel *label,
275 glLabelObject *object)
277 gl_debug (DEBUG_LABEL, "START");
279 g_return_if_fail (label && GL_IS_LABEL (label));
280 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
282 object->parent = NULL;
283 label->objects = g_list_remove (label->objects, object);
285 if ( G_OBJECT(label)->ref_count /* not finalized */ ) {
287 g_signal_handlers_disconnect_by_func (object,
288 G_CALLBACK(object_changed_cb),
290 g_signal_handlers_disconnect_by_func (object,
291 G_CALLBACK(object_moved_cb),
294 label->private->modified_flag = TRUE;
296 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
297 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
301 gl_debug (DEBUG_LABEL, "END");
304 /*---------------------------------------------------------------------------*/
305 /* PRIVATE. Object changed callback. */
306 /*---------------------------------------------------------------------------*/
308 object_changed_cb (glLabelObject *object,
312 if ( !label->private->modified_flag ) {
314 label->private->modified_flag = TRUE;
316 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
319 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
322 /*---------------------------------------------------------------------------*/
323 /* PRIVATE. Object moved callback. */
324 /*---------------------------------------------------------------------------*/
326 object_moved_cb (glLabelObject *object,
332 if ( !label->private->modified_flag ) {
334 label->private->modified_flag = TRUE;
336 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
339 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
342 /****************************************************************************/
343 /* Bring label object to front/top. */
344 /****************************************************************************/
346 gl_label_raise_object_to_top (glLabel *label,
347 glLabelObject *object)
349 gl_debug (DEBUG_LABEL, "START");
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);
355 label->private->modified_flag = TRUE;
357 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
358 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
360 gl_debug (DEBUG_LABEL, "END");
363 /****************************************************************************/
364 /* Send label object to rear/bottom. */
365 /****************************************************************************/
367 gl_label_lower_object_to_bottom (glLabel *label,
368 glLabelObject *object)
370 gl_debug (DEBUG_LABEL, "START");
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);
376 label->private->modified_flag = TRUE;
378 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
379 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
381 gl_debug (DEBUG_LABEL, "END");
384 /****************************************************************************/
386 /****************************************************************************/
388 gl_label_set_template (glLabel *label,
389 glTemplate *template)
391 gl_debug (DEBUG_LABEL, "START");
393 g_return_if_fail (label && GL_IS_LABEL (label));
395 if ((label->private->template == NULL) ||
396 (g_strcasecmp (template->name, label->private->template->name) != 0)) {
398 gl_template_free (&label->private->template);
399 label->private->template = gl_template_dup (template);
401 label->private->modified_flag = TRUE;
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);
409 gl_debug (DEBUG_LABEL, "END");
412 /****************************************************************************/
413 /* set rotate flag. */
414 /****************************************************************************/
416 gl_label_set_rotate_flag (glLabel *label,
417 gboolean rotate_flag)
419 gl_debug (DEBUG_LABEL, "START");
421 g_return_if_fail (label && GL_IS_LABEL (label));
423 if (rotate_flag != label->private->rotate_flag) {
425 label->private->rotate_flag = rotate_flag;
427 label->private->modified_flag = TRUE;
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);
435 gl_debug (DEBUG_LABEL, "END");
438 /****************************************************************************/
440 /****************************************************************************/
442 gl_label_get_template (glLabel *label)
444 gl_debug (DEBUG_LABEL, "START");
446 g_return_if_fail (label && GL_IS_LABEL (label));
448 gl_debug (DEBUG_LABEL, "END");
450 return gl_template_dup (label->private->template);
453 /****************************************************************************/
454 /* Get rotate flag. */
455 /****************************************************************************/
457 gl_label_get_rotate_flag (glLabel *label)
459 gl_debug (DEBUG_LABEL, "START");
461 g_return_if_fail (label && GL_IS_LABEL (label));
463 gl_debug (DEBUG_LABEL, "END");
465 return label->private->rotate_flag;
468 /****************************************************************************/
469 /* Get label size. */
470 /****************************************************************************/
472 gl_label_get_size (glLabel *label,
476 glTemplate *template;
478 gl_debug (DEBUG_LABEL, "START");
480 g_return_if_fail (label && GL_IS_LABEL (label));
482 template = label->private->template;
484 gl_debug (DEBUG_LABEL, "END -- template NULL");
489 if (!label->private->rotate_flag) {
490 gl_template_get_label_size (template, w, h);
492 gl_template_get_label_size (template, h, w);
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 if ( label->private->merge != NULL ) {
510 g_object_unref (G_OBJECT(label->private->merge));
512 label->private->merge = gl_merge_dup (merge);
514 label->private->modified_flag = TRUE;
516 g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0);
517 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
518 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
520 gl_debug (DEBUG_LABEL, "END");
523 /****************************************************************************/
524 /* Get merge information structure. */
525 /****************************************************************************/
527 gl_label_get_merge (glLabel *label)
529 gl_debug (DEBUG_LABEL, "START");
531 g_return_if_fail (label && GL_IS_LABEL (label));
533 gl_debug (DEBUG_LABEL, "END");
535 return gl_merge_dup (label->private->merge);
538 /****************************************************************************/
539 /* return filename. */
540 /****************************************************************************/
542 gl_label_get_filename (glLabel *label)
544 gl_debug (DEBUG_LABEL, "");
546 return g_strdup ( label->private->filename );
549 /****************************************************************************/
550 /* return short filename. */
551 /****************************************************************************/
553 gl_label_get_short_name (glLabel *label)
555 gl_debug (DEBUG_LABEL, "");
557 if ( label->private->filename == NULL ) {
559 if ( label->private->untitled_instance == 0 ) {
560 label->private->untitled_instance = ++untitled;
563 return g_strdup_printf ( "%s %d", _("Untitled"),
564 label->private->untitled_instance );
567 gchar *temp_name, *short_name;
569 temp_name = g_path_get_basename ( label->private->filename );
570 short_name = gl_util_remove_extension (temp_name);
577 /****************************************************************************/
578 /* Get pixbuf cache. */
579 /****************************************************************************/
581 gl_label_get_pixbuf_cache (glLabel *label)
583 return label->private->pixbuf_cache;
586 /****************************************************************************/
587 /* Is label modified? */
588 /****************************************************************************/
590 gl_label_is_modified (glLabel *label)
592 gl_debug (DEBUG_LABEL, "return %d", label->private->modified_flag);
593 return label->private->modified_flag;
596 /****************************************************************************/
597 /* Is label untitled? */
598 /****************************************************************************/
600 gl_label_is_untitled (glLabel *label)
602 gl_debug (DEBUG_LABEL, "return %d",(label->private->filename == NULL));
603 return (label->private->filename == NULL);
606 /****************************************************************************/
608 /****************************************************************************/
610 gl_label_can_undo (glLabel *label)
616 /****************************************************************************/
618 /****************************************************************************/
620 gl_label_can_redo (glLabel *label)
626 /****************************************************************************/
628 /****************************************************************************/
630 gl_label_set_filename (glLabel *label,
631 const gchar *filename)
633 label->private->filename = g_strdup (filename);
635 g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
638 /****************************************************************************/
639 /* Clear modified flag. */
640 /****************************************************************************/
642 gl_label_clear_modified (glLabel *label)
645 if ( label->private->modified_flag ) {
647 label->private->modified_flag = FALSE;
649 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);