diff options
Diffstat (limited to 'glabels2/src/label.c')
-rw-r--r-- | glabels2/src/label.c | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/glabels2/src/label.c b/glabels2/src/label.c new file mode 100644 index 0000000..c886529 --- /dev/null +++ b/glabels2/src/label.c @@ -0,0 +1,674 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * (GLABELS) Label and Business Card Creation program for GNOME + * + * label.c: GLabels label module + * + * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +#include "label.h" + +#include <glib/gi18n.h> + +#include "marshal.h" +#include "prefs.h" +#include "util.h" + +#include "debug.h" + +/*========================================================*/ +/* Private macros and constants. */ +/*========================================================*/ + +/*========================================================*/ +/* Private types. */ +/*========================================================*/ + +struct _glLabelPrivate { + + gchar *filename; + gint compression; + gboolean modified_flag; + gint untitled_instance; + + glMerge *merge; + + GHashTable *pixbuf_cache; +}; + +enum { + CHANGED, + NAME_CHANGED, + MODIFIED_CHANGED, + MERGE_CHANGED, + SIZE_CHANGED, + OBJECT_ADDED, + LAST_SIGNAL +}; + +/*========================================================*/ +/* Private globals. */ +/*========================================================*/ + +static guint signals[LAST_SIGNAL] = {0}; + +static guint untitled = 0; + +/*========================================================*/ +/* Private function prototypes. */ +/*========================================================*/ + +static void gl_label_finalize (GObject *object); + +static void object_changed_cb (glLabelObject *object, + glLabel *label); + +static void object_moved_cb (glLabelObject *object, + gdouble x, + gdouble y, + glLabel *label); + + +/*****************************************************************************/ +/* Boilerplate object stuff. */ +/*****************************************************************************/ +G_DEFINE_TYPE (glLabel, gl_label, G_TYPE_OBJECT); + +static void +gl_label_class_init (glLabelClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + gl_debug (DEBUG_LABEL, "START"); + + gl_label_parent_class = g_type_class_peek_parent (class); + + object_class->finalize = gl_label_finalize; + + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[NAME_CHANGED] = + g_signal_new ("name_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, name_changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[MODIFIED_CHANGED] = + g_signal_new ("modified_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, modified_changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[MERGE_CHANGED] = + g_signal_new ("merge_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, merge_changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[SIZE_CHANGED] = + g_signal_new ("size_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, size_changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[OBJECT_ADDED] = + g_signal_new ("object_added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glLabelClass, object_added), + NULL, NULL, + gl_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, G_TYPE_OBJECT); + + gl_debug (DEBUG_LABEL, "END"); +} + +static void +gl_label_init (glLabel *label) +{ + gl_debug (DEBUG_LABEL, "START"); + + label->template = NULL; + label->rotate_flag = FALSE; + label->objects = NULL; + + label->priv = g_new0 (glLabelPrivate, 1); + + label->priv->filename = NULL; + label->priv->merge = NULL; + label->priv->pixbuf_cache = gl_pixbuf_cache_new (); + + gl_debug (DEBUG_LABEL, "END"); +} + +static void +gl_label_finalize (GObject *object) +{ + glLabel *label = GL_LABEL (object); + GList *p, *p_next; + + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (object && GL_IS_LABEL (object)); + + for (p = label->objects; p != NULL; p = p_next) { + p_next = p->next; /* NOTE: p will be left dangling */ + g_object_unref (G_OBJECT(p->data)); + } + + lgl_template_free (label->template); + g_free (label->priv->filename); + if (label->priv->merge != NULL) { + g_object_unref (G_OBJECT(label->priv->merge)); + } + gl_pixbuf_cache_free (label->priv->pixbuf_cache); + + g_free (label->priv); + + G_OBJECT_CLASS (gl_label_parent_class)->finalize (object); + + gl_debug (DEBUG_LABEL, "END"); +} + +GObject * +gl_label_new (void) +{ + glLabel *label; + + gl_debug (DEBUG_LABEL, "START"); + + label = g_object_new (gl_label_get_type(), NULL); + + label->priv->compression = 9; + + label->priv->modified_flag = FALSE; + + gl_debug (DEBUG_LABEL, "END"); + + return G_OBJECT (label); +} + + +/*****************************************************************************/ +/* Add object to label. */ +/*****************************************************************************/ +void +gl_label_add_object (glLabel *label, + glLabelObject *object) +{ + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + g_return_if_fail (object && GL_IS_LABEL_OBJECT (object)); + + object->parent = label; + label->objects = g_list_append (label->objects, g_object_ref (object)); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[OBJECT_ADDED], 0, object); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + + g_signal_connect (G_OBJECT(object), "changed", + G_CALLBACK(object_changed_cb), label); + + g_signal_connect (G_OBJECT(object), "moved", + G_CALLBACK(object_moved_cb), label); + + gl_debug (DEBUG_LABEL, "END"); +} + +/*****************************************************************************/ +/* Remove object from label. */ +/*****************************************************************************/ +void +gl_label_remove_object (glLabel *label, + glLabelObject *object) +{ + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + g_return_if_fail (GL_IS_LABEL_OBJECT (object)); + + object->parent = NULL; + label->objects = g_list_remove (label->objects, object); + + if ( G_OBJECT(label)->ref_count /* not finalized */ ) { + + g_signal_handlers_disconnect_by_func (object, + G_CALLBACK(object_changed_cb), + label); + g_signal_handlers_disconnect_by_func (object, + G_CALLBACK(object_moved_cb), + label); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + + } + + gl_debug (DEBUG_LABEL, "END"); +} + +/*---------------------------------------------------------------------------*/ +/* PRIVATE. Object changed callback. */ +/*---------------------------------------------------------------------------*/ +static void +object_changed_cb (glLabelObject *object, + glLabel *label) +{ + + if ( !label->priv->modified_flag ) { + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + } + + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); +} + +/*---------------------------------------------------------------------------*/ +/* PRIVATE. Object moved callback. */ +/*---------------------------------------------------------------------------*/ +static void +object_moved_cb (glLabelObject *object, + gdouble x, + gdouble y, + glLabel *label) +{ + + if ( !label->priv->modified_flag ) { + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + } + + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); +} + +/****************************************************************************/ +/* Bring label object to front/top. */ +/****************************************************************************/ +void +gl_label_raise_object_to_top (glLabel *label, + glLabelObject *object) +{ + gl_debug (DEBUG_LABEL, "START"); + + /* Move to end of list, representing front most object */ + label->objects = g_list_remove (label->objects, object); + label->objects = g_list_append (label->objects, object); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* Send label object to rear/bottom. */ +/****************************************************************************/ +void +gl_label_lower_object_to_bottom (glLabel *label, + glLabelObject *object) +{ + gl_debug (DEBUG_LABEL, "START"); + + /* Move to front of list, representing rear most object */ + label->objects = g_list_remove (label->objects, object); + label->objects = g_list_prepend (label->objects, object); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* set template. */ +/****************************************************************************/ +extern void +gl_label_set_template (glLabel *label, + lglTemplate *template) +{ + gchar *name; + + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + g_return_if_fail (template); + + if ((label->template == NULL) || + !lgl_template_do_templates_match (template, label->template)) { + + lgl_template_free (label->template); + label->template = lgl_template_dup (template); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + + name = lgl_template_get_name (template); + gl_prefs_add_recent_template (name); + g_free (name); + } + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* set rotate flag. */ +/****************************************************************************/ +extern void +gl_label_set_rotate_flag (glLabel *label, + gboolean rotate_flag) +{ + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + + if (rotate_flag != label->rotate_flag) { + + label->rotate_flag = rotate_flag; + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + + } + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* Get label size. */ +/****************************************************************************/ +void +gl_label_get_size (glLabel *label, + gdouble *w, + gdouble *h) +{ + lglTemplate *template; + const lglTemplateFrame *frame; + + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + + template = label->template; + if ( !template ) { + gl_debug (DEBUG_LABEL, "END -- template NULL"); + *w = *h = 0; + return; + } + frame = (lglTemplateFrame *)template->frames->data; + + if (!label->rotate_flag) { + lgl_template_frame_get_size (frame, w, h); + } else { + lgl_template_frame_get_size (frame, h, w); + } + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* set merge information structure. */ +/****************************************************************************/ +extern void +gl_label_set_merge (glLabel *label, + glMerge *merge) +{ + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (label && GL_IS_LABEL (label)); + + if ( label->priv->merge != NULL ) { + g_object_unref (G_OBJECT(label->priv->merge)); + } + label->priv->merge = gl_merge_dup (merge); + + label->priv->modified_flag = TRUE; + + g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + g_signal_emit (G_OBJECT(label), signals[CHANGED], 0); + + gl_debug (DEBUG_LABEL, "END"); +} + +/****************************************************************************/ +/* Get merge information structure. */ +/****************************************************************************/ +glMerge * +gl_label_get_merge (glLabel *label) +{ + gl_debug (DEBUG_LABEL, "START"); + + g_return_val_if_fail (label && GL_IS_LABEL (label), NULL); + + gl_debug (DEBUG_LABEL, "END"); + + return gl_merge_dup (label->priv->merge); +} + +/****************************************************************************/ +/* return filename. */ +/****************************************************************************/ +gchar * +gl_label_get_filename (glLabel *label) +{ + gl_debug (DEBUG_LABEL, ""); + + return g_strdup ( label->priv->filename ); +} + +/****************************************************************************/ +/* return short filename. */ +/****************************************************************************/ +gchar * +gl_label_get_short_name (glLabel *label) +{ + gl_debug (DEBUG_LABEL, ""); + + if ( label->priv->filename == NULL ) { + + if ( label->priv->untitled_instance == 0 ) { + label->priv->untitled_instance = ++untitled; + } + + return g_strdup_printf ( "%s %d", _("Untitled"), + label->priv->untitled_instance ); + + } else { + gchar *temp_name, *short_name; + + temp_name = g_path_get_basename ( label->priv->filename ); + short_name = gl_util_remove_extension (temp_name); + g_free (temp_name); + + return short_name; + } +} + +/****************************************************************************/ +/* Get pixbuf cache. */ +/****************************************************************************/ +GHashTable * +gl_label_get_pixbuf_cache (glLabel *label) +{ + return label->priv->pixbuf_cache; +} + +/****************************************************************************/ +/* Is label modified? */ +/****************************************************************************/ +gboolean +gl_label_is_modified (glLabel *label) +{ + gl_debug (DEBUG_LABEL, "return %d", label->priv->modified_flag); + return label->priv->modified_flag; +} + +/****************************************************************************/ +/* Is label untitled? */ +/****************************************************************************/ +gboolean +gl_label_is_untitled (glLabel *label) +{ + gl_debug (DEBUG_LABEL, "return %d",(label->priv->filename == NULL)); + return (label->priv->filename == NULL); +} + +/****************************************************************************/ +/* Can undo? */ +/****************************************************************************/ +gboolean +gl_label_can_undo (glLabel *label) +{ + return FALSE; +} + + +/****************************************************************************/ +/* Can redo? */ +/****************************************************************************/ +gboolean +gl_label_can_redo (glLabel *label) +{ + return FALSE; +} + + +/****************************************************************************/ +/* Set filename. */ +/****************************************************************************/ +void +gl_label_set_filename (glLabel *label, + const gchar *filename) +{ + label->priv->filename = g_strdup (filename); + + g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0); +} + +/****************************************************************************/ +/* Clear modified flag. */ +/****************************************************************************/ +void +gl_label_clear_modified (glLabel *label) +{ + + if ( label->priv->modified_flag ) { + + label->priv->modified_flag = FALSE; + + g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0); + } + +} + + +/****************************************************************************/ +/* Set compression level. */ +/****************************************************************************/ +void +gl_label_set_compression (glLabel *label, + gint compression) +{ + gl_debug (DEBUG_LABEL, "set %d", compression); + + /* Older versions of libxml2 always return a -1 for documents "read in," so + * default to 9. Also, default to 9 for anything else out of range. */ + if ((compression < 0) || (compression >9)) { + compression = 9; + } + + gl_debug (DEBUG_LABEL, "actual set %d", compression); + label->priv->compression = compression; +} + + +/****************************************************************************/ +/* Get compression level. */ +/****************************************************************************/ +gint +gl_label_get_compression (glLabel *label) +{ + gl_debug (DEBUG_LABEL, "return %d", label->priv->compression); + return label->priv->compression; +} + + +/****************************************************************************/ +/* Draw label. */ +/****************************************************************************/ +void +gl_label_draw (glLabel *label, + cairo_t *cr, + gboolean screen_flag, + glMergeRecord *record) +{ + GList *p_obj; + glLabelObject *object; + + g_return_if_fail (label && GL_IS_LABEL (label)); + + for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) + { + object = GL_LABEL_OBJECT (p_obj->data); + + gl_label_object_draw (object, cr, screen_flag, record); + } +} |