3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
25 #include <glib/gi18n.h>
34 /*========================================================*/
35 /* Private macros and constants. */
36 /*========================================================*/
39 /*========================================================*/
41 /*========================================================*/
43 struct _glLabelPrivate {
47 gboolean modified_flag;
48 gint untitled_instance;
52 GHashTable *pixbuf_cache;
66 /*========================================================*/
67 /* Private globals. */
68 /*========================================================*/
70 static guint signals[LAST_SIGNAL] = {0};
72 static guint untitled = 0;
75 /*========================================================*/
76 /* Private function prototypes. */
77 /*========================================================*/
79 static void gl_label_finalize (GObject *object);
81 static void object_changed_cb (glLabelObject *object,
84 static void object_moved_cb (glLabelObject *object,
90 /*****************************************************************************/
91 /* Boilerplate object stuff. */
92 /*****************************************************************************/
93 G_DEFINE_TYPE (glLabel, gl_label, G_TYPE_OBJECT);
97 gl_label_class_init (glLabelClass *class)
99 GObjectClass *object_class = G_OBJECT_CLASS (class);
101 gl_debug (DEBUG_LABEL, "START");
103 gl_label_parent_class = g_type_class_peek_parent (class);
105 object_class->finalize = gl_label_finalize;
108 g_signal_new ("changed",
109 G_OBJECT_CLASS_TYPE (object_class),
111 G_STRUCT_OFFSET (glLabelClass, changed),
113 gl_marshal_VOID__VOID,
116 signals[NAME_CHANGED] =
117 g_signal_new ("name_changed",
118 G_OBJECT_CLASS_TYPE (object_class),
120 G_STRUCT_OFFSET (glLabelClass, name_changed),
122 gl_marshal_VOID__VOID,
125 signals[MODIFIED_CHANGED] =
126 g_signal_new ("modified_changed",
127 G_OBJECT_CLASS_TYPE (object_class),
129 G_STRUCT_OFFSET (glLabelClass, modified_changed),
131 gl_marshal_VOID__VOID,
134 signals[MERGE_CHANGED] =
135 g_signal_new ("merge_changed",
136 G_OBJECT_CLASS_TYPE (object_class),
138 G_STRUCT_OFFSET (glLabelClass, merge_changed),
140 gl_marshal_VOID__VOID,
143 signals[SIZE_CHANGED] =
144 g_signal_new ("size_changed",
145 G_OBJECT_CLASS_TYPE (object_class),
147 G_STRUCT_OFFSET (glLabelClass, size_changed),
149 gl_marshal_VOID__VOID,
152 signals[OBJECT_ADDED] =
153 g_signal_new ("object_added",
154 G_OBJECT_CLASS_TYPE (object_class),
156 G_STRUCT_OFFSET (glLabelClass, object_added),
158 gl_marshal_VOID__OBJECT,
162 gl_debug (DEBUG_LABEL, "END");
167 gl_label_init (glLabel *label)
169 gl_debug (DEBUG_LABEL, "START");
171 label->template = NULL;
172 label->rotate_flag = FALSE;
173 label->objects = NULL;
175 label->priv = g_new0 (glLabelPrivate, 1);
177 label->priv->filename = NULL;
178 label->priv->merge = NULL;
179 label->priv->pixbuf_cache = gl_pixbuf_cache_new ();
181 gl_debug (DEBUG_LABEL, "END");
186 gl_label_finalize (GObject *object)
188 glLabel *label = GL_LABEL (object);
191 gl_debug (DEBUG_LABEL, "START");
193 g_return_if_fail (object && GL_IS_LABEL (object));
195 for (p = label->objects; p != NULL; p = p_next) {
196 p_next = p->next; /* NOTE: p will be left dangling */
197 g_object_unref (G_OBJECT(p->data));
200 lgl_template_free (label->template);
201 g_free (label->priv->filename);
202 if (label->priv->merge != NULL) {
203 g_object_unref (G_OBJECT(label->priv->merge));
205 gl_pixbuf_cache_free (label->priv->pixbuf_cache);
207 g_free (label->priv);
209 G_OBJECT_CLASS (gl_label_parent_class)->finalize (object);
211 gl_debug (DEBUG_LABEL, "END");
220 gl_debug (DEBUG_LABEL, "START");
222 label = g_object_new (gl_label_get_type(), NULL);
224 label->priv->compression = 9;
226 label->priv->modified_flag = FALSE;
228 gl_debug (DEBUG_LABEL, "END");
230 return G_OBJECT (label);
234 /*****************************************************************************/
235 /* Add object to label. */
236 /*****************************************************************************/
238 gl_label_add_object (glLabel *label,
239 glLabelObject *object)
241 gl_debug (DEBUG_LABEL, "START");
243 g_return_if_fail (label && GL_IS_LABEL (label));
244 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
246 object->parent = label;
247 label->objects = g_list_append (label->objects, g_object_ref (object));
249 label->priv->modified_flag = TRUE;
251 g_signal_emit (G_OBJECT(label), signals[OBJECT_ADDED], 0, object);
252 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
253 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
255 g_signal_connect (G_OBJECT(object), "changed",
256 G_CALLBACK(object_changed_cb), label);
258 g_signal_connect (G_OBJECT(object), "moved",
259 G_CALLBACK(object_moved_cb), label);
261 gl_debug (DEBUG_LABEL, "END");
265 /*****************************************************************************/
266 /* Remove object from label. */
267 /*****************************************************************************/
269 gl_label_remove_object (glLabel *label,
270 glLabelObject *object)
272 gl_debug (DEBUG_LABEL, "START");
274 g_return_if_fail (label && GL_IS_LABEL (label));
275 g_return_if_fail (GL_IS_LABEL_OBJECT (object));
277 object->parent = NULL;
278 label->objects = g_list_remove (label->objects, object);
280 if ( G_OBJECT(label)->ref_count /* not finalized */ ) {
282 g_signal_handlers_disconnect_by_func (object,
283 G_CALLBACK(object_changed_cb),
285 g_signal_handlers_disconnect_by_func (object,
286 G_CALLBACK(object_moved_cb),
289 label->priv->modified_flag = TRUE;
291 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
292 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
296 gl_debug (DEBUG_LABEL, "END");
300 /*---------------------------------------------------------------------------*/
301 /* PRIVATE. Object changed callback. */
302 /*---------------------------------------------------------------------------*/
304 object_changed_cb (glLabelObject *object,
308 if ( !label->priv->modified_flag ) {
310 label->priv->modified_flag = TRUE;
312 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
315 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
319 /*---------------------------------------------------------------------------*/
320 /* PRIVATE. Object moved callback. */
321 /*---------------------------------------------------------------------------*/
323 object_moved_cb (glLabelObject *object,
329 if ( !label->priv->modified_flag ) {
331 label->priv->modified_flag = TRUE;
333 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
336 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
340 /****************************************************************************/
341 /* Bring label object to front/top. */
342 /****************************************************************************/
344 gl_label_raise_object_to_top (glLabel *label,
345 glLabelObject *object)
347 gl_debug (DEBUG_LABEL, "START");
349 /* Move to end of list, representing front most object */
350 label->objects = g_list_remove (label->objects, object);
351 label->objects = g_list_append (label->objects, object);
353 label->priv->modified_flag = TRUE;
355 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
356 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
358 gl_debug (DEBUG_LABEL, "END");
362 /****************************************************************************/
363 /* Send label object to rear/bottom. */
364 /****************************************************************************/
366 gl_label_lower_object_to_bottom (glLabel *label,
367 glLabelObject *object)
369 gl_debug (DEBUG_LABEL, "START");
371 /* Move to front of list, representing rear most object */
372 label->objects = g_list_remove (label->objects, object);
373 label->objects = g_list_prepend (label->objects, object);
375 label->priv->modified_flag = TRUE;
377 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
378 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
380 gl_debug (DEBUG_LABEL, "END");
384 /****************************************************************************/
386 /****************************************************************************/
388 gl_label_set_template (glLabel *label,
389 lglTemplate *template)
393 gl_debug (DEBUG_LABEL, "START");
395 g_return_if_fail (label && GL_IS_LABEL (label));
396 g_return_if_fail (template);
398 if ((label->template == NULL) ||
399 !lgl_template_do_templates_match (template, label->template)) {
401 lgl_template_free (label->template);
402 label->template = lgl_template_dup (template);
404 label->priv->modified_flag = TRUE;
406 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
407 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
408 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
410 name = lgl_template_get_name (template);
411 gl_prefs_add_recent_template (name);
415 gl_debug (DEBUG_LABEL, "END");
419 /****************************************************************************/
420 /* set rotate flag. */
421 /****************************************************************************/
423 gl_label_set_rotate_flag (glLabel *label,
424 gboolean rotate_flag)
426 gl_debug (DEBUG_LABEL, "START");
428 g_return_if_fail (label && GL_IS_LABEL (label));
430 if (rotate_flag != label->rotate_flag) {
432 label->rotate_flag = rotate_flag;
434 label->priv->modified_flag = TRUE;
436 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
437 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
438 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
442 gl_debug (DEBUG_LABEL, "END");
446 /****************************************************************************/
447 /* Get label size. */
448 /****************************************************************************/
450 gl_label_get_size (glLabel *label,
454 lglTemplate *template;
455 const lglTemplateFrame *frame;
457 gl_debug (DEBUG_LABEL, "START");
459 g_return_if_fail (label && GL_IS_LABEL (label));
461 template = label->template;
463 gl_debug (DEBUG_LABEL, "END -- template NULL");
467 frame = (lglTemplateFrame *)template->frames->data;
469 if (!label->rotate_flag) {
470 lgl_template_frame_get_size (frame, w, h);
472 lgl_template_frame_get_size (frame, h, w);
475 gl_debug (DEBUG_LABEL, "END");
479 /****************************************************************************/
480 /* set merge information structure. */
481 /****************************************************************************/
483 gl_label_set_merge (glLabel *label,
486 gl_debug (DEBUG_LABEL, "START");
488 g_return_if_fail (label && GL_IS_LABEL (label));
490 if ( label->priv->merge != NULL ) {
491 g_object_unref (G_OBJECT(label->priv->merge));
493 label->priv->merge = gl_merge_dup (merge);
495 label->priv->modified_flag = TRUE;
497 g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0);
498 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
499 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
501 gl_debug (DEBUG_LABEL, "END");
505 /****************************************************************************/
506 /* Get merge information structure. */
507 /****************************************************************************/
509 gl_label_get_merge (glLabel *label)
511 gl_debug (DEBUG_LABEL, "START");
513 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
515 gl_debug (DEBUG_LABEL, "END");
517 return gl_merge_dup (label->priv->merge);
521 /****************************************************************************/
522 /* return filename. */
523 /****************************************************************************/
525 gl_label_get_filename (glLabel *label)
527 gl_debug (DEBUG_LABEL, "");
529 return g_strdup ( label->priv->filename );
533 /****************************************************************************/
534 /* return short filename. */
535 /****************************************************************************/
537 gl_label_get_short_name (glLabel *label)
539 gl_debug (DEBUG_LABEL, "");
541 if ( label->priv->filename == NULL ) {
543 if ( label->priv->untitled_instance == 0 ) {
544 label->priv->untitled_instance = ++untitled;
547 return g_strdup_printf ( "%s %d", _("Untitled"),
548 label->priv->untitled_instance );
551 gchar *temp_name, *short_name;
553 temp_name = g_path_get_basename ( label->priv->filename );
554 short_name = gl_util_remove_extension (temp_name);
562 /****************************************************************************/
563 /* Get pixbuf cache. */
564 /****************************************************************************/
566 gl_label_get_pixbuf_cache (glLabel *label)
568 return label->priv->pixbuf_cache;
572 /****************************************************************************/
573 /* Is label modified? */
574 /****************************************************************************/
576 gl_label_is_modified (glLabel *label)
578 gl_debug (DEBUG_LABEL, "return %d", label->priv->modified_flag);
579 return label->priv->modified_flag;
583 /****************************************************************************/
584 /* Is label untitled? */
585 /****************************************************************************/
587 gl_label_is_untitled (glLabel *label)
589 gl_debug (DEBUG_LABEL, "return %d",(label->priv->filename == NULL));
590 return (label->priv->filename == NULL);
594 /****************************************************************************/
596 /****************************************************************************/
598 gl_label_can_undo (glLabel *label)
604 /****************************************************************************/
606 /****************************************************************************/
608 gl_label_can_redo (glLabel *label)
614 /****************************************************************************/
616 /****************************************************************************/
618 gl_label_set_filename (glLabel *label,
619 const gchar *filename)
621 label->priv->filename = g_strdup (filename);
623 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->priv->modified_flag ) {
636 label->priv->modified_flag = FALSE;
638 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
644 /****************************************************************************/
645 /* Set compression level. */
646 /****************************************************************************/
648 gl_label_set_compression (glLabel *label,
651 gl_debug (DEBUG_LABEL, "set %d", compression);
653 /* Older versions of libxml2 always return a -1 for documents "read in," so
654 * default to 9. Also, default to 9 for anything else out of range. */
655 if ((compression < 0) || (compression >9)) {
659 gl_debug (DEBUG_LABEL, "actual set %d", compression);
660 label->priv->compression = compression;
664 /****************************************************************************/
665 /* Get compression level. */
666 /****************************************************************************/
668 gl_label_get_compression (glLabel *label)
670 gl_debug (DEBUG_LABEL, "return %d", label->priv->compression);
671 return label->priv->compression;
675 /****************************************************************************/
677 /****************************************************************************/
679 gl_label_draw (glLabel *label,
681 gboolean screen_flag,
682 glMergeRecord *record)
685 glLabelObject *object;
687 g_return_if_fail (label && GL_IS_LABEL (label));
689 for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next)
691 object = GL_LABEL_OBJECT (p_obj->data);
693 gl_label_object_draw (object, cr, screen_flag, record);
701 * Local Variables: -- emacs
703 * c-basic-offset: 8 -- emacs
704 * tab-width: 8 -- emacs
705 * indent-tabs-mode: nil -- emacs