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>
28 #include "template-history.h"
29 #include "file-util.h"
30 #include "xml-label.h"
32 #include "label-text.h"
33 #include "label-image.h"
39 /*========================================================*/
40 /* Private macros and constants. */
41 /*========================================================*/
44 /*========================================================*/
46 /*========================================================*/
48 struct _glLabelPrivate {
52 gint untitled_instance;
54 gboolean modified_flag;
57 lglTemplate *template;
64 GHashTable *pixbuf_cache;
65 GHashTable *svg_cache;
67 /* Delay changed signals while operating on selections of multiple objects. */
68 gboolean selection_op_flag;
69 gboolean delayed_change_flag;
71 /* Default object text properties */
72 gchar *default_font_family;
73 gdouble default_font_size;
74 PangoWeight default_font_weight;
75 gboolean default_font_italic_flag;
76 guint default_text_color;
77 PangoAlignment default_text_alignment;
78 gdouble default_text_line_spacing;
80 /* Default object line properties */
81 gdouble default_line_width;
82 guint default_line_color;
84 /* Default object fill properties */
85 guint default_fill_color;
90 gboolean cp_cleared_flag;
113 gboolean modified_flag;
116 lglTemplate *template;
117 gboolean rotate_flag;
126 /*========================================================*/
127 /* Private globals. */
128 /*========================================================*/
130 static guint signals[LAST_SIGNAL] = {0};
132 static guint untitled = 0;
135 /*========================================================*/
136 /* Private function prototypes. */
137 /*========================================================*/
139 static void gl_label_finalize (GObject *object);
141 static void object_changed_cb (glLabelObject *object,
144 static void object_moved_cb (glLabelObject *object,
147 static void do_modify (glLabel *label);
149 static void begin_selection_op (glLabel *label);
150 static void end_selection_op (glLabel *label);
152 static void clipboard_get_cb (GtkClipboard *clipboard,
153 GtkSelectionData *selection_data,
155 ClipboardData *data);
157 static void clipboard_clear_cb (GtkClipboard *clipboard,
158 ClipboardData *data);
160 static void receive_targets_cb (GtkClipboard *clipboard,
165 static void paste_xml_received_cb (GtkClipboard *clipboard,
166 GtkSelectionData *selection_data,
169 static void paste_text_received_cb (GtkClipboard *clipboard,
173 static void paste_image_received_cb(GtkClipboard *clipboard,
177 static void stack_clear (GQueue *stack);
178 static void stack_push_state (GQueue *stack,
180 static State *stack_pop_state (GQueue *stack);
182 static State *state_new (glLabel *this,
183 const gchar *description);
184 static void state_free (State *state);
185 static void state_restore (State *state,
189 /*****************************************************************************/
190 /* Boilerplate object stuff. */
191 /*****************************************************************************/
192 G_DEFINE_TYPE (glLabel, gl_label, G_TYPE_OBJECT)
196 gl_label_class_init (glLabelClass *class)
198 GObjectClass *object_class = G_OBJECT_CLASS (class);
200 gl_debug (DEBUG_LABEL, "START");
202 gl_label_parent_class = g_type_class_peek_parent (class);
204 object_class->finalize = gl_label_finalize;
206 signals[SELECTION_CHANGED] =
207 g_signal_new ("selection_changed",
208 G_OBJECT_CLASS_TYPE (object_class),
210 G_STRUCT_OFFSET (glLabelClass, selection_changed),
212 gl_marshal_VOID__VOID,
216 g_signal_new ("changed",
217 G_OBJECT_CLASS_TYPE (object_class),
219 G_STRUCT_OFFSET (glLabelClass, changed),
221 gl_marshal_VOID__VOID,
224 signals[NAME_CHANGED] =
225 g_signal_new ("name_changed",
226 G_OBJECT_CLASS_TYPE (object_class),
228 G_STRUCT_OFFSET (glLabelClass, name_changed),
230 gl_marshal_VOID__VOID,
233 signals[MODIFIED_CHANGED] =
234 g_signal_new ("modified_changed",
235 G_OBJECT_CLASS_TYPE (object_class),
237 G_STRUCT_OFFSET (glLabelClass, modified_changed),
239 gl_marshal_VOID__VOID,
242 signals[MERGE_CHANGED] =
243 g_signal_new ("merge_changed",
244 G_OBJECT_CLASS_TYPE (object_class),
246 G_STRUCT_OFFSET (glLabelClass, merge_changed),
248 gl_marshal_VOID__VOID,
251 signals[SIZE_CHANGED] =
252 g_signal_new ("size_changed",
253 G_OBJECT_CLASS_TYPE (object_class),
255 G_STRUCT_OFFSET (glLabelClass, size_changed),
257 gl_marshal_VOID__VOID,
261 gl_debug (DEBUG_LABEL, "END");
266 gl_label_init (glLabel *label)
268 gl_debug (DEBUG_LABEL, "START");
270 label->priv = g_new0 (glLabelPrivate, 1);
272 label->priv->template = NULL;
273 label->priv->rotate_flag = FALSE;
274 label->priv->object_list = NULL;
276 label->priv->filename = NULL;
277 label->priv->modified_flag = FALSE;
278 label->priv->compression = 9;
280 label->priv->merge = NULL;
281 label->priv->pixbuf_cache = gl_pixbuf_cache_new ();
282 label->priv->svg_cache = gl_svg_cache_new ();
284 label->priv->undo_stack = g_queue_new ();
285 label->priv->redo_stack = g_queue_new ();
288 * Defaults from preferences
290 label->priv->default_font_family = gl_prefs_model_get_default_font_family (gl_prefs);
291 label->priv->default_font_size = gl_prefs_model_get_default_font_size (gl_prefs);
292 label->priv->default_font_weight = gl_prefs_model_get_default_font_weight (gl_prefs);
293 label->priv->default_font_italic_flag = gl_prefs_model_get_default_font_italic_flag (gl_prefs);
294 label->priv->default_text_color = gl_prefs_model_get_default_text_color (gl_prefs);
295 label->priv->default_text_alignment = gl_prefs_model_get_default_text_alignment (gl_prefs);
296 label->priv->default_text_line_spacing = gl_prefs_model_get_default_text_line_spacing (gl_prefs);
297 label->priv->default_line_width = gl_prefs_model_get_default_line_width (gl_prefs);
298 label->priv->default_line_color = gl_prefs_model_get_default_line_color (gl_prefs);
299 label->priv->default_fill_color = gl_prefs_model_get_default_fill_color (gl_prefs);
301 gl_debug (DEBUG_LABEL, "END");
306 gl_label_finalize (GObject *object)
308 glLabel *label = GL_LABEL (object);
311 gl_debug (DEBUG_LABEL, "START");
313 g_return_if_fail (object && GL_IS_LABEL (object));
315 for (p = label->priv->object_list; p != NULL; p = p->next)
317 g_object_unref (G_OBJECT(p->data));
319 g_list_free (label->priv->object_list);
321 lgl_template_free (label->priv->template);
322 g_free (label->priv->filename);
323 if (label->priv->merge != NULL)
325 g_object_unref (G_OBJECT(label->priv->merge));
327 g_free (label->priv->default_font_family);
329 stack_clear (label->priv->undo_stack);
330 stack_clear (label->priv->redo_stack);
332 g_queue_free (label->priv->undo_stack);
333 g_queue_free (label->priv->redo_stack);
335 gl_pixbuf_cache_free (label->priv->pixbuf_cache);
336 gl_svg_cache_free (label->priv->svg_cache);
338 g_free (label->priv);
340 G_OBJECT_CLASS (gl_label_parent_class)->finalize (object);
342 gl_debug (DEBUG_LABEL, "END");
346 /*****************************************************************************/
348 /*****************************************************************************/
354 gl_debug (DEBUG_LABEL, "START");
356 label = g_object_new (gl_label_get_type(), NULL);
358 gl_debug (DEBUG_LABEL, "END");
360 return G_OBJECT (label);
364 /****************************************************************************/
366 /****************************************************************************/
368 gl_label_set_filename (glLabel *label,
369 const gchar *filename)
371 label->priv->filename = g_strdup (filename);
373 g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
377 /****************************************************************************/
378 /* return filename. */
379 /****************************************************************************/
381 gl_label_get_filename (glLabel *label)
383 gl_debug (DEBUG_LABEL, "");
385 return g_strdup ( label->priv->filename );
389 /****************************************************************************/
390 /* return short filename. */
391 /****************************************************************************/
393 gl_label_get_short_name (glLabel *label)
395 gl_debug (DEBUG_LABEL, "");
397 if ( label->priv->filename == NULL )
400 if ( label->priv->untitled_instance == 0 )
402 label->priv->untitled_instance = ++untitled;
405 return g_strdup_printf ( "%s %d", _("Untitled"),
406 label->priv->untitled_instance );
411 gchar *temp_name, *short_name;
413 temp_name = g_path_get_basename ( label->priv->filename );
414 short_name = gl_file_util_remove_extension (temp_name);
422 /****************************************************************************/
423 /* Is label untitled? */
424 /****************************************************************************/
426 gl_label_is_untitled (glLabel *label)
428 gl_debug (DEBUG_LABEL, "return %d",(label->priv->filename == NULL));
429 return (label->priv->filename == NULL);
433 /****************************************************************************/
434 /* Set compression level. */
435 /****************************************************************************/
437 gl_label_set_compression (glLabel *label,
440 gl_debug (DEBUG_LABEL, "set %d", compression);
442 /* Older versions of libxml2 always return a -1 for documents "read in," so
443 * default to 9. Also, default to 9 for anything else out of range. */
444 if ((compression < 0) || (compression >9))
449 gl_debug (DEBUG_LABEL, "actual set %d", compression);
450 label->priv->compression = compression;
454 /****************************************************************************/
455 /* Get compression level. */
456 /****************************************************************************/
458 gl_label_get_compression (glLabel *label)
460 gl_debug (DEBUG_LABEL, "return %d", label->priv->compression);
461 return label->priv->compression;
465 /****************************************************************************/
466 /* Set modified flag. */
467 /****************************************************************************/
469 gl_label_set_modified (glLabel *label)
472 if ( !label->priv->modified_flag )
475 label->priv->modified_flag = TRUE;
477 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
483 /****************************************************************************/
484 /* Clear modified flag. */
485 /****************************************************************************/
487 gl_label_clear_modified (glLabel *label)
490 if ( label->priv->modified_flag )
493 g_get_current_time (&label->priv->time_stamp);
494 label->priv->modified_flag = FALSE;
496 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
502 /****************************************************************************/
503 /* Is label modified? */
504 /****************************************************************************/
506 gl_label_is_modified (glLabel *label)
508 gl_debug (DEBUG_LABEL, "return %d", label->priv->modified_flag);
509 return label->priv->modified_flag;
513 /****************************************************************************/
514 /* Object "changed" callback. */
515 /****************************************************************************/
517 object_changed_cb (glLabelObject *object,
524 /****************************************************************************/
525 /* Object "moved" callback. */
526 /****************************************************************************/
528 object_moved_cb (glLabelObject *object,
535 /****************************************************************************/
537 /****************************************************************************/
539 do_modify (glLabel *label)
541 if ( label->priv->selection_op_flag )
543 label->priv->delayed_change_flag = TRUE;
547 label->priv->modified_flag = TRUE;
549 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
550 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
555 /****************************************************************************/
556 /* Begin selection operation. */
557 /****************************************************************************/
559 begin_selection_op (glLabel *label)
561 label->priv->selection_op_flag = TRUE;
565 /****************************************************************************/
566 /* End selection operation. */
567 /****************************************************************************/
569 end_selection_op (glLabel *label)
571 label->priv->selection_op_flag = FALSE;
572 if ( label->priv->delayed_change_flag )
574 label->priv->delayed_change_flag = FALSE;
580 /****************************************************************************/
582 /****************************************************************************/
584 gl_label_set_template (glLabel *label,
585 const lglTemplate *template,
590 gl_debug (DEBUG_LABEL, "START");
592 g_return_if_fail (label && GL_IS_LABEL (label));
593 g_return_if_fail (template);
595 if ((label->priv->template == NULL) ||
596 !lgl_template_do_templates_match (template, label->priv->template))
601 gl_label_checkpoint (label, _("Label properties"));
604 lgl_template_free (label->priv->template);
605 label->priv->template = lgl_template_dup (template);
608 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
610 name = lgl_template_get_name (template);
611 gl_template_history_model_add_name (gl_template_history, name);
615 gl_debug (DEBUG_LABEL, "END");
619 /****************************************************************************/
621 /****************************************************************************/
623 gl_label_get_template (glLabel *label)
625 return label->priv->template;
629 /****************************************************************************/
630 /* set rotate flag. */
631 /****************************************************************************/
633 gl_label_set_rotate_flag (glLabel *label,
634 gboolean rotate_flag,
637 gl_debug (DEBUG_LABEL, "START");
639 g_return_if_fail (label && GL_IS_LABEL (label));
641 if (rotate_flag != label->priv->rotate_flag)
645 gl_label_checkpoint (label, _("Label properties"));
648 label->priv->rotate_flag = rotate_flag;
651 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
654 gl_debug (DEBUG_LABEL, "END");
658 /****************************************************************************/
659 /* Get rotate flag. */
660 /****************************************************************************/
662 gl_label_get_rotate_flag (glLabel *label)
664 return label->priv->rotate_flag;
668 /****************************************************************************/
669 /* Get label size. */
670 /****************************************************************************/
672 gl_label_get_size (glLabel *label,
676 lglTemplate *template;
677 const lglTemplateFrame *frame;
679 gl_debug (DEBUG_LABEL, "START");
681 g_return_if_fail (label && GL_IS_LABEL (label));
683 template = label->priv->template;
686 gl_debug (DEBUG_LABEL, "END -- template NULL");
690 frame = (lglTemplateFrame *)template->frames->data;
692 if (!label->priv->rotate_flag)
694 lgl_template_frame_get_size (frame, w, h);
698 lgl_template_frame_get_size (frame, h, w);
701 gl_debug (DEBUG_LABEL, "END");
705 /****************************************************************************/
706 /* set merge information structure. */
707 /****************************************************************************/
709 gl_label_set_merge (glLabel *label,
713 gl_debug (DEBUG_LABEL, "START");
715 g_return_if_fail (label && GL_IS_LABEL (label));
719 gl_label_checkpoint (label, _("Merge properties"));
722 if ( label->priv->merge != NULL )
724 g_object_unref (G_OBJECT(label->priv->merge));
726 label->priv->merge = gl_merge_dup (merge);
729 g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0);
731 gl_debug (DEBUG_LABEL, "END");
735 /****************************************************************************/
736 /* Get merge information structure. */
737 /****************************************************************************/
739 gl_label_get_merge (glLabel *label)
741 gl_debug (DEBUG_LABEL, "START");
743 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
745 gl_debug (DEBUG_LABEL, "END");
747 return gl_merge_dup (label->priv->merge);
751 /****************************************************************************/
752 /* Get pixbuf cache. */
753 /****************************************************************************/
755 gl_label_get_pixbuf_cache (glLabel *label)
757 return label->priv->pixbuf_cache;
761 /****************************************************************************/
763 /****************************************************************************/
765 gl_label_get_svg_cache (glLabel *label)
767 return label->priv->svg_cache;
771 /*****************************************************************************/
772 /* Add object to label. */
773 /*****************************************************************************/
775 gl_label_add_object (glLabel *label,
776 glLabelObject *object)
778 gl_debug (DEBUG_LABEL, "START");
780 g_return_if_fail (label && GL_IS_LABEL (label));
781 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
783 gl_label_object_set_parent (object, label);
784 label->priv->object_list = g_list_append (label->priv->object_list, object);
786 g_signal_connect (G_OBJECT (object), "changed",
787 G_CALLBACK (object_changed_cb), label);
788 g_signal_connect (G_OBJECT (object), "moved",
789 G_CALLBACK (object_moved_cb), label);
793 gl_debug (DEBUG_LABEL, "END");
797 /*****************************************************************************/
798 /* Delete object from label. */
799 /*****************************************************************************/
801 gl_label_delete_object (glLabel *label,
802 glLabelObject *object)
804 gl_debug (DEBUG_LABEL, "START");
806 g_return_if_fail (label && GL_IS_LABEL (label));
807 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
809 label->priv->object_list = g_list_remove (label->priv->object_list, object);
811 g_signal_handlers_disconnect_by_func (G_OBJECT (object),
812 G_CALLBACK (object_changed_cb), label);
813 g_signal_handlers_disconnect_by_func (G_OBJECT (object),
814 G_CALLBACK (object_moved_cb), label);
815 g_object_unref (object);
819 gl_debug (DEBUG_LABEL, "END");
823 /*****************************************************************************/
824 /* Get object list. */
825 /*****************************************************************************/
827 gl_label_get_object_list (glLabel *label)
829 return label->priv->object_list;
833 /*****************************************************************************/
835 /*****************************************************************************/
837 gl_label_select_object (glLabel *label,
838 glLabelObject *object)
840 gl_debug (DEBUG_LABEL, "START");
842 g_return_if_fail (label && GL_IS_LABEL (label));
843 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
845 gl_label_object_select (object);
847 label->priv->cp_cleared_flag = TRUE;
848 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
850 gl_debug (DEBUG_LABEL, "END");
854 /*****************************************************************************/
855 /* Unselect object. */
856 /*****************************************************************************/
858 gl_label_unselect_object (glLabel *label,
859 glLabelObject *object)
861 gl_debug (DEBUG_LABEL, "START");
863 g_return_if_fail (label && GL_IS_LABEL (label));
864 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
866 gl_label_object_unselect (object);
868 label->priv->cp_cleared_flag = TRUE;
869 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
871 gl_debug (DEBUG_LABEL, "END");
875 /*****************************************************************************/
876 /* Select all objects. */
877 /*****************************************************************************/
879 gl_label_select_all (glLabel *label)
882 glLabelObject *object;
884 gl_debug (DEBUG_LABEL, "START");
886 g_return_if_fail (label && GL_IS_LABEL (label));
888 for ( p = label->priv->object_list; p != NULL; p = p->next )
890 object = GL_LABEL_OBJECT (p->data);
892 gl_label_object_select (object);
895 label->priv->cp_cleared_flag = TRUE;
896 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
898 gl_debug (DEBUG_LABEL, "END");
902 /*****************************************************************************/
903 /* Unselect all objects. */
904 /*****************************************************************************/
906 gl_label_unselect_all (glLabel *label)
909 glLabelObject *object;
911 gl_debug (DEBUG_LABEL, "START");
913 g_return_if_fail (label && GL_IS_LABEL (label));
915 for ( p = label->priv->object_list; p != NULL; p = p->next )
917 object = GL_LABEL_OBJECT (p->data);
919 gl_label_object_unselect (object);
922 label->priv->cp_cleared_flag = TRUE;
923 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
925 gl_debug (DEBUG_LABEL, "END");
929 /*****************************************************************************/
930 /* Select all objects contained in region. */
931 /*****************************************************************************/
933 gl_label_select_region (glLabel *label,
934 glLabelRegion *region)
937 glLabelObject *object;
940 glLabelRegion obj_extent;
942 gl_debug (DEBUG_LABEL, "START");
944 g_return_if_fail (label && GL_IS_LABEL (label));
946 r_x1 = MIN (region->x1, region->x2);
947 r_y1 = MIN (region->y1, region->y2);
948 r_x2 = MAX (region->x1, region->x2);
949 r_y2 = MAX (region->y1, region->y2);
951 for (p = label->priv->object_list; p != NULL; p = p->next)
953 object = GL_LABEL_OBJECT(p->data);
955 gl_label_object_get_extent (object, &obj_extent);
956 if ((obj_extent.x1 >= r_x1) &&
957 (obj_extent.x2 <= r_x2) &&
958 (obj_extent.y1 >= r_y1) &&
959 (obj_extent.y2 <= r_y2))
961 gl_label_object_select (object);
965 label->priv->cp_cleared_flag = TRUE;
966 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
968 gl_debug (DEBUG_LABEL, "END");
972 /*****************************************************************************/
973 /* Is selection empty? */
974 /*****************************************************************************/
976 gl_label_is_selection_empty (glLabel *label)
979 glLabelObject *object;
981 for ( p = label->priv->object_list; p != NULL; p = p->next )
983 object = GL_LABEL_OBJECT (p->data);
985 if ( gl_label_object_is_selected (object) )
995 /*****************************************************************************/
996 /* Is selection atomic? */
997 /*****************************************************************************/
999 gl_label_is_selection_atomic (glLabel *label)
1002 glLabelObject *object;
1003 gint n_selected = 0;
1005 for ( p = label->priv->object_list; p != NULL; p = p->next )
1007 object = GL_LABEL_OBJECT (p->data);
1009 if ( gl_label_object_is_selected (object) )
1020 return (n_selected == 1);
1024 /*****************************************************************************/
1025 /* Get first selected object. */
1026 /*****************************************************************************/
1028 gl_label_get_1st_selected_object (glLabel *label)
1031 glLabelObject *object;
1033 for ( p = label->priv->object_list; p != NULL; p = p->next )
1035 object = GL_LABEL_OBJECT (p->data);
1037 if ( gl_label_object_is_selected (object) )
1047 /*****************************************************************************/
1048 /* Get list of selected objects. */
1049 /*****************************************************************************/
1051 gl_label_get_selection_list (glLabel *label)
1053 GList *selection_list = NULL;
1055 glLabelObject *object;
1057 for ( p = label->priv->object_list; p != NULL; p = p->next )
1059 object = GL_LABEL_OBJECT (p->data);
1061 if ( gl_label_object_is_selected (object) )
1063 selection_list = g_list_append (selection_list, object);
1067 return (selection_list);
1071 /*****************************************************************************/
1072 /* Can text properties be set for selection? */
1073 /*****************************************************************************/
1075 gl_label_can_selection_text (glLabel *label)
1077 GList *selection_list;
1079 glLabelObject *object;
1081 gl_debug (DEBUG_LABEL, "");
1083 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1085 selection_list = gl_label_get_selection_list (label);
1087 for (p = selection_list; p != NULL; p = p->next)
1089 object = GL_LABEL_OBJECT (p->data);
1091 if (gl_label_object_can_text (object))
1093 g_list_free (selection_list);
1098 g_list_free (selection_list);
1103 /*****************************************************************************/
1104 /* Can fill properties be set for selection? */
1105 /*****************************************************************************/
1107 gl_label_can_selection_fill (glLabel *label)
1109 GList *selection_list;
1111 glLabelObject *object;
1113 gl_debug (DEBUG_LABEL, "");
1115 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1117 selection_list = gl_label_get_selection_list (label);
1119 for (p = selection_list; p != NULL; p = p->next)
1121 object = GL_LABEL_OBJECT (p->data);
1123 if (gl_label_object_can_fill (object))
1125 g_list_free (selection_list);
1131 g_list_free (selection_list);
1136 /*****************************************************************************/
1137 /* Can line color properties be set for selection? */
1138 /*****************************************************************************/
1140 gl_label_can_selection_line_color (glLabel *label)
1142 GList *selection_list;
1144 glLabelObject *object;
1146 gl_debug (DEBUG_LABEL, "");
1148 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1150 selection_list = gl_label_get_selection_list (label);
1152 for (p = selection_list; p != NULL; p = p->next)
1154 object = GL_LABEL_OBJECT (p->data);
1156 if (gl_label_object_can_line_color (object))
1158 g_list_free (selection_list);
1163 g_list_free (selection_list);
1168 /*****************************************************************************/
1169 /* Can line width properties be set for selection? */
1170 /*****************************************************************************/
1172 gl_label_can_selection_line_width (glLabel *label)
1174 GList *selection_list;
1176 glLabelObject *object;
1178 gl_debug (DEBUG_LABEL, "");
1180 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1182 selection_list = gl_label_get_selection_list (label);
1184 for (p = selection_list; p != NULL; p = p->next)
1186 object = GL_LABEL_OBJECT (p->data);
1188 if (gl_label_object_can_line_width (object))
1190 g_list_free (selection_list);
1196 g_list_free (selection_list);
1201 /*****************************************************************************/
1202 /* Delete selection from label. */
1203 /*****************************************************************************/
1205 gl_label_delete_selection (glLabel *label)
1207 GList *selection_list;
1209 glLabelObject *object;
1211 gl_debug (DEBUG_LABEL, "START");
1213 g_return_if_fail (label && GL_IS_LABEL (label));
1215 gl_label_checkpoint (label, _("Delete"));
1217 begin_selection_op (label);
1219 selection_list = gl_label_get_selection_list (label);
1221 for ( p = selection_list; p != NULL; p = p->next )
1223 object = GL_LABEL_OBJECT (p->data);
1225 gl_label_delete_object (label, object);
1228 g_list_free (selection_list);
1230 end_selection_op (label);
1232 gl_debug (DEBUG_LABEL, "END");
1236 /****************************************************************************/
1237 /* Bring selection object to front/top. */
1238 /****************************************************************************/
1240 gl_label_raise_selection_to_top (glLabel *label)
1242 GList *selection_list;
1244 glLabelObject *object;
1246 gl_debug (DEBUG_LABEL, "START");
1248 gl_label_checkpoint (label, _("Bring to front"));
1250 begin_selection_op (label);
1252 selection_list = gl_label_get_selection_list (label);
1254 for ( p = selection_list; p != NULL; p = p->next )
1256 object = GL_LABEL_OBJECT (p->data);
1258 label->priv->object_list = g_list_remove (label->priv->object_list, object);
1261 /* Move to end of list, representing front most object */
1262 label->priv->object_list = g_list_concat (label->priv->object_list, selection_list);
1266 end_selection_op (label);
1268 gl_debug (DEBUG_LABEL, "END");
1272 /****************************************************************************/
1273 /* Send selection to rear/bottom. */
1274 /****************************************************************************/
1276 gl_label_lower_selection_to_bottom (glLabel *label)
1278 GList *selection_list;
1280 glLabelObject *object;
1282 gl_debug (DEBUG_LABEL, "START");
1284 gl_label_checkpoint (label, _("Send to back"));
1286 begin_selection_op (label);
1288 selection_list = gl_label_get_selection_list (label);
1290 for ( p = selection_list; p != NULL; p = p->next )
1292 object = GL_LABEL_OBJECT (p->data);
1294 label->priv->object_list = g_list_remove (label->priv->object_list, object);
1297 /* Move to front of list, representing rear most object */
1298 label->priv->object_list = g_list_concat (selection_list, label->priv->object_list);
1302 end_selection_op (label);
1304 gl_debug (DEBUG_LABEL, "END");
1308 /*****************************************************************************/
1309 /* Rotate selected objects by given angle. */
1310 /*****************************************************************************/
1312 gl_label_rotate_selection (glLabel *label,
1315 GList *selection_list;
1317 glLabelObject *object;
1319 gl_debug (DEBUG_LABEL, "START");
1321 g_return_if_fail (label && GL_IS_LABEL (label));
1323 begin_selection_op (label);
1325 gl_label_checkpoint (label, _("Rotate"));
1327 selection_list = gl_label_get_selection_list (label);
1329 for ( p = selection_list; p != NULL; p = p->next )
1331 object = GL_LABEL_OBJECT (p->data);
1333 gl_label_object_rotate (object, theta_degs);
1336 g_list_free (selection_list);
1338 end_selection_op (label);
1340 gl_debug (DEBUG_LABEL, "END");
1344 /*****************************************************************************/
1345 /* Rotate selected objects 90 degrees left. */
1346 /*****************************************************************************/
1348 gl_label_rotate_selection_left (glLabel *label)
1350 GList *selection_list;
1352 glLabelObject *object;
1354 gl_debug (DEBUG_LABEL, "START");
1356 g_return_if_fail (label && GL_IS_LABEL (label));
1358 begin_selection_op (label);
1360 gl_label_checkpoint (label, _("Rotate left"));
1362 selection_list = gl_label_get_selection_list (label);
1364 for ( p = selection_list; p != NULL; p = p->next )
1366 object = GL_LABEL_OBJECT (p->data);
1368 gl_label_object_rotate (object, -90.0);
1371 g_list_free (selection_list);
1373 end_selection_op (label);
1375 gl_debug (DEBUG_LABEL, "END");
1379 /*****************************************************************************/
1380 /* Rotate selected objects 90 degrees right. */
1381 /*****************************************************************************/
1383 gl_label_rotate_selection_right (glLabel *label)
1385 GList *selection_list;
1387 glLabelObject *object;
1389 gl_debug (DEBUG_LABEL, "START");
1391 g_return_if_fail (label && GL_IS_LABEL (label));
1393 gl_label_checkpoint (label, _("Rotate right"));
1395 begin_selection_op (label);
1397 selection_list = gl_label_get_selection_list (label);
1399 for ( p = selection_list; p != NULL; p = p->next )
1401 object = GL_LABEL_OBJECT (p->data);
1403 gl_label_object_rotate (object, 90.0);
1406 g_list_free (selection_list);
1408 end_selection_op (label);
1410 gl_debug (DEBUG_LABEL, "END");
1414 /*****************************************************************************/
1415 /* Flip selected objects horizontally. */
1416 /*****************************************************************************/
1418 gl_label_flip_selection_horiz (glLabel *label)
1420 GList *selection_list;
1422 glLabelObject *object;
1424 gl_debug (DEBUG_LABEL, "START");
1426 g_return_if_fail (label && GL_IS_LABEL (label));
1428 gl_label_checkpoint (label, _("Flip horizontally"));
1430 begin_selection_op (label);
1432 selection_list = gl_label_get_selection_list (label);
1434 for ( p = selection_list; p != NULL; p = p->next )
1436 object = GL_LABEL_OBJECT (p->data);
1438 gl_label_object_flip_horiz (object);
1441 g_list_free (selection_list);
1443 end_selection_op (label);
1445 gl_debug (DEBUG_LABEL, "END");
1449 /*****************************************************************************/
1450 /* Flip selected objects vertically. */
1451 /*****************************************************************************/
1453 gl_label_flip_selection_vert (glLabel *label)
1455 GList *selection_list;
1457 glLabelObject *object;
1459 gl_debug (DEBUG_LABEL, "START");
1461 g_return_if_fail (label && GL_IS_LABEL (label));
1463 gl_label_checkpoint (label, _("Flip vertically"));
1465 begin_selection_op (label);
1467 selection_list = gl_label_get_selection_list (label);
1469 for ( p = selection_list; p != NULL; p = p->next )
1471 object = GL_LABEL_OBJECT (p->data);
1473 gl_label_object_flip_vert (object);
1476 g_list_free (selection_list);
1478 end_selection_op (label);
1480 gl_debug (DEBUG_LABEL, "END");
1484 /*****************************************************************************/
1485 /* Align selected objects to left most edge. */
1486 /*****************************************************************************/
1488 gl_label_align_selection_left (glLabel *label)
1490 GList *selection_list;
1492 glLabelObject *object;
1494 glLabelRegion obj_extent;
1496 gl_debug (DEBUG_LABEL, "START");
1498 g_return_if_fail (label && GL_IS_LABEL (label));
1500 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1501 !gl_label_is_selection_atomic (label));
1503 gl_label_checkpoint (label, _("Align left"));
1505 begin_selection_op (label);
1507 selection_list = gl_label_get_selection_list (label);
1509 /* find left most edge */
1511 object = GL_LABEL_OBJECT (p->data);
1513 gl_label_object_get_extent (object, &obj_extent);
1514 x1_min = obj_extent.x1;
1515 for (p = p->next; p != NULL; p = p->next)
1517 object = GL_LABEL_OBJECT (p->data);
1519 gl_label_object_get_extent (object, &obj_extent);
1520 if ( obj_extent.x1 < x1_min ) x1_min = obj_extent.x1;
1523 /* now adjust the object positions to line up the left edges */
1524 for (p = selection_list; p != NULL; p = p->next)
1526 object = GL_LABEL_OBJECT (p->data);
1528 gl_label_object_get_extent (object, &obj_extent);
1529 dx = x1_min - obj_extent.x1;
1530 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1533 g_list_free (selection_list);
1535 end_selection_op (label);
1537 gl_debug (DEBUG_LABEL, "END");
1541 /*****************************************************************************/
1542 /* Align selected objects to right most edge. */
1543 /*****************************************************************************/
1545 gl_label_align_selection_right (glLabel *label)
1547 GList *selection_list;
1549 glLabelObject *object;
1551 glLabelRegion obj_extent;
1553 gl_debug (DEBUG_LABEL, "START");
1555 g_return_if_fail (label && GL_IS_LABEL (label));
1557 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1558 !gl_label_is_selection_atomic (label));
1560 gl_label_checkpoint (label, _("Align right"));
1562 begin_selection_op (label);
1564 selection_list = gl_label_get_selection_list (label);
1566 /* find left most edge */
1568 object = GL_LABEL_OBJECT (p->data);
1570 gl_label_object_get_extent (object, &obj_extent);
1571 x2_max = obj_extent.x2;
1572 for (p = p->next; p != NULL; p = p->next)
1574 object = GL_LABEL_OBJECT (p->data);
1576 gl_label_object_get_extent (object, &obj_extent);
1577 if ( obj_extent.x2 > x2_max ) x2_max = obj_extent.x2;
1580 /* now adjust the object positions to line up the left edges */
1581 for (p = selection_list; p != NULL; p = p->next)
1583 object = GL_LABEL_OBJECT (p->data);
1585 gl_label_object_get_extent (object, &obj_extent);
1586 dx = x2_max - obj_extent.x2;
1587 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1590 g_list_free (selection_list);
1592 end_selection_op (label);
1594 gl_debug (DEBUG_LABEL, "END");
1598 /*****************************************************************************/
1599 /* Align selected objects to horizontal center of objects. */
1600 /*****************************************************************************/
1602 gl_label_align_selection_hcenter (glLabel *label)
1604 GList *selection_list;
1606 glLabelObject *object;
1610 glLabelRegion obj_extent;
1614 gl_debug (DEBUG_LABEL, "START");
1616 g_return_if_fail (label && GL_IS_LABEL (label));
1618 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1619 !gl_label_is_selection_atomic (label));
1621 gl_label_checkpoint (label, _("Align horizontal center"));
1623 begin_selection_op (label);
1625 selection_list = gl_label_get_selection_list (label);
1627 /* find average center of objects */
1630 for (p = selection_list; p != NULL; p = p->next)
1632 object = GL_LABEL_OBJECT (p->data);
1634 gl_label_object_get_extent (object, &obj_extent);
1635 xsum += (obj_extent.x1 + obj_extent.x2) / 2.0;
1640 /* find center of object closest to average center */
1642 object = GL_LABEL_OBJECT (p->data);
1644 gl_label_object_get_extent (object, &obj_extent);
1645 dxmin = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1646 xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1647 for (p = p->next; p != NULL; p = p->next)
1649 object = GL_LABEL_OBJECT (p->data);
1651 gl_label_object_get_extent (object, &obj_extent);
1652 dx = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1656 xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1660 /* now adjust the object positions to line up this center */
1661 for (p = selection_list; p != NULL; p = p->next)
1663 object = GL_LABEL_OBJECT (p->data);
1665 gl_label_object_get_extent (object, &obj_extent);
1666 dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
1667 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1670 g_list_free (selection_list);
1672 end_selection_op (label);
1674 gl_debug (DEBUG_LABEL, "END");
1678 /*****************************************************************************/
1679 /* Align selected objects to top most edge. */
1680 /*****************************************************************************/
1682 gl_label_align_selection_top (glLabel *label)
1684 GList *selection_list;
1686 glLabelObject *object;
1688 glLabelRegion obj_extent;
1690 gl_debug (DEBUG_LABEL, "START");
1692 g_return_if_fail (label && GL_IS_LABEL (label));
1694 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1695 !gl_label_is_selection_atomic (label));
1697 gl_label_checkpoint (label, _("Align tops"));
1699 begin_selection_op (label);
1701 selection_list = gl_label_get_selection_list (label);
1703 /* find top most edge */
1705 object = GL_LABEL_OBJECT (p->data);
1707 gl_label_object_get_extent (object, &obj_extent);
1708 y1_min = obj_extent.y1;
1709 for (p = p->next; p != NULL; p = p->next)
1711 object = GL_LABEL_OBJECT (p->data);
1713 gl_label_object_get_extent (object, &obj_extent);
1714 if ( obj_extent.y1 < y1_min ) y1_min = obj_extent.y1;
1717 /* now adjust the object positions to line up the top edges */
1718 for (p = selection_list; p != NULL; p = p->next)
1720 object = GL_LABEL_OBJECT (p->data);
1722 gl_label_object_get_extent (object, &obj_extent);
1723 dy = y1_min - obj_extent.y1;
1724 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1727 g_list_free (selection_list);
1729 end_selection_op (label);
1731 gl_debug (DEBUG_LABEL, "END");
1735 /*****************************************************************************/
1736 /* Align selected objects to bottom most edge. */
1737 /*****************************************************************************/
1739 gl_label_align_selection_bottom (glLabel *label)
1741 GList *selection_list;
1743 glLabelObject *object;
1745 glLabelRegion obj_extent;
1747 gl_debug (DEBUG_LABEL, "START");
1749 g_return_if_fail (label && GL_IS_LABEL (label));
1751 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1752 !gl_label_is_selection_atomic (label));
1754 gl_label_checkpoint (label, _("Align bottoms"));
1756 begin_selection_op (label);
1758 selection_list = gl_label_get_selection_list (label);
1760 /* find bottom most edge */
1762 object = GL_LABEL_OBJECT (p->data);
1764 gl_label_object_get_extent (object, &obj_extent);
1765 y2_max = obj_extent.y2;
1766 for (p = p->next; p != NULL; p = p->next)
1768 object = GL_LABEL_OBJECT (p->data);
1770 gl_label_object_get_extent (object, &obj_extent);
1771 if ( obj_extent.y2 > y2_max ) y2_max = obj_extent.y2;
1774 /* now adjust the object positions to line up the bottom edges */
1775 for (p = selection_list; p != NULL; p = p->next)
1777 object = GL_LABEL_OBJECT (p->data);
1779 gl_label_object_get_extent (object, &obj_extent);
1780 dy = y2_max - obj_extent.y2;
1781 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1784 g_list_free (selection_list);
1786 end_selection_op (label);
1788 gl_debug (DEBUG_LABEL, "END");
1792 /*****************************************************************************/
1793 /* Align selected objects to viertical center of objects. */
1794 /*****************************************************************************/
1796 gl_label_align_selection_vcenter (glLabel *label)
1798 GList *selection_list;
1800 glLabelObject *object;
1804 glLabelRegion obj_extent;
1808 gl_debug (DEBUG_LABEL, "START");
1810 g_return_if_fail (label && GL_IS_LABEL (label));
1812 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1813 !gl_label_is_selection_atomic (label));
1815 gl_label_checkpoint (label, _("Align vertical center"));
1817 begin_selection_op (label);
1819 selection_list = gl_label_get_selection_list (label);
1821 /* find average center of objects */
1824 for (p = selection_list; p != NULL; p = p->next)
1826 object = GL_LABEL_OBJECT (p->data);
1828 gl_label_object_get_extent (object, &obj_extent);
1829 ysum += (obj_extent.y1 + obj_extent.y2) / 2.0;
1834 /* find center of object closest to average center */
1836 object = GL_LABEL_OBJECT (p->data);
1838 gl_label_object_get_extent (object, &obj_extent);
1839 dymin = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1840 ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1841 for (p = p->next; p != NULL; p = p->next)
1843 object = GL_LABEL_OBJECT (p->data);
1845 gl_label_object_get_extent (object, &obj_extent);
1846 dy = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1850 ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1854 /* now adjust the object positions to line up this center */
1855 for (p = selection_list; p != NULL; p = p->next)
1857 object = GL_LABEL_OBJECT (p->data);
1859 gl_label_object_get_extent (object, &obj_extent);
1860 dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
1861 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1864 g_list_free (selection_list);
1866 end_selection_op (label);
1868 gl_debug (DEBUG_LABEL, "END");
1872 /*****************************************************************************/
1873 /* Center selected objects to in center of label. */
1874 /*****************************************************************************/
1876 gl_label_center_selection_horiz (glLabel *label)
1878 GList *selection_list;
1880 glLabelObject *object;
1882 gdouble x_label_center;
1883 gdouble x_obj_center;
1884 glLabelRegion obj_extent;
1887 gl_debug (DEBUG_LABEL, "START");
1889 g_return_if_fail (label && GL_IS_LABEL (label));
1891 g_return_if_fail (!gl_label_is_selection_empty (label));
1893 gl_label_checkpoint (label, _("Center horizontally"));
1895 begin_selection_op (label);
1897 gl_label_get_size (label, &w, &h);
1898 x_label_center = w / 2.0;
1900 /* adjust the object positions */
1901 selection_list = gl_label_get_selection_list (label);
1902 for (p = selection_list; p != NULL; p = p->next)
1904 object = GL_LABEL_OBJECT (p->data);
1906 gl_label_object_get_extent (object, &obj_extent);
1907 x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
1908 dx = x_label_center - x_obj_center;
1909 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1911 g_list_free (selection_list);
1913 end_selection_op (label);
1915 gl_debug (DEBUG_LABEL, "END");
1919 /*****************************************************************************/
1920 /* Center selected objects to in center of label. */
1921 /*****************************************************************************/
1923 gl_label_center_selection_vert (glLabel *label)
1925 GList *selection_list;
1927 glLabelObject *object;
1929 gdouble y_label_center;
1930 gdouble y_obj_center;
1931 glLabelRegion obj_extent;
1934 gl_debug (DEBUG_LABEL, "START");
1936 g_return_if_fail (label && GL_IS_LABEL (label));
1938 g_return_if_fail (!gl_label_is_selection_empty (label));
1940 gl_label_checkpoint (label, _("Center vertically"));
1942 begin_selection_op (label);
1944 gl_label_get_size (label, &w, &h);
1945 y_label_center = h / 2.0;
1947 /* adjust the object positions */
1948 selection_list = gl_label_get_selection_list (label);
1949 for (p = selection_list; p != NULL; p = p->next)
1951 object = GL_LABEL_OBJECT (p->data);
1953 gl_label_object_get_extent (object, &obj_extent);
1954 y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
1955 dy = y_label_center - y_obj_center;
1956 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1958 g_list_free (selection_list);
1960 end_selection_op (label);
1962 gl_debug (DEBUG_LABEL, "END");
1966 /*****************************************************************************/
1967 /* Move selected objects */
1968 /*****************************************************************************/
1970 gl_label_move_selection (glLabel *label,
1974 GList *selection_list;
1976 glLabelObject *object;
1978 gl_debug (DEBUG_LABEL, "START");
1980 g_return_if_fail (label && GL_IS_LABEL (label));
1982 begin_selection_op (label);
1984 selection_list = gl_label_get_selection_list (label);
1986 for (p = selection_list; p != NULL; p = p->next)
1988 object = GL_LABEL_OBJECT (p->data);
1990 gl_label_object_set_position_relative (object, dx, dy, TRUE);
1993 g_list_free (selection_list);
1995 end_selection_op (label);
1997 gl_debug (DEBUG_LABEL, "END");
2001 /*****************************************************************************/
2002 /* Set font family for all text contained in selected objects. */
2003 /*****************************************************************************/
2005 gl_label_set_selection_font_family (glLabel *label,
2006 const gchar *font_family)
2008 GList *selection_list;
2010 glLabelObject *object;
2012 gl_debug (DEBUG_LABEL, "START");
2014 g_return_if_fail (label && GL_IS_LABEL (label));
2016 begin_selection_op (label);
2018 selection_list = gl_label_get_selection_list (label);
2020 for (p = selection_list; p != NULL; p = p->next)
2022 object = GL_LABEL_OBJECT (p->data);
2023 gl_label_object_set_font_family (object, font_family, TRUE);
2026 g_list_free (selection_list);
2028 end_selection_op (label);
2030 gl_debug (DEBUG_LABEL, "END");
2034 /*****************************************************************************/
2035 /* Set font size for all text contained in selected objects. */
2036 /*****************************************************************************/
2038 gl_label_set_selection_font_size (glLabel *label,
2041 GList *selection_list;
2043 glLabelObject *object;
2045 gl_debug (DEBUG_LABEL, "START");
2047 g_return_if_fail (label && GL_IS_LABEL (label));
2049 begin_selection_op (label);
2051 selection_list = gl_label_get_selection_list (label);
2053 for (p = selection_list; p != NULL; p = p->next)
2055 object = GL_LABEL_OBJECT (p->data);
2056 gl_label_object_set_font_size (object, font_size, TRUE);
2059 g_list_free (selection_list);
2061 end_selection_op (label);
2063 gl_debug (DEBUG_LABEL, "END");
2067 /*****************************************************************************/
2068 /* Set font weight for all text contained in selected objects. */
2069 /*****************************************************************************/
2071 gl_label_set_selection_font_weight (glLabel *label,
2072 PangoWeight font_weight)
2074 GList *selection_list;
2076 glLabelObject *object;
2078 gl_debug (DEBUG_LABEL, "START");
2080 g_return_if_fail (label && GL_IS_LABEL (label));
2082 begin_selection_op (label);
2084 selection_list = gl_label_get_selection_list (label);
2086 for (p = selection_list; p != NULL; p = p->next)
2088 object = GL_LABEL_OBJECT (p->data);
2089 gl_label_object_set_font_weight (object, font_weight, TRUE);
2092 g_list_free (selection_list);
2094 end_selection_op (label);
2096 gl_debug (DEBUG_LABEL, "END");
2100 /*****************************************************************************/
2101 /* Set font italic flag for all text contained in selected objects. */
2102 /*****************************************************************************/
2104 gl_label_set_selection_font_italic_flag (glLabel *label,
2105 gboolean font_italic_flag)
2107 GList *selection_list;
2109 glLabelObject *object;
2111 gl_debug (DEBUG_LABEL, "START");
2113 g_return_if_fail (label && GL_IS_LABEL (label));
2115 begin_selection_op (label);
2117 selection_list = gl_label_get_selection_list (label);
2119 for (p = selection_list; p != NULL; p = p->next)
2121 object = GL_LABEL_OBJECT (p->data);
2122 gl_label_object_set_font_italic_flag (object, font_italic_flag, TRUE);
2125 g_list_free (selection_list);
2127 end_selection_op (label);
2129 gl_debug (DEBUG_LABEL, "END");
2133 /*****************************************************************************/
2134 /* Set text alignment for all text contained in selected objects. */
2135 /*****************************************************************************/
2137 gl_label_set_selection_text_alignment (glLabel *label,
2138 PangoAlignment text_alignment)
2140 GList *selection_list;
2142 glLabelObject *object;
2144 gl_debug (DEBUG_LABEL, "START");
2146 g_return_if_fail (label && GL_IS_LABEL (label));
2148 begin_selection_op (label);
2150 selection_list = gl_label_get_selection_list (label);
2152 for (p = selection_list; p != NULL; p = p->next)
2154 object = GL_LABEL_OBJECT (p->data);
2155 gl_label_object_set_text_alignment (object, text_alignment, TRUE);
2158 g_list_free (selection_list);
2160 end_selection_op (label);
2162 gl_debug (DEBUG_LABEL, "END");
2166 /*****************************************************************************/
2167 /* Set text line spacing for all text contained in selected objects. */
2168 /*****************************************************************************/
2170 gl_label_set_selection_text_line_spacing (glLabel *label,
2171 gdouble text_line_spacing)
2173 GList *selection_list;
2175 glLabelObject *object;
2177 gl_debug (DEBUG_LABEL, "START");
2179 g_return_if_fail (label && GL_IS_LABEL (label));
2181 begin_selection_op (label);
2183 selection_list = gl_label_get_selection_list (label);
2185 for (p = selection_list; p != NULL; p = p->next)
2187 object = GL_LABEL_OBJECT (p->data);
2188 gl_label_object_set_text_line_spacing (object, text_line_spacing, TRUE);
2191 g_list_free (selection_list);
2193 end_selection_op (label);
2195 gl_debug (DEBUG_LABEL, "END");
2199 /*****************************************************************************/
2200 /* Set text color for all text contained in selected objects. */
2201 /*****************************************************************************/
2203 gl_label_set_selection_text_color (glLabel *label,
2204 glColorNode *text_color_node)
2206 GList *selection_list;
2208 glLabelObject *object;
2210 gl_debug (DEBUG_LABEL, "START");
2212 g_return_if_fail (label && GL_IS_LABEL (label));
2214 begin_selection_op (label);
2216 selection_list = gl_label_get_selection_list (label);
2218 for (p = selection_list; p != NULL; p = p->next)
2220 object = GL_LABEL_OBJECT (p->data);
2221 gl_label_object_set_text_color (object, text_color_node, TRUE);
2224 g_list_free (selection_list);
2226 end_selection_op (label);
2228 gl_debug (DEBUG_LABEL, "END");
2232 /*****************************************************************************/
2233 /* Set fill color for all selected objects. */
2234 /*****************************************************************************/
2236 gl_label_set_selection_fill_color (glLabel *label,
2237 glColorNode *fill_color_node)
2239 GList *selection_list;
2241 glLabelObject *object;
2243 gl_debug (DEBUG_LABEL, "START");
2245 g_return_if_fail (label && GL_IS_LABEL (label));
2247 begin_selection_op (label);
2249 selection_list = gl_label_get_selection_list (label);
2251 for (p = selection_list; p != NULL; p = p->next)
2253 object = GL_LABEL_OBJECT (p->data);
2254 gl_label_object_set_fill_color (object, fill_color_node, TRUE);
2257 g_list_free (selection_list);
2259 end_selection_op (label);
2261 gl_debug (DEBUG_LABEL, "END");
2265 /*****************************************************************************/
2266 /* Set line color for all selected objects. */
2267 /*****************************************************************************/
2269 gl_label_set_selection_line_color (glLabel *label,
2270 glColorNode *line_color_node)
2272 GList *selection_list;
2274 glLabelObject *object;
2276 gl_debug (DEBUG_LABEL, "START");
2278 g_return_if_fail (label && GL_IS_LABEL (label));
2280 begin_selection_op (label);
2282 selection_list = gl_label_get_selection_list (label);
2284 for (p = selection_list; p != NULL; p = p->next)
2286 object = GL_LABEL_OBJECT (p->data);
2287 gl_label_object_set_line_color (object, line_color_node, TRUE);
2290 g_list_free (selection_list);
2292 end_selection_op (label);
2294 gl_debug (DEBUG_LABEL, "END");
2298 /*****************************************************************************/
2299 /* Set line width for all selected objects. */
2300 /*****************************************************************************/
2302 gl_label_set_selection_line_width (glLabel *label,
2305 GList *selection_list;
2307 glLabelObject *object;
2309 gl_debug (DEBUG_LABEL, "START");
2311 g_return_if_fail (label && GL_IS_LABEL (label));
2313 begin_selection_op (label);
2315 selection_list = gl_label_get_selection_list (label);
2317 for (p = selection_list; p != NULL; p = p->next)
2319 object = GL_LABEL_OBJECT (p->data);
2320 gl_label_object_set_line_width (object, line_width, TRUE);
2323 g_list_free (selection_list);
2325 end_selection_op (label);
2327 gl_debug (DEBUG_LABEL, "END");
2331 /*****************************************************************************/
2332 /* "Cut" selected items and place on clipboard. */
2333 /*****************************************************************************/
2335 gl_label_cut_selection (glLabel *label)
2337 gl_debug (DEBUG_LABEL, "START");
2339 g_return_if_fail (label && GL_IS_LABEL (label));
2341 gl_label_copy_selection (label);
2342 gl_label_delete_selection (label);
2344 gl_debug (DEBUG_LABEL, "END");
2348 /*****************************************************************************/
2349 /* "Copy" selected items to clipboard. */
2350 /*****************************************************************************/
2352 gl_label_copy_selection (glLabel *label)
2354 GtkClipboard *clipboard;
2355 GList *selection_list;
2356 glLabel *label_copy;
2358 glLabelObject *object;
2359 glXMLLabelStatus status;
2361 ClipboardData *data;
2363 static GtkTargetEntry glabels_targets[] = { { "application/glabels", 0, 0 },
2364 { "text/xml", 0, 0 },
2367 GtkTargetList *target_list;
2368 GtkTargetEntry *target_table;
2371 gl_debug (DEBUG_LABEL, "START");
2373 g_return_if_fail (label && GL_IS_LABEL (label));
2375 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2377 selection_list = gl_label_get_selection_list (label);
2382 data = g_new0 (ClipboardData, 1);
2384 target_list = gtk_target_list_new (glabels_targets, G_N_ELEMENTS(glabels_targets));
2387 * Serialize selection by encoding as an XML label document.
2389 label_copy = GL_LABEL(gl_label_new ());
2391 gl_label_set_template (label_copy, label->priv->template, FALSE);
2392 gl_label_set_rotate_flag (label_copy, label->priv->rotate_flag, FALSE);
2394 for (p = selection_list; p != NULL; p = p->next)
2396 object = GL_LABEL_OBJECT (p->data);
2398 gl_label_add_object (label_copy, gl_label_object_dup (object, label_copy));
2401 data->xml_buffer = gl_xml_label_save_buffer (label_copy, &status);
2403 g_object_unref (G_OBJECT (label_copy));
2407 * Is it an atomic text selection? If so, also make available as text.
2409 if ( gl_label_is_selection_atomic (label) &&
2410 GL_IS_LABEL_TEXT (selection_list->data) )
2412 glLabelText *text_object = GL_LABEL_TEXT (selection_list->data);
2414 gtk_target_list_add_text_targets (target_list, 1);
2416 data->text = gl_label_text_get_text (text_object);
2421 * Is it an atomic image selection? If so, also make available as pixbuf.
2423 if ( gl_label_is_selection_atomic (label) &&
2424 GL_IS_LABEL_IMAGE (selection_list->data) )
2426 glLabelImage *image_object = GL_LABEL_IMAGE (selection_list->data);
2427 GdkPixbuf *pixbuf = gl_label_image_get_pixbuf (image_object, NULL);
2431 gtk_target_list_add_image_targets (target_list, 2, TRUE);
2432 data->pixbuf = pixbuf;
2437 target_table = gtk_target_table_new_from_list (target_list, &n_targets);
2439 gtk_clipboard_set_with_data (clipboard,
2440 target_table, n_targets,
2441 (GtkClipboardGetFunc)clipboard_get_cb,
2442 (GtkClipboardClearFunc)clipboard_clear_cb,
2445 gtk_target_table_free (target_table, n_targets);
2446 gtk_target_list_unref (target_list);
2450 g_list_free (selection_list);
2452 gl_debug (DEBUG_LABEL, "END");
2456 /*****************************************************************************/
2457 /* "Paste" from clipboard. */
2458 /*****************************************************************************/
2460 gl_label_paste (glLabel *label)
2462 GtkClipboard *clipboard;
2464 gl_debug (DEBUG_LABEL, "START");
2466 g_return_if_fail (label && GL_IS_LABEL (label));
2468 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2470 gtk_clipboard_request_targets (clipboard,
2471 (GtkClipboardTargetsReceivedFunc)receive_targets_cb,
2474 gl_debug (DEBUG_LABEL, "END");
2478 /*****************************************************************************/
2479 /* Is there anything that can be pasted? */
2480 /*****************************************************************************/
2482 gl_label_can_paste (glLabel *label)
2484 GtkClipboard *clipboard;
2487 gl_debug (DEBUG_LABEL, "START");
2489 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2491 can_flag = gtk_clipboard_wait_is_target_available (clipboard,
2492 gdk_atom_intern("application/glabels", TRUE))
2493 || gtk_clipboard_wait_is_text_available (clipboard)
2494 || gtk_clipboard_wait_is_image_available (clipboard);
2496 gl_debug (DEBUG_LABEL, "END");
2501 /****************************************************************************/
2502 /* Clipboard "Get" function. */
2503 /****************************************************************************/
2505 clipboard_get_cb (GtkClipboard *clipboard,
2506 GtkSelectionData *selection_data,
2508 ClipboardData *data)
2510 gl_debug (DEBUG_LABEL, "START");
2516 gtk_selection_data_set (selection_data,
2517 gtk_selection_data_get_target (selection_data),
2519 (guchar *)data->xml_buffer, strlen (data->xml_buffer));
2523 gtk_selection_data_set_text (selection_data, data->text, -1);
2527 gtk_selection_data_set_pixbuf (selection_data, data->pixbuf);
2531 g_assert_not_reached ();
2536 gl_debug (DEBUG_LABEL, "END");
2540 /****************************************************************************/
2541 /* Clipboard "Clear" function. */
2542 /****************************************************************************/
2544 clipboard_clear_cb (GtkClipboard *clipboard,
2545 ClipboardData *data)
2547 gl_debug (DEBUG_LABEL, "START");
2549 g_free (data->xml_buffer);
2550 g_free (data->text);
2553 g_object_unref (data->pixbuf);
2558 gl_debug (DEBUG_LABEL, "END");
2562 /****************************************************************************/
2563 /* Deal with clipboard data. */
2564 /****************************************************************************/
2566 receive_targets_cb (GtkClipboard *clipboard,
2574 * Application/glabels
2576 for ( i = 0; i < n_targets; i++ )
2578 if ( strcmp(gdk_atom_name(targets[i]), "application/glabels") == 0 )
2580 gtk_clipboard_request_contents (clipboard,
2581 gdk_atom_intern("application/glabels", TRUE),
2582 (GtkClipboardReceivedFunc)paste_xml_received_cb,
2591 if ( gtk_targets_include_text (targets, n_targets) )
2593 gtk_clipboard_request_text (clipboard,
2594 (GtkClipboardTextReceivedFunc)paste_text_received_cb,
2602 if ( gtk_targets_include_image (targets, n_targets, TRUE) )
2604 gtk_clipboard_request_image (clipboard,
2605 (GtkClipboardImageReceivedFunc)paste_image_received_cb,
2612 /****************************************************************************/
2613 /* Paste received glabels XML callback. */
2614 /****************************************************************************/
2616 paste_xml_received_cb (GtkClipboard *clipboard,
2617 GtkSelectionData *selection_data,
2621 glLabel *label_copy;
2622 glXMLLabelStatus status;
2624 glLabelObject *object, *newobject;
2626 gl_debug (DEBUG_LABEL, "START");
2628 gl_label_checkpoint (label, _("Paste"));
2630 xml_buffer = (gchar *)gtk_selection_data_get_data (selection_data);
2633 * Deserialize XML label document and extract objects.
2635 label_copy = gl_xml_label_open_buffer (xml_buffer, &status);
2638 gl_label_unselect_all (label);
2640 for (p = label_copy->priv->object_list; p != NULL; p = p->next)
2642 object = (glLabelObject *) p->data;
2643 newobject = gl_label_object_dup (object, label);
2644 gl_label_add_object( label, newobject );
2646 gl_label_select_object (label, newobject);
2648 gl_debug (DEBUG_LABEL, "object pasted");
2651 g_object_unref (G_OBJECT (label_copy));
2654 gl_debug (DEBUG_LABEL, "END");
2658 /****************************************************************************/
2659 /* Paste received text callback. */
2660 /****************************************************************************/
2662 paste_text_received_cb (GtkClipboard *clipboard,
2666 glLabelObject *object;
2668 gl_debug (DEBUG_LABEL, "START");
2670 gl_label_checkpoint (label, _("Paste"));
2672 gl_label_unselect_all (label);
2674 object = GL_LABEL_OBJECT (gl_label_text_new (label, FALSE));
2675 gl_label_text_set_text (GL_LABEL_TEXT (object), text, FALSE);
2676 gl_label_object_set_position (object, 18, 18, FALSE);
2678 gl_label_select_object (label, object);
2680 gl_debug (DEBUG_LABEL, "END");
2684 /****************************************************************************/
2685 /* Paste received image callback. */
2686 /****************************************************************************/
2688 paste_image_received_cb (GtkClipboard *clipboard,
2692 glLabelObject *object;
2694 gl_debug (DEBUG_LABEL, "START");
2696 gl_label_checkpoint (label, _("Paste"));
2698 gl_label_unselect_all (label);
2700 object = GL_LABEL_OBJECT (gl_label_image_new (label, FALSE));
2701 gl_label_image_set_pixbuf (GL_LABEL_IMAGE (object), pixbuf, FALSE);
2702 gl_label_object_set_position (object, 18, 18, FALSE);
2704 gl_label_select_object (label, object);
2706 gl_debug (DEBUG_LABEL, "END");
2710 /****************************************************************************/
2711 /* Set default font family. */
2712 /****************************************************************************/
2714 gl_label_set_default_font_family (glLabel *label,
2715 const gchar *font_family)
2717 gl_debug (DEBUG_LABEL, "START");
2719 g_return_if_fail (label && GL_IS_LABEL (label));
2721 g_free (label->priv->default_font_family);
2722 label->priv->default_font_family = g_strdup (font_family);
2724 gl_debug (DEBUG_LABEL, "END");
2728 /****************************************************************************/
2729 /* Set default font size. */
2730 /****************************************************************************/
2732 gl_label_set_default_font_size (glLabel *label,
2735 gl_debug (DEBUG_LABEL, "START");
2737 g_return_if_fail (label && GL_IS_LABEL (label));
2739 label->priv->default_font_size = font_size;
2741 gl_debug (DEBUG_LABEL, "END");
2745 /****************************************************************************/
2746 /* Set default font weight. */
2747 /****************************************************************************/
2749 gl_label_set_default_font_weight (glLabel *label,
2750 PangoWeight font_weight)
2752 gl_debug (DEBUG_LABEL, "START");
2754 g_return_if_fail (label && GL_IS_LABEL (label));
2756 label->priv->default_font_weight = font_weight;
2758 gl_debug (DEBUG_LABEL, "END");
2762 /****************************************************************************/
2763 /* Set default font italic flag. */
2764 /****************************************************************************/
2766 gl_label_set_default_font_italic_flag (glLabel *label,
2767 gboolean font_italic_flag)
2769 gl_debug (DEBUG_LABEL, "START");
2771 g_return_if_fail (label && GL_IS_LABEL (label));
2773 label->priv->default_font_italic_flag = font_italic_flag;
2775 gl_debug (DEBUG_LABEL, "END");
2779 /****************************************************************************/
2780 /* Set default text color. */
2781 /****************************************************************************/
2783 gl_label_set_default_text_color (glLabel *label,
2786 gl_debug (DEBUG_LABEL, "START");
2788 g_return_if_fail (label && GL_IS_LABEL (label));
2790 label->priv->default_text_color = text_color;
2792 gl_debug (DEBUG_LABEL, "END");
2796 /****************************************************************************/
2797 /* Set default text alignment. */
2798 /****************************************************************************/
2800 gl_label_set_default_text_alignment (glLabel *label,
2801 PangoAlignment text_alignment)
2803 gl_debug (DEBUG_LABEL, "START");
2805 g_return_if_fail (label && GL_IS_LABEL (label));
2807 label->priv->default_text_alignment = text_alignment;
2808 gl_debug (DEBUG_LABEL, "END");
2812 /****************************************************************************/
2813 /* Set default text line spacing. */
2814 /****************************************************************************/
2816 gl_label_set_default_text_line_spacing (glLabel *label,
2817 gdouble text_line_spacing)
2819 gl_debug (DEBUG_LABEL, "START");
2821 g_return_if_fail (label && GL_IS_LABEL (label));
2823 label->priv->default_text_line_spacing = text_line_spacing;
2825 gl_debug (DEBUG_LABEL, "END");
2829 /****************************************************************************/
2830 /* Set default line width. */
2831 /****************************************************************************/
2833 gl_label_set_default_line_width (glLabel *label,
2836 gl_debug (DEBUG_LABEL, "START");
2838 g_return_if_fail (label && GL_IS_LABEL (label));
2840 label->priv->default_line_width = line_width;
2842 gl_debug (DEBUG_LABEL, "END");
2846 /****************************************************************************/
2847 /* Set default line color. */
2848 /****************************************************************************/
2850 gl_label_set_default_line_color (glLabel *label,
2853 gl_debug (DEBUG_LABEL, "START");
2855 g_return_if_fail (label && GL_IS_LABEL (label));
2857 label->priv->default_line_color = line_color;
2859 gl_debug (DEBUG_LABEL, "END");
2863 /****************************************************************************/
2864 /* Set default fill color. */
2865 /****************************************************************************/
2867 gl_label_set_default_fill_color (glLabel *label,
2870 gl_debug (DEBUG_LABEL, "START");
2872 g_return_if_fail (label && GL_IS_LABEL (label));
2874 label->priv->default_fill_color = fill_color;
2876 gl_debug (DEBUG_LABEL, "END");
2880 /****************************************************************************/
2881 /* Get default font family. */
2882 /****************************************************************************/
2884 gl_label_get_default_font_family (glLabel *label)
2886 gl_debug (DEBUG_LABEL, "START");
2888 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
2890 gl_debug (DEBUG_LABEL, "END");
2892 return g_strdup (label->priv->default_font_family);
2896 /****************************************************************************/
2897 /* Get default font size. */
2898 /****************************************************************************/
2900 gl_label_get_default_font_size (glLabel *label)
2902 gl_debug (DEBUG_LABEL, "START");
2904 g_return_val_if_fail (label && GL_IS_LABEL (label), 12.0);
2906 gl_debug (DEBUG_LABEL, "END");
2908 return label->priv->default_font_size;
2912 /****************************************************************************/
2913 /* Get default font weight. */
2914 /****************************************************************************/
2916 gl_label_get_default_font_weight (glLabel *label)
2918 gl_debug (DEBUG_LABEL, "START");
2920 g_return_val_if_fail (label && GL_IS_LABEL (label), PANGO_WEIGHT_NORMAL);
2922 gl_debug (DEBUG_LABEL, "END");
2924 return label->priv->default_font_weight;
2928 /****************************************************************************/
2929 /* Get default font italic flag. */
2930 /****************************************************************************/
2932 gl_label_get_default_font_italic_flag (glLabel *label)
2934 gl_debug (DEBUG_LABEL, "START");
2936 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
2938 gl_debug (DEBUG_LABEL, "END");
2940 return label->priv->default_font_italic_flag;
2944 /****************************************************************************/
2945 /* Get default text color. */
2946 /****************************************************************************/
2948 gl_label_get_default_text_color (glLabel *label)
2950 gl_debug (DEBUG_LABEL, "START");
2952 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
2954 gl_debug (DEBUG_LABEL, "END");
2956 return label->priv->default_text_color;
2960 /****************************************************************************/
2961 /* Get default text alignment. */
2962 /****************************************************************************/
2964 gl_label_get_default_text_alignment (glLabel *label)
2966 gl_debug (DEBUG_LABEL, "START");
2968 g_return_val_if_fail (label && GL_IS_LABEL (label), PANGO_ALIGN_LEFT);
2970 gl_debug (DEBUG_LABEL, "END");
2972 return label->priv->default_text_alignment;
2976 /****************************************************************************/
2977 /* Get default text line spacing. */
2978 /****************************************************************************/
2980 gl_label_get_default_text_line_spacing (glLabel *label)
2982 gl_debug (DEBUG_LABEL, "START");
2984 g_return_val_if_fail (label && GL_IS_LABEL (label), 1.0);
2986 gl_debug (DEBUG_LABEL, "END");
2988 return label->priv->default_text_line_spacing;
2992 /****************************************************************************/
2993 /* Get default line width. */
2994 /****************************************************************************/
2996 gl_label_get_default_line_width (glLabel *label)
2998 gl_debug (DEBUG_LABEL, "START");
3000 g_return_val_if_fail (label && GL_IS_LABEL (label), 1.0);
3002 gl_debug (DEBUG_LABEL, "END");
3004 return label->priv->default_line_width;
3008 /****************************************************************************/
3009 /* Get default line color. */
3010 /****************************************************************************/
3012 gl_label_get_default_line_color (glLabel *label)
3014 gl_debug (DEBUG_LABEL, "START");
3016 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
3018 gl_debug (DEBUG_LABEL, "END");
3020 return label->priv->default_line_color;
3024 /****************************************************************************/
3025 /* Get default fill color. */
3026 /****************************************************************************/
3028 gl_label_get_default_fill_color (glLabel *label)
3030 gl_debug (DEBUG_LABEL, "START");
3032 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
3034 gl_debug (DEBUG_LABEL, "END");
3036 return label->priv->default_fill_color;
3040 /****************************************************************************/
3042 /****************************************************************************/
3044 gl_label_draw (glLabel *label,
3046 gboolean screen_flag,
3047 glMergeRecord *record)
3050 glLabelObject *object;
3052 g_return_if_fail (label && GL_IS_LABEL (label));
3054 for (p_obj = label->priv->object_list; p_obj != NULL; p_obj = p_obj->next)
3056 object = GL_LABEL_OBJECT (p_obj->data);
3058 gl_label_object_draw (object, cr, screen_flag, record);
3063 /****************************************************************************/
3064 /* Get object located at coordinates. */
3065 /****************************************************************************/
3066 glLabelObject *gl_label_object_at (glLabel *label,
3072 glLabelObject *object;
3074 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
3076 for (p_obj = g_list_last (label->priv->object_list); p_obj != NULL; p_obj = p_obj->prev)
3078 object = GL_LABEL_OBJECT (p_obj->data);
3080 if (gl_label_object_is_located_at (object, cr, x_pixels, y_pixels))
3091 /****************************************************************************/
3092 /* Return handle and associated object at coordinates. */
3093 /****************************************************************************/
3095 gl_label_get_handle_at (glLabel *label,
3099 glLabelObjectHandle *handle)
3101 GList *selection_list;
3103 glLabelObject *object;
3105 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
3107 selection_list = gl_label_get_selection_list (label);
3109 for (p_obj = g_list_last (selection_list); p_obj != NULL; p_obj = p_obj->prev)
3112 object = GL_LABEL_OBJECT (p_obj->data);
3114 if ((*handle = gl_label_object_handle_at (object, cr, x_pixels, y_pixels)))
3116 g_list_free (selection_list);
3122 g_list_free (selection_list);
3124 *handle = GL_LABEL_OBJECT_HANDLE_NONE;
3129 /****************************************************************************/
3130 /* Checkpoint state. */
3131 /****************************************************************************/
3133 gl_label_checkpoint (glLabel *this,
3134 const gchar *description)
3138 gl_debug (DEBUG_LABEL, "START");
3141 * Do not perform consecutive checkpoints that are identical.
3142 * E.g. moving an object by dragging, would produce a large number
3143 * of incremental checkpoints -- what we really want is a single
3144 * checkpoint so that we can undo the entire dragging effort with
3147 if ( this->priv->cp_cleared_flag
3148 || (this->priv->cp_desc == NULL)
3149 || (strcmp (description, this->priv->cp_desc) != 0) )
3152 /* Sever old redo "thread" */
3153 stack_clear (this->priv->redo_stack);
3155 /* Save state onto undo stack. */
3156 state = state_new (this, description);
3157 stack_push_state (this->priv->undo_stack, state);
3159 /* Track consecutive checkpoints. */
3160 this->priv->cp_cleared_flag = FALSE;
3161 this->priv->cp_desc = g_strdup (description);
3164 gl_debug (DEBUG_LABEL, "END");
3168 /****************************************************************************/
3170 /****************************************************************************/
3172 gl_label_undo (glLabel *this)
3177 gl_debug (DEBUG_LABEL, "START");
3179 state_old = stack_pop_state (this->priv->undo_stack);
3180 state_now = state_new (this, state_old->description);
3182 stack_push_state (this->priv->redo_stack, state_now);
3184 state_restore (state_old, this);
3185 state_free (state_old);
3187 this->priv->cp_cleared_flag = TRUE;
3189 gl_debug (DEBUG_LABEL, "END");
3193 /****************************************************************************/
3195 /****************************************************************************/
3197 gl_label_redo (glLabel *this)
3202 gl_debug (DEBUG_LABEL, "START");
3204 state_old = stack_pop_state (this->priv->redo_stack);
3205 state_now = state_new (this, state_old->description);
3207 stack_push_state (this->priv->undo_stack, state_now);
3209 state_restore (state_old, this);
3210 state_free (state_old);
3212 this->priv->cp_cleared_flag = TRUE;
3214 gl_debug (DEBUG_LABEL, "END");
3218 /****************************************************************************/
3220 /****************************************************************************/
3222 gl_label_can_undo (glLabel *this)
3224 return (!g_queue_is_empty (this->priv->undo_stack));
3228 /****************************************************************************/
3230 /****************************************************************************/
3232 gl_label_can_redo (glLabel *this)
3234 return (!g_queue_is_empty (this->priv->redo_stack));
3238 /****************************************************************************/
3239 /* Get undo description string. */
3240 /****************************************************************************/
3242 gl_label_get_undo_description (glLabel *this)
3247 state = g_queue_peek_head (this->priv->undo_stack);
3250 description = g_strdup (state->description);
3254 description = g_strdup ("");
3261 /****************************************************************************/
3262 /* Get redo description string. */
3263 /****************************************************************************/
3265 gl_label_get_redo_description (glLabel *this)
3270 state = g_queue_peek_head (this->priv->redo_stack);
3273 description = g_strdup (state->description);
3277 description = g_strdup ("");
3284 /****************************************************************************/
3285 /* Clear undo or redo stack. */
3286 /****************************************************************************/
3288 stack_clear (GQueue *stack)
3292 gl_debug (DEBUG_LABEL, "START");
3294 while ( (state = g_queue_pop_head (stack)) != NULL )
3299 gl_debug (DEBUG_LABEL, "END");
3303 /****************************************************************************/
3304 /* Push state onto stack. */
3305 /****************************************************************************/
3307 stack_push_state (GQueue *stack,
3310 gl_debug (DEBUG_LABEL, "START");
3312 g_queue_push_head( stack, state );
3314 gl_debug (DEBUG_LABEL, "END");
3318 /****************************************************************************/
3319 /* Pop state from stack. */
3320 /****************************************************************************/
3322 stack_pop_state (GQueue *stack)
3326 gl_debug (DEBUG_LABEL, "START");
3328 state = g_queue_pop_head (stack);
3330 gl_debug (DEBUG_LABEL, "END");
3335 /****************************************************************************/
3336 /* New state from label. */
3337 /****************************************************************************/
3339 state_new (glLabel *this,
3340 const gchar *description)
3344 glLabelObject *object;
3346 gl_debug (DEBUG_LABEL, "START");
3348 state = g_new0 (State, 1);
3350 state->description = g_strdup (description);
3352 state->template = lgl_template_dup (this->priv->template);
3353 state->rotate_flag = this->priv->rotate_flag;
3355 for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_obj->next )
3357 object = GL_LABEL_OBJECT (p_obj->data);
3359 state->object_list = g_list_append (state->object_list,
3360 gl_label_object_dup (object, this));
3363 state->merge = gl_merge_dup (this->priv->merge);
3365 state->modified_flag = this->priv->modified_flag;
3366 state->time_stamp = this->priv->time_stamp;
3369 gl_debug (DEBUG_LABEL, "END");
3374 /****************************************************************************/
3375 /* Restore label from saved state. */
3376 /****************************************************************************/
3378 state_free (State *state)
3382 gl_debug (DEBUG_LABEL, "START");
3384 g_free (state->description);
3386 lgl_template_free (state->template);
3389 g_object_unref (G_OBJECT (state->merge));
3392 for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
3394 g_object_unref (G_OBJECT (p_obj->data));
3396 g_list_free (state->object_list);
3400 gl_debug (DEBUG_LABEL, "END");
3404 /****************************************************************************/
3405 /* Restore label from saved state. */
3406 /****************************************************************************/
3408 state_restore (State *state,
3412 GList *p_obj, *p_next;
3413 glLabelObject *object;
3415 gl_debug (DEBUG_LABEL, "START");
3417 gl_label_set_rotate_flag (this, state->rotate_flag, FALSE);
3418 gl_label_set_template (this, state->template, FALSE);
3420 for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_next )
3422 p_next = p_obj->next; /* Hold on to next; delete is destructive */
3423 object = GL_LABEL_OBJECT (p_obj->data);
3425 gl_label_delete_object (this, object);
3428 for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
3430 object = GL_LABEL_OBJECT (p_obj->data);
3432 gl_label_add_object (this, gl_label_object_dup (object, this));
3434 g_signal_emit (G_OBJECT(this), signals[SELECTION_CHANGED], 0);
3436 gl_label_set_merge (this, state->merge, FALSE);
3439 if ( !state->modified_flag &&
3440 (state->time_stamp.tv_sec == this->priv->time_stamp.tv_sec) &&
3441 (state->time_stamp.tv_usec == this->priv->time_stamp.tv_usec) )
3443 gl_label_clear_modified (this);
3446 gl_debug (DEBUG_LABEL, "END");
3453 * Local Variables: -- emacs
3455 * c-basic-offset: 8 -- emacs
3456 * tab-width: 8 -- emacs
3457 * indent-tabs-mode: nil -- emacs