1 /*
2 * label.c
3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
4 *
5 * This file is part of gLabels.
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21 #include <config.h>
22
23 #include "label.h"
24
25 #include <glib/gi18n.h>
26 #include <math.h>
27
28 #include "template-history.h"
29 #include "file-util.h"
30 #include "xml-label.h"
31 #include "prefs.h"
32 #include "label-text.h"
33 #include "label-image.h"
34 #include "marshal.h"
35
36 #include "debug.h"
37
38
39 /*========================================================*/
40 /* Private macros and constants. */
41 /*========================================================*/
42
43
44 /*========================================================*/
45 /* Private types. */
46 /*========================================================*/
47
48 struct _glLabelPrivate {
49
50 gchar *filename;
51 gint compression;
52 gint untitled_instance;
53
54 gboolean modified_flag;
55 GTimeVal time_stamp;
56
57 lglTemplate *template;
58 gboolean rotate_flag;
59
60 GList *object_list;
61
62 glMerge *merge;
63
64 GHashTable *pixbuf_cache;
65 GHashTable *svg_cache;
66
67 /* Delay changed signals while operating on selections of multiple objects. */
68 gboolean selection_op_flag;
69 gboolean delayed_change_flag;
70
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 glValignment default_text_valignment;
79 gdouble default_text_line_spacing;
80
81 /* Default object line properties */
82 gdouble default_line_width;
83 guint default_line_color;
84
85 /* Default object fill properties */
86 guint default_fill_color;
87
88 /* Undo/Redo state */
89 GQueue *undo_stack;
90 GQueue *redo_stack;
91 gboolean cp_cleared_flag;
92 gchar *cp_desc;
93 };
94
95 typedef struct {
96 gchar *xml_buffer;
97 gchar *text;
98 GdkPixbuf *pixbuf;
99 } ClipboardData;
100
101 enum {
102 SELECTION_CHANGED,
103 CHANGED,
104 NAME_CHANGED,
105 MODIFIED_CHANGED,
106 MERGE_CHANGED,
107 SIZE_CHANGED,
108 LAST_SIGNAL
109 };
110
111 typedef struct {
112 gchar *description;
113
114 gboolean modified_flag;
115 GTimeVal time_stamp;
116
117 lglTemplate *template;
118 gboolean rotate_flag;
119
120 GList *object_list;
121
122 glMerge *merge;
123
124 } State;
125
126
127 /*========================================================*/
128 /* Private globals. */
129 /*========================================================*/
130
131 static guint signals[LAST_SIGNAL] = {0};
132
133 static guint untitled = 0;
134
135
136 /*========================================================*/
137 /* Private function prototypes. */
138 /*========================================================*/
139
140 static void gl_label_finalize (GObject *object);
141
142 static void object_changed_cb (glLabelObject *object,
143 glLabel *label);
144
145 static void object_moved_cb (glLabelObject *object,
146 glLabel *label);
147
148 static void do_modify (glLabel *label);
149
150 static void begin_selection_op (glLabel *label);
151 static void end_selection_op (glLabel *label);
152
153 static void clipboard_get_cb (GtkClipboard *clipboard,
154 GtkSelectionData *selection_data,
155 guint info,
156 ClipboardData *data);
157
158 static void clipboard_clear_cb (GtkClipboard *clipboard,
159 ClipboardData *data);
160
161 static void receive_targets_cb (GtkClipboard *clipboard,
162 GdkAtom *targets,
163 gint n_targets,
164 glLabel *label);
165
166 static void paste_xml_received_cb (GtkClipboard *clipboard,
167 GtkSelectionData *selection_data,
168 glLabel *label);
169
170 static void paste_text_received_cb (GtkClipboard *clipboard,
171 const gchar *text,
172 glLabel *label);
173
174 static void paste_image_received_cb(GtkClipboard *clipboard,
175 GdkPixbuf *pixbuf,
176 glLabel *label);
177
178 static void stack_clear (GQueue *stack);
179 static void stack_push_state (GQueue *stack,
180 State *state);
181 static State *stack_pop_state (GQueue *stack);
182
183 static State *state_new (glLabel *this,
184 const gchar *description);
185 static void state_free (State *state);
186 static void state_restore (State *state,
187 glLabel *this);
188
189
190 /*****************************************************************************/
191 /* Boilerplate object stuff. */
192 /*****************************************************************************/
G_DEFINE_TYPE(glLabel,gl_label,G_TYPE_OBJECT)193 G_DEFINE_TYPE (glLabel, gl_label, G_TYPE_OBJECT)
194
195
196 static void
197 gl_label_class_init (glLabelClass *class)
198 {
199 GObjectClass *object_class = G_OBJECT_CLASS (class);
200
201 gl_debug (DEBUG_LABEL, "START");
202
203 gl_label_parent_class = g_type_class_peek_parent (class);
204
205 object_class->finalize = gl_label_finalize;
206
207 signals[SELECTION_CHANGED] =
208 g_signal_new ("selection_changed",
209 G_OBJECT_CLASS_TYPE (object_class),
210 G_SIGNAL_RUN_LAST,
211 G_STRUCT_OFFSET (glLabelClass, selection_changed),
212 NULL, NULL,
213 gl_marshal_VOID__VOID,
214 G_TYPE_NONE,
215 0);
216 signals[CHANGED] =
217 g_signal_new ("changed",
218 G_OBJECT_CLASS_TYPE (object_class),
219 G_SIGNAL_RUN_LAST,
220 G_STRUCT_OFFSET (glLabelClass, changed),
221 NULL, NULL,
222 gl_marshal_VOID__VOID,
223 G_TYPE_NONE,
224 0);
225 signals[NAME_CHANGED] =
226 g_signal_new ("name_changed",
227 G_OBJECT_CLASS_TYPE (object_class),
228 G_SIGNAL_RUN_LAST,
229 G_STRUCT_OFFSET (glLabelClass, name_changed),
230 NULL, NULL,
231 gl_marshal_VOID__VOID,
232 G_TYPE_NONE,
233 0);
234 signals[MODIFIED_CHANGED] =
235 g_signal_new ("modified_changed",
236 G_OBJECT_CLASS_TYPE (object_class),
237 G_SIGNAL_RUN_LAST,
238 G_STRUCT_OFFSET (glLabelClass, modified_changed),
239 NULL, NULL,
240 gl_marshal_VOID__VOID,
241 G_TYPE_NONE,
242 0);
243 signals[MERGE_CHANGED] =
244 g_signal_new ("merge_changed",
245 G_OBJECT_CLASS_TYPE (object_class),
246 G_SIGNAL_RUN_LAST,
247 G_STRUCT_OFFSET (glLabelClass, merge_changed),
248 NULL, NULL,
249 gl_marshal_VOID__VOID,
250 G_TYPE_NONE,
251 0);
252 signals[SIZE_CHANGED] =
253 g_signal_new ("size_changed",
254 G_OBJECT_CLASS_TYPE (object_class),
255 G_SIGNAL_RUN_LAST,
256 G_STRUCT_OFFSET (glLabelClass, size_changed),
257 NULL, NULL,
258 gl_marshal_VOID__VOID,
259 G_TYPE_NONE,
260 0);
261
262 gl_debug (DEBUG_LABEL, "END");
263 }
264
265
266 static void
gl_label_init(glLabel * label)267 gl_label_init (glLabel *label)
268 {
269 gl_debug (DEBUG_LABEL, "START");
270
271 label->priv = g_new0 (glLabelPrivate, 1);
272
273 label->priv->template = NULL;
274 label->priv->rotate_flag = FALSE;
275 label->priv->object_list = NULL;
276
277 label->priv->filename = NULL;
278 label->priv->modified_flag = FALSE;
279 label->priv->compression = 9;
280
281 label->priv->merge = NULL;
282 label->priv->pixbuf_cache = gl_pixbuf_cache_new ();
283 label->priv->svg_cache = gl_svg_cache_new ();
284
285 label->priv->undo_stack = g_queue_new ();
286 label->priv->redo_stack = g_queue_new ();
287
288 /*
289 * Defaults from preferences
290 */
291 label->priv->default_font_family = gl_prefs_model_get_default_font_family (gl_prefs);
292 label->priv->default_font_size = gl_prefs_model_get_default_font_size (gl_prefs);
293 label->priv->default_font_weight = gl_prefs_model_get_default_font_weight (gl_prefs);
294 label->priv->default_font_italic_flag = gl_prefs_model_get_default_font_italic_flag (gl_prefs);
295 label->priv->default_text_color = gl_prefs_model_get_default_text_color (gl_prefs);
296 label->priv->default_text_alignment = gl_prefs_model_get_default_text_alignment (gl_prefs);
297 label->priv->default_text_line_spacing = gl_prefs_model_get_default_text_line_spacing (gl_prefs);
298 label->priv->default_line_width = gl_prefs_model_get_default_line_width (gl_prefs);
299 label->priv->default_line_color = gl_prefs_model_get_default_line_color (gl_prefs);
300 label->priv->default_fill_color = gl_prefs_model_get_default_fill_color (gl_prefs);
301
302 gl_debug (DEBUG_LABEL, "END");
303 }
304
305
306 static void
gl_label_finalize(GObject * object)307 gl_label_finalize (GObject *object)
308 {
309 glLabel *label = GL_LABEL (object);
310 GList *p;
311
312 gl_debug (DEBUG_LABEL, "START");
313
314 g_return_if_fail (object && GL_IS_LABEL (object));
315
316 for (p = label->priv->object_list; p != NULL; p = p->next)
317 {
318 g_object_unref (G_OBJECT(p->data));
319 }
320 g_list_free (label->priv->object_list);
321
322 lgl_template_free (label->priv->template);
323 g_free (label->priv->filename);
324 if (label->priv->merge != NULL)
325 {
326 g_object_unref (G_OBJECT(label->priv->merge));
327 }
328 g_free (label->priv->default_font_family);
329
330 stack_clear (label->priv->undo_stack);
331 stack_clear (label->priv->redo_stack);
332
333 g_queue_free (label->priv->undo_stack);
334 g_queue_free (label->priv->redo_stack);
335
336 gl_pixbuf_cache_free (label->priv->pixbuf_cache);
337 gl_svg_cache_free (label->priv->svg_cache);
338
339 g_free (label->priv);
340
341 G_OBJECT_CLASS (gl_label_parent_class)->finalize (object);
342
343 gl_debug (DEBUG_LABEL, "END");
344 }
345
346
347 /*****************************************************************************/
348 /* New label. */
349 /*****************************************************************************/
350 GObject *
gl_label_new(void)351 gl_label_new (void)
352 {
353 glLabel *label;
354
355 gl_debug (DEBUG_LABEL, "START");
356
357 label = g_object_new (gl_label_get_type(), NULL);
358
359 gl_debug (DEBUG_LABEL, "END");
360
361 return G_OBJECT (label);
362 }
363
364
365 /****************************************************************************/
366 /* Set filename. */
367 /****************************************************************************/
368 void
gl_label_set_filename(glLabel * label,const gchar * filename)369 gl_label_set_filename (glLabel *label,
370 const gchar *filename)
371 {
372 label->priv->filename = g_strdup (filename);
373
374 g_signal_emit (G_OBJECT(label), signals[NAME_CHANGED], 0);
375 }
376
377
378 /****************************************************************************/
379 /* return filename. */
380 /****************************************************************************/
381 gchar *
gl_label_get_filename(glLabel * label)382 gl_label_get_filename (glLabel *label)
383 {
384 gl_debug (DEBUG_LABEL, "");
385
386 return g_strdup ( label->priv->filename );
387 }
388
389
390 /****************************************************************************/
391 /* return short filename. */
392 /****************************************************************************/
393 gchar *
gl_label_get_short_name(glLabel * label)394 gl_label_get_short_name (glLabel *label)
395 {
396 gl_debug (DEBUG_LABEL, "");
397
398 if ( label->priv->filename == NULL )
399 {
400
401 if ( label->priv->untitled_instance == 0 )
402 {
403 label->priv->untitled_instance = ++untitled;
404 }
405
406 return g_strdup_printf ( "%s %d", _("Untitled"),
407 label->priv->untitled_instance );
408
409 }
410 else
411 {
412 gchar *temp_name, *short_name;
413
414 temp_name = g_path_get_basename ( label->priv->filename );
415 short_name = gl_file_util_remove_extension (temp_name);
416 g_free (temp_name);
417
418 return short_name;
419 }
420 }
421
422
423 /****************************************************************************/
424 /* Is label untitled? */
425 /****************************************************************************/
426 gboolean
gl_label_is_untitled(glLabel * label)427 gl_label_is_untitled (glLabel *label)
428 {
429 gl_debug (DEBUG_LABEL, "return %d",(label->priv->filename == NULL));
430 return (label->priv->filename == NULL);
431 }
432
433
434 /****************************************************************************/
435 /* Set compression level. */
436 /****************************************************************************/
437 void
gl_label_set_compression(glLabel * label,gint compression)438 gl_label_set_compression (glLabel *label,
439 gint compression)
440 {
441 gl_debug (DEBUG_LABEL, "set %d", compression);
442
443 /* Older versions of libxml2 always return a -1 for documents "read in," so
444 * default to 9. Also, default to 9 for anything else out of range. */
445 if ((compression < 0) || (compression >9))
446 {
447 compression = 9;
448 }
449
450 gl_debug (DEBUG_LABEL, "actual set %d", compression);
451 label->priv->compression = compression;
452 }
453
454
455 /****************************************************************************/
456 /* Get compression level. */
457 /****************************************************************************/
458 gint
gl_label_get_compression(glLabel * label)459 gl_label_get_compression (glLabel *label)
460 {
461 gl_debug (DEBUG_LABEL, "return %d", label->priv->compression);
462 return label->priv->compression;
463 }
464
465
466 /****************************************************************************/
467 /* Set modified flag. */
468 /****************************************************************************/
469 void
gl_label_set_modified(glLabel * label)470 gl_label_set_modified (glLabel *label)
471 {
472
473 if ( !label->priv->modified_flag )
474 {
475
476 label->priv->modified_flag = TRUE;
477
478 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
479 }
480
481 }
482
483
484 /****************************************************************************/
485 /* Clear modified flag. */
486 /****************************************************************************/
487 void
gl_label_clear_modified(glLabel * label)488 gl_label_clear_modified (glLabel *label)
489 {
490
491 if ( label->priv->modified_flag )
492 {
493
494 g_get_current_time (&label->priv->time_stamp);
495 label->priv->modified_flag = FALSE;
496
497 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
498 }
499
500 }
501
502
503 /****************************************************************************/
504 /* Is label modified? */
505 /****************************************************************************/
506 gboolean
gl_label_is_modified(glLabel * label)507 gl_label_is_modified (glLabel *label)
508 {
509 gl_debug (DEBUG_LABEL, "return %d", label->priv->modified_flag);
510 return label->priv->modified_flag;
511 }
512
513
514 /****************************************************************************/
515 /* Object "changed" callback. */
516 /****************************************************************************/
517 static void
object_changed_cb(glLabelObject * object,glLabel * label)518 object_changed_cb (glLabelObject *object,
519 glLabel *label)
520 {
521 do_modify (label);
522 }
523
524
525 /****************************************************************************/
526 /* Object "moved" callback. */
527 /****************************************************************************/
528 static void
object_moved_cb(glLabelObject * object,glLabel * label)529 object_moved_cb (glLabelObject *object,
530 glLabel *label)
531 {
532 do_modify (label);
533 }
534
535
536 /****************************************************************************/
537 /* Do modify. */
538 /****************************************************************************/
539 static void
do_modify(glLabel * label)540 do_modify (glLabel *label)
541 {
542 if ( label->priv->selection_op_flag )
543 {
544 label->priv->delayed_change_flag = TRUE;
545 }
546 else
547 {
548 label->priv->modified_flag = TRUE;
549
550 g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
551 g_signal_emit (G_OBJECT(label), signals[CHANGED], 0);
552 }
553 }
554
555
556 /****************************************************************************/
557 /* Begin selection operation. */
558 /****************************************************************************/
559 static void
begin_selection_op(glLabel * label)560 begin_selection_op (glLabel *label)
561 {
562 label->priv->selection_op_flag = TRUE;
563 }
564
565
566 /****************************************************************************/
567 /* End selection operation. */
568 /****************************************************************************/
569 static void
end_selection_op(glLabel * label)570 end_selection_op (glLabel *label)
571 {
572 label->priv->selection_op_flag = FALSE;
573 if ( label->priv->delayed_change_flag )
574 {
575 label->priv->delayed_change_flag = FALSE;
576 do_modify (label);
577 }
578 }
579
580
581 /****************************************************************************/
582 /* set template. */
583 /****************************************************************************/
584 void
gl_label_set_template(glLabel * label,const lglTemplate * template,gboolean checkpoint)585 gl_label_set_template (glLabel *label,
586 const lglTemplate *template,
587 gboolean checkpoint)
588 {
589 gchar *name;
590
591 gl_debug (DEBUG_LABEL, "START");
592
593 g_return_if_fail (label && GL_IS_LABEL (label));
594 g_return_if_fail (template);
595
596 if ((label->priv->template == NULL) ||
597 !lgl_template_do_templates_match (template, label->priv->template))
598 {
599
600 if ( checkpoint )
601 {
602 gl_label_checkpoint (label, _("Label properties"));
603 }
604
605 lgl_template_free (label->priv->template);
606 label->priv->template = lgl_template_dup (template);
607
608 do_modify (label);
609 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
610
611 name = lgl_template_get_name (template);
612 gl_template_history_model_add_name (gl_template_history, name);
613 g_free (name);
614 }
615
616 gl_debug (DEBUG_LABEL, "END");
617 }
618
619
620 /****************************************************************************/
621 /* get template. */
622 /****************************************************************************/
623 const lglTemplate *
gl_label_get_template(glLabel * label)624 gl_label_get_template (glLabel *label)
625 {
626 return label->priv->template;
627 }
628
629
630 /****************************************************************************/
631 /* set rotate flag. */
632 /****************************************************************************/
633 void
gl_label_set_rotate_flag(glLabel * label,gboolean rotate_flag,gboolean checkpoint)634 gl_label_set_rotate_flag (glLabel *label,
635 gboolean rotate_flag,
636 gboolean checkpoint)
637 {
638 gl_debug (DEBUG_LABEL, "START");
639
640 g_return_if_fail (label && GL_IS_LABEL (label));
641
642 if (rotate_flag != label->priv->rotate_flag)
643 {
644 if ( checkpoint )
645 {
646 gl_label_checkpoint (label, _("Label properties"));
647 }
648
649 label->priv->rotate_flag = rotate_flag;
650
651 do_modify (label);
652 g_signal_emit (G_OBJECT(label), signals[SIZE_CHANGED], 0);
653 }
654
655 gl_debug (DEBUG_LABEL, "END");
656 }
657
658
659 /****************************************************************************/
660 /* Get rotate flag. */
661 /****************************************************************************/
662 gboolean
gl_label_get_rotate_flag(glLabel * label)663 gl_label_get_rotate_flag (glLabel *label)
664 {
665 return label->priv->rotate_flag;
666 }
667
668
669 /****************************************************************************/
670 /* Get label size. */
671 /****************************************************************************/
672 void
gl_label_get_size(glLabel * label,gdouble * w,gdouble * h)673 gl_label_get_size (glLabel *label,
674 gdouble *w,
675 gdouble *h)
676 {
677 lglTemplate *template;
678 const lglTemplateFrame *frame;
679
680 gl_debug (DEBUG_LABEL, "START");
681
682 g_return_if_fail (label && GL_IS_LABEL (label));
683
684 template = label->priv->template;
685 if ( !template )
686 {
687 gl_debug (DEBUG_LABEL, "END -- template NULL");
688 *w = *h = 0;
689 return;
690 }
691 frame = (lglTemplateFrame *)template->frames->data;
692
693 if (!label->priv->rotate_flag)
694 {
695 lgl_template_frame_get_size (frame, w, h);
696 }
697 else
698 {
699 lgl_template_frame_get_size (frame, h, w);
700 }
701
702 gl_debug (DEBUG_LABEL, "END");
703 }
704
705
706 /****************************************************************************/
707 /* get string with info about dimensions */
708 /****************************************************************************/
709 gchar *
gl_label_get_dimensions_string(glLabel * label)710 gl_label_get_dimensions_string (glLabel *label)
711 {
712 gchar *dims;
713 lglTemplate *template;
714 const lglTemplateFrame *frame;
715 lglUnits units;
716 gdouble units_per_point;
717 gchar *s1 = NULL;
718 gchar *s2 = NULL;
719 gchar *s3 = NULL;
720
721 gl_debug (DEBUG_LABEL, "START");
722
723 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
724
725 template = label->priv->template;
726 if (!template)
727 return g_strdup("");
728 frame = (lglTemplateFrame *)template->frames->data;
729 units = gl_prefs_model_get_units (gl_prefs);
730 units_per_point = lgl_units_get_units_per_point (units);
731
732 switch (frame->shape)
733 {
734 case LGL_TEMPLATE_FRAME_SHAPE_RECT:
735 if (units == LGL_UNITS_INCH)
736 {
737 s1 = lgl_str_format_fraction (frame->rect.w*units_per_point);
738 s2 = lgl_str_format_fraction (frame->rect.h*units_per_point);
739 s3 = lgl_str_format_fraction (frame->rect.r*units_per_point);
740 }
741 else
742 {
743 s1 = g_strdup_printf ("%.5g", frame->rect.w*units_per_point);
744 s2 = g_strdup_printf ("%.5g", frame->rect.h*units_per_point);
745 s3 = g_strdup_printf ("%.5g", frame->rect.r*units_per_point);
746 }
747 if (frame->rect.r == 0)
748 /*Translators: A rectangular label dimensions. first param is numeric value*/
749 /* of width, second is numeric value of height and third is unit. Example:*/
750 /*"60 × 22.5 mm (width / height)"*/
751 dims = g_strdup_printf (_("%s × %s %s (width × height)"),
752 s1, s2, lgl_units_get_name (units));
753 else
754 /*Translators: A rounded rectangular label dimensions. first param is numeric*/
755 /*value of width, second is numeric value of height, third is numeric value*/
756 /*of round and fourth is unit. Example:*/
757 /*"50 × 30 / 1.5 mm (width × height / round)"*/
758 dims = g_strdup_printf (_("%s × %s / %s %s (width × height / round)"),
759 s1, s2, s3, lgl_units_get_name (units));
760 break;
761
762 case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
763 if (units == LGL_UNITS_INCH)
764 {
765 s1 = lgl_str_format_fraction (frame->ellipse.w*units_per_point);
766 s2 = lgl_str_format_fraction (frame->ellipse.h*units_per_point);
767 }
768 else
769 {
770 s1 = g_strdup_printf ("%.5g", frame->ellipse.w*units_per_point);
771 s2 = g_strdup_printf ("%.5g", frame->ellipse.h*units_per_point);
772 }
773 /*Translators: A elliptical label dimensions. first param is numeric value of*/
774 /*width, second is numeric value of height and third is unit. Example:*/
775 /*"60 × 22.5 mm (width / height)"*/
776 dims = g_strdup_printf (_("%s × %s %s (width × height)"),
777 s1, s2, lgl_units_get_name (units));
778 break;
779
780 case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
781 if (units == LGL_UNITS_INCH)
782 s1 = lgl_str_format_fraction (2*frame->round.r*units_per_point);
783 else
784 s1 = g_strdup_printf ("%.5g", 2*frame->round.r*units_per_point);
785 /*Translators: A round label dimensions. first param is numeric value of*/
786 /*diameter and second is unit. Example:*/
787 /*"120.5 mm (diameter)"*/
788 dims = g_strdup_printf (_("%s %s (diameter)"),
789 s1, lgl_units_get_name (units));
790 break;
791
792 case LGL_TEMPLATE_FRAME_SHAPE_CD:
793 if (units == LGL_UNITS_INCH)
794 {
795 s1 = lgl_str_format_fraction (2*frame->cd.r1*units_per_point);
796 s2 = lgl_str_format_fraction (2*frame->cd.r2*units_per_point);
797 }
798 else
799 {
800 s1 = g_strdup_printf ("%.5g", 2*frame->cd.r1*units_per_point);
801 s2 = g_strdup_printf ("%.5g", 2*frame->cd.r2*units_per_point);
802 }
803 /*Translators: A CD/DVD label dimensions. first param is numeric value of*/
804 /*diameter, second is numeric value of hole and third is unit. Example:*/
805 /*"120.5 / 30 mm (diameter / hole)"*/
806 dims = g_strdup_printf (_("%s / %s %s (diameter / hole)"),
807 s1, s2, lgl_units_get_name (units));
808 break;
809 }
810
811 g_free (s1);
812 g_free (s2);
813 g_free (s3);
814
815 gl_debug (DEBUG_LABEL, "END");
816
817 return dims;
818 }
819
820
821 /****************************************************************************/
822 /* set merge information structure. */
823 /****************************************************************************/
824 void
gl_label_set_merge(glLabel * label,glMerge * merge,gboolean checkpoint)825 gl_label_set_merge (glLabel *label,
826 glMerge *merge,
827 gboolean checkpoint)
828 {
829 gl_debug (DEBUG_LABEL, "START");
830
831 g_return_if_fail (label && GL_IS_LABEL (label));
832
833 if ( checkpoint )
834 {
835 gl_label_checkpoint (label, _("Merge properties"));
836 }
837
838 if ( label->priv->merge != NULL )
839 {
840 g_object_unref (G_OBJECT(label->priv->merge));
841 }
842 label->priv->merge = gl_merge_dup (merge);
843
844 do_modify (label);
845 g_signal_emit (G_OBJECT(label), signals[MERGE_CHANGED], 0);
846
847 gl_debug (DEBUG_LABEL, "END");
848 }
849
850
851 /****************************************************************************/
852 /* Get merge information structure. */
853 /****************************************************************************/
854 glMerge *
gl_label_get_merge(glLabel * label)855 gl_label_get_merge (glLabel *label)
856 {
857 gl_debug (DEBUG_LABEL, "START");
858
859 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
860
861 gl_debug (DEBUG_LABEL, "END");
862
863 return gl_merge_dup (label->priv->merge);
864 }
865
866
867 /****************************************************************************/
868 /* Get pixbuf cache. */
869 /****************************************************************************/
870 GHashTable *
gl_label_get_pixbuf_cache(glLabel * label)871 gl_label_get_pixbuf_cache (glLabel *label)
872 {
873 return label->priv->pixbuf_cache;
874 }
875
876
877 /****************************************************************************/
878 /* Get svg cache. */
879 /****************************************************************************/
880 GHashTable *
gl_label_get_svg_cache(glLabel * label)881 gl_label_get_svg_cache (glLabel *label)
882 {
883 return label->priv->svg_cache;
884 }
885
886
887 /*****************************************************************************/
888 /* Add object to label. */
889 /*****************************************************************************/
890 void
gl_label_add_object(glLabel * label,glLabelObject * object)891 gl_label_add_object (glLabel *label,
892 glLabelObject *object)
893 {
894 gl_debug (DEBUG_LABEL, "START");
895
896 g_return_if_fail (label && GL_IS_LABEL (label));
897 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
898
899 gl_label_object_set_parent (object, label);
900 label->priv->object_list = g_list_append (label->priv->object_list, object);
901
902 g_signal_connect (G_OBJECT (object), "changed",
903 G_CALLBACK (object_changed_cb), label);
904 g_signal_connect (G_OBJECT (object), "moved",
905 G_CALLBACK (object_moved_cb), label);
906
907 do_modify (label);
908
909 gl_debug (DEBUG_LABEL, "END");
910 }
911
912
913 /*****************************************************************************/
914 /* Delete object from label. */
915 /*****************************************************************************/
916 void
gl_label_delete_object(glLabel * label,glLabelObject * object)917 gl_label_delete_object (glLabel *label,
918 glLabelObject *object)
919 {
920 gl_debug (DEBUG_LABEL, "START");
921
922 g_return_if_fail (label && GL_IS_LABEL (label));
923 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
924
925 label->priv->object_list = g_list_remove (label->priv->object_list, object);
926
927 g_signal_handlers_disconnect_by_func (G_OBJECT (object),
928 G_CALLBACK (object_changed_cb), label);
929 g_signal_handlers_disconnect_by_func (G_OBJECT (object),
930 G_CALLBACK (object_moved_cb), label);
931 g_object_unref (object);
932
933 do_modify (label);
934
935 gl_debug (DEBUG_LABEL, "END");
936 }
937
938
939 /*****************************************************************************/
940 /* Get object list. */
941 /*****************************************************************************/
942 const GList *
gl_label_get_object_list(glLabel * label)943 gl_label_get_object_list (glLabel *label)
944 {
945 return label->priv->object_list;
946 }
947
948
949 /*****************************************************************************/
950 /* Select object. */
951 /*****************************************************************************/
952 void
gl_label_select_object(glLabel * label,glLabelObject * object)953 gl_label_select_object (glLabel *label,
954 glLabelObject *object)
955 {
956 gl_debug (DEBUG_LABEL, "START");
957
958 g_return_if_fail (label && GL_IS_LABEL (label));
959 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
960
961 gl_label_object_select (object);
962
963 label->priv->cp_cleared_flag = TRUE;
964 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
965
966 gl_debug (DEBUG_LABEL, "END");
967 }
968
969
970 /*****************************************************************************/
971 /* Unselect object. */
972 /*****************************************************************************/
973 void
gl_label_unselect_object(glLabel * label,glLabelObject * object)974 gl_label_unselect_object (glLabel *label,
975 glLabelObject *object)
976 {
977 gl_debug (DEBUG_LABEL, "START");
978
979 g_return_if_fail (label && GL_IS_LABEL (label));
980 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
981
982 gl_label_object_unselect (object);
983
984 label->priv->cp_cleared_flag = TRUE;
985 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
986
987 gl_debug (DEBUG_LABEL, "END");
988 }
989
990
991 /*****************************************************************************/
992 /* Select all objects. */
993 /*****************************************************************************/
994 void
gl_label_select_all(glLabel * label)995 gl_label_select_all (glLabel *label)
996 {
997 GList *p;
998 glLabelObject *object;
999
1000 gl_debug (DEBUG_LABEL, "START");
1001
1002 g_return_if_fail (label && GL_IS_LABEL (label));
1003
1004 for ( p = label->priv->object_list; p != NULL; p = p->next )
1005 {
1006 object = GL_LABEL_OBJECT (p->data);
1007
1008 gl_label_object_select (object);
1009 }
1010
1011 label->priv->cp_cleared_flag = TRUE;
1012 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
1013
1014 gl_debug (DEBUG_LABEL, "END");
1015 }
1016
1017
1018 /*****************************************************************************/
1019 /* Unselect all objects. */
1020 /*****************************************************************************/
1021 void
gl_label_unselect_all(glLabel * label)1022 gl_label_unselect_all (glLabel *label)
1023 {
1024 GList *p;
1025 glLabelObject *object;
1026
1027 gl_debug (DEBUG_LABEL, "START");
1028
1029 g_return_if_fail (label && GL_IS_LABEL (label));
1030
1031 for ( p = label->priv->object_list; p != NULL; p = p->next )
1032 {
1033 object = GL_LABEL_OBJECT (p->data);
1034
1035 gl_label_object_unselect (object);
1036 }
1037
1038 label->priv->cp_cleared_flag = TRUE;
1039 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
1040
1041 gl_debug (DEBUG_LABEL, "END");
1042 }
1043
1044
1045 /*****************************************************************************/
1046 /* Select all objects contained in region. */
1047 /*****************************************************************************/
1048 void
gl_label_select_region(glLabel * label,glLabelRegion * region)1049 gl_label_select_region (glLabel *label,
1050 glLabelRegion *region)
1051 {
1052 GList *p;
1053 glLabelObject *object;
1054 gdouble r_x1, r_y1;
1055 gdouble r_x2, r_y2;
1056 glLabelRegion obj_extent;
1057
1058 gl_debug (DEBUG_LABEL, "START");
1059
1060 g_return_if_fail (label && GL_IS_LABEL (label));
1061
1062 r_x1 = MIN (region->x1, region->x2);
1063 r_y1 = MIN (region->y1, region->y2);
1064 r_x2 = MAX (region->x1, region->x2);
1065 r_y2 = MAX (region->y1, region->y2);
1066
1067 for (p = label->priv->object_list; p != NULL; p = p->next)
1068 {
1069 object = GL_LABEL_OBJECT(p->data);
1070
1071 gl_label_object_get_extent (object, &obj_extent);
1072 if ((obj_extent.x1 >= r_x1) &&
1073 (obj_extent.x2 <= r_x2) &&
1074 (obj_extent.y1 >= r_y1) &&
1075 (obj_extent.y2 <= r_y2))
1076 {
1077 gl_label_object_select (object);
1078 }
1079 }
1080
1081 label->priv->cp_cleared_flag = TRUE;
1082 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
1083
1084 gl_debug (DEBUG_LABEL, "END");
1085 }
1086
1087
1088 /*****************************************************************************/
1089 /* Is selection empty? */
1090 /*****************************************************************************/
1091 gboolean
gl_label_is_selection_empty(glLabel * label)1092 gl_label_is_selection_empty (glLabel *label)
1093 {
1094 GList *p;
1095 glLabelObject *object;
1096
1097 for ( p = label->priv->object_list; p != NULL; p = p->next )
1098 {
1099 object = GL_LABEL_OBJECT (p->data);
1100
1101 if ( gl_label_object_is_selected (object) )
1102 {
1103 return FALSE;
1104 }
1105 }
1106
1107 return TRUE;
1108 }
1109
1110
1111 /*****************************************************************************/
1112 /* Is selection atomic? */
1113 /*****************************************************************************/
1114 gboolean
gl_label_is_selection_atomic(glLabel * label)1115 gl_label_is_selection_atomic (glLabel *label)
1116 {
1117 GList *p;
1118 glLabelObject *object;
1119 gint n_selected = 0;
1120
1121 for ( p = label->priv->object_list; p != NULL; p = p->next )
1122 {
1123 object = GL_LABEL_OBJECT (p->data);
1124
1125 if ( gl_label_object_is_selected (object) )
1126 {
1127 n_selected++;
1128
1129 if (n_selected > 1)
1130 {
1131 return FALSE;
1132 }
1133 }
1134 }
1135
1136 return (n_selected == 1);
1137 }
1138
1139
1140 /*****************************************************************************/
1141 /* Get first selected object. */
1142 /*****************************************************************************/
1143 glLabelObject *
gl_label_get_1st_selected_object(glLabel * label)1144 gl_label_get_1st_selected_object (glLabel *label)
1145 {
1146 GList *p;
1147 glLabelObject *object;
1148
1149 for ( p = label->priv->object_list; p != NULL; p = p->next )
1150 {
1151 object = GL_LABEL_OBJECT (p->data);
1152
1153 if ( gl_label_object_is_selected (object) )
1154 {
1155 return object;
1156 }
1157 }
1158
1159 return NULL;
1160 }
1161
1162
1163 /*****************************************************************************/
1164 /* Get list of selected objects. */
1165 /*****************************************************************************/
1166 GList *
gl_label_get_selection_list(glLabel * label)1167 gl_label_get_selection_list (glLabel *label)
1168 {
1169 GList *selection_list = NULL;
1170 GList *p;
1171 glLabelObject *object;
1172
1173 for ( p = label->priv->object_list; p != NULL; p = p->next )
1174 {
1175 object = GL_LABEL_OBJECT (p->data);
1176
1177 if ( gl_label_object_is_selected (object) )
1178 {
1179 selection_list = g_list_append (selection_list, object);
1180 }
1181 }
1182
1183 return (selection_list);
1184 }
1185
1186
1187 /*****************************************************************************/
1188 /* Can text properties be set for selection? */
1189 /*****************************************************************************/
1190 gboolean
gl_label_can_selection_text(glLabel * label)1191 gl_label_can_selection_text (glLabel *label)
1192 {
1193 GList *selection_list;
1194 GList *p;
1195 glLabelObject *object;
1196
1197 gl_debug (DEBUG_LABEL, "");
1198
1199 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1200
1201 selection_list = gl_label_get_selection_list (label);
1202
1203 for (p = selection_list; p != NULL; p = p->next)
1204 {
1205 object = GL_LABEL_OBJECT (p->data);
1206
1207 if (gl_label_object_can_text (object))
1208 {
1209 g_list_free (selection_list);
1210 return TRUE;
1211 }
1212 }
1213
1214 g_list_free (selection_list);
1215 return FALSE;
1216 }
1217
1218
1219 /*****************************************************************************/
1220 /* Can fill properties be set for selection? */
1221 /*****************************************************************************/
1222 gboolean
gl_label_can_selection_fill(glLabel * label)1223 gl_label_can_selection_fill (glLabel *label)
1224 {
1225 GList *selection_list;
1226 GList *p;
1227 glLabelObject *object;
1228
1229 gl_debug (DEBUG_LABEL, "");
1230
1231 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1232
1233 selection_list = gl_label_get_selection_list (label);
1234
1235 for (p = selection_list; p != NULL; p = p->next)
1236 {
1237 object = GL_LABEL_OBJECT (p->data);
1238
1239 if (gl_label_object_can_fill (object))
1240 {
1241 g_list_free (selection_list);
1242 return TRUE;
1243 }
1244
1245 }
1246
1247 g_list_free (selection_list);
1248 return FALSE;
1249 }
1250
1251
1252 /*****************************************************************************/
1253 /* Can line color properties be set for selection? */
1254 /*****************************************************************************/
1255 gboolean
gl_label_can_selection_line_color(glLabel * label)1256 gl_label_can_selection_line_color (glLabel *label)
1257 {
1258 GList *selection_list;
1259 GList *p;
1260 glLabelObject *object;
1261
1262 gl_debug (DEBUG_LABEL, "");
1263
1264 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1265
1266 selection_list = gl_label_get_selection_list (label);
1267
1268 for (p = selection_list; p != NULL; p = p->next)
1269 {
1270 object = GL_LABEL_OBJECT (p->data);
1271
1272 if (gl_label_object_can_line_color (object))
1273 {
1274 g_list_free (selection_list);
1275 return TRUE;
1276 }
1277 }
1278
1279 g_list_free (selection_list);
1280 return FALSE;
1281 }
1282
1283
1284 /*****************************************************************************/
1285 /* Can line width properties be set for selection? */
1286 /*****************************************************************************/
1287 gboolean
gl_label_can_selection_line_width(glLabel * label)1288 gl_label_can_selection_line_width (glLabel *label)
1289 {
1290 GList *selection_list;
1291 GList *p;
1292 glLabelObject *object;
1293
1294 gl_debug (DEBUG_LABEL, "");
1295
1296 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
1297
1298 selection_list = gl_label_get_selection_list (label);
1299
1300 for (p = selection_list; p != NULL; p = p->next)
1301 {
1302 object = GL_LABEL_OBJECT (p->data);
1303
1304 if (gl_label_object_can_line_width (object))
1305 {
1306 g_list_free (selection_list);
1307 return TRUE;
1308 }
1309
1310 }
1311
1312 g_list_free (selection_list);
1313 return FALSE;
1314 }
1315
1316
1317 /*****************************************************************************/
1318 /* Delete selection from label. */
1319 /*****************************************************************************/
1320 void
gl_label_delete_selection(glLabel * label)1321 gl_label_delete_selection (glLabel *label)
1322 {
1323 GList *selection_list;
1324 GList *p;
1325 glLabelObject *object;
1326
1327 gl_debug (DEBUG_LABEL, "START");
1328
1329 g_return_if_fail (label && GL_IS_LABEL (label));
1330
1331 gl_label_checkpoint (label, _("Delete"));
1332
1333 begin_selection_op (label);
1334
1335 selection_list = gl_label_get_selection_list (label);
1336
1337 for ( p = selection_list; p != NULL; p = p->next )
1338 {
1339 object = GL_LABEL_OBJECT (p->data);
1340
1341 gl_label_delete_object (label, object);
1342 }
1343
1344 g_list_free (selection_list);
1345
1346 end_selection_op (label);
1347
1348 g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
1349
1350 gl_debug (DEBUG_LABEL, "END");
1351 }
1352
1353
1354 /****************************************************************************/
1355 /* Bring selection object to front/top. */
1356 /****************************************************************************/
1357 void
gl_label_raise_selection_to_top(glLabel * label)1358 gl_label_raise_selection_to_top (glLabel *label)
1359 {
1360 GList *selection_list;
1361 GList *p;
1362 glLabelObject *object;
1363
1364 gl_debug (DEBUG_LABEL, "START");
1365
1366 gl_label_checkpoint (label, _("Bring to front"));
1367
1368 begin_selection_op (label);
1369
1370 selection_list = gl_label_get_selection_list (label);
1371
1372 for ( p = selection_list; p != NULL; p = p->next )
1373 {
1374 object = GL_LABEL_OBJECT (p->data);
1375
1376 label->priv->object_list = g_list_remove (label->priv->object_list, object);
1377 }
1378
1379 /* Move to end of list, representing front most object */
1380 label->priv->object_list = g_list_concat (label->priv->object_list, selection_list);
1381
1382 do_modify (label);
1383
1384 end_selection_op (label);
1385
1386 gl_debug (DEBUG_LABEL, "END");
1387 }
1388
1389
1390 /****************************************************************************/
1391 /* Send selection to rear/bottom. */
1392 /****************************************************************************/
1393 void
gl_label_lower_selection_to_bottom(glLabel * label)1394 gl_label_lower_selection_to_bottom (glLabel *label)
1395 {
1396 GList *selection_list;
1397 GList *p;
1398 glLabelObject *object;
1399
1400 gl_debug (DEBUG_LABEL, "START");
1401
1402 gl_label_checkpoint (label, _("Send to back"));
1403
1404 begin_selection_op (label);
1405
1406 selection_list = gl_label_get_selection_list (label);
1407
1408 for ( p = selection_list; p != NULL; p = p->next )
1409 {
1410 object = GL_LABEL_OBJECT (p->data);
1411
1412 label->priv->object_list = g_list_remove (label->priv->object_list, object);
1413 }
1414
1415 /* Move to front of list, representing rear most object */
1416 label->priv->object_list = g_list_concat (selection_list, label->priv->object_list);
1417
1418 do_modify (label);
1419
1420 end_selection_op (label);
1421
1422 gl_debug (DEBUG_LABEL, "END");
1423 }
1424
1425
1426 /*****************************************************************************/
1427 /* Rotate selected objects by given angle. */
1428 /*****************************************************************************/
1429 void
gl_label_rotate_selection(glLabel * label,gdouble theta_degs)1430 gl_label_rotate_selection (glLabel *label,
1431 gdouble theta_degs)
1432 {
1433 GList *selection_list;
1434 GList *p;
1435 glLabelObject *object;
1436
1437 gl_debug (DEBUG_LABEL, "START");
1438
1439 g_return_if_fail (label && GL_IS_LABEL (label));
1440
1441 begin_selection_op (label);
1442
1443 gl_label_checkpoint (label, _("Rotate"));
1444
1445 selection_list = gl_label_get_selection_list (label);
1446
1447 for ( p = selection_list; p != NULL; p = p->next )
1448 {
1449 object = GL_LABEL_OBJECT (p->data);
1450
1451 gl_label_object_rotate (object, theta_degs);
1452 }
1453
1454 g_list_free (selection_list);
1455
1456 do_modify (label);
1457
1458 end_selection_op (label);
1459
1460 gl_debug (DEBUG_LABEL, "END");
1461 }
1462
1463
1464 /*****************************************************************************/
1465 /* Rotate selected objects 90 degrees left. */
1466 /*****************************************************************************/
1467 void
gl_label_rotate_selection_left(glLabel * label)1468 gl_label_rotate_selection_left (glLabel *label)
1469 {
1470 GList *selection_list;
1471 GList *p;
1472 glLabelObject *object;
1473
1474 gl_debug (DEBUG_LABEL, "START");
1475
1476 g_return_if_fail (label && GL_IS_LABEL (label));
1477
1478 begin_selection_op (label);
1479
1480 gl_label_checkpoint (label, _("Rotate left"));
1481
1482 selection_list = gl_label_get_selection_list (label);
1483
1484 for ( p = selection_list; p != NULL; p = p->next )
1485 {
1486 object = GL_LABEL_OBJECT (p->data);
1487
1488 gl_label_object_rotate (object, -90.0);
1489 }
1490
1491 g_list_free (selection_list);
1492
1493 do_modify (label);
1494
1495 end_selection_op (label);
1496
1497 gl_debug (DEBUG_LABEL, "END");
1498 }
1499
1500
1501 /*****************************************************************************/
1502 /* Rotate selected objects 90 degrees right. */
1503 /*****************************************************************************/
1504 void
gl_label_rotate_selection_right(glLabel * label)1505 gl_label_rotate_selection_right (glLabel *label)
1506 {
1507 GList *selection_list;
1508 GList *p;
1509 glLabelObject *object;
1510
1511 gl_debug (DEBUG_LABEL, "START");
1512
1513 g_return_if_fail (label && GL_IS_LABEL (label));
1514
1515 gl_label_checkpoint (label, _("Rotate right"));
1516
1517 begin_selection_op (label);
1518
1519 selection_list = gl_label_get_selection_list (label);
1520
1521 for ( p = selection_list; p != NULL; p = p->next )
1522 {
1523 object = GL_LABEL_OBJECT (p->data);
1524
1525 gl_label_object_rotate (object, 90.0);
1526 }
1527
1528 g_list_free (selection_list);
1529
1530 do_modify (label);
1531
1532 end_selection_op (label);
1533
1534 gl_debug (DEBUG_LABEL, "END");
1535 }
1536
1537
1538 /*****************************************************************************/
1539 /* Flip selected objects horizontally. */
1540 /*****************************************************************************/
1541 void
gl_label_flip_selection_horiz(glLabel * label)1542 gl_label_flip_selection_horiz (glLabel *label)
1543 {
1544 GList *selection_list;
1545 GList *p;
1546 glLabelObject *object;
1547
1548 gl_debug (DEBUG_LABEL, "START");
1549
1550 g_return_if_fail (label && GL_IS_LABEL (label));
1551
1552 gl_label_checkpoint (label, _("Flip horizontally"));
1553
1554 begin_selection_op (label);
1555
1556 selection_list = gl_label_get_selection_list (label);
1557
1558 for ( p = selection_list; p != NULL; p = p->next )
1559 {
1560 object = GL_LABEL_OBJECT (p->data);
1561
1562 gl_label_object_flip_horiz (object);
1563 }
1564
1565 g_list_free (selection_list);
1566
1567 do_modify (label);
1568
1569 end_selection_op (label);
1570
1571 gl_debug (DEBUG_LABEL, "END");
1572 }
1573
1574
1575 /*****************************************************************************/
1576 /* Flip selected objects vertically. */
1577 /*****************************************************************************/
1578 void
gl_label_flip_selection_vert(glLabel * label)1579 gl_label_flip_selection_vert (glLabel *label)
1580 {
1581 GList *selection_list;
1582 GList *p;
1583 glLabelObject *object;
1584
1585 gl_debug (DEBUG_LABEL, "START");
1586
1587 g_return_if_fail (label && GL_IS_LABEL (label));
1588
1589 gl_label_checkpoint (label, _("Flip vertically"));
1590
1591 begin_selection_op (label);
1592
1593 selection_list = gl_label_get_selection_list (label);
1594
1595 for ( p = selection_list; p != NULL; p = p->next )
1596 {
1597 object = GL_LABEL_OBJECT (p->data);
1598
1599 gl_label_object_flip_vert (object);
1600 }
1601
1602 g_list_free (selection_list);
1603
1604 do_modify (label);
1605
1606 end_selection_op (label);
1607
1608 gl_debug (DEBUG_LABEL, "END");
1609 }
1610
1611
1612 /*****************************************************************************/
1613 /* Align selected objects to left most edge. */
1614 /*****************************************************************************/
1615 void
gl_label_align_selection_left(glLabel * label)1616 gl_label_align_selection_left (glLabel *label)
1617 {
1618 GList *selection_list;
1619 GList *p;
1620 glLabelObject *object;
1621 gdouble dx, x1_min;
1622 glLabelRegion obj_extent;
1623
1624 gl_debug (DEBUG_LABEL, "START");
1625
1626 g_return_if_fail (label && GL_IS_LABEL (label));
1627
1628 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1629 !gl_label_is_selection_atomic (label));
1630
1631 gl_label_checkpoint (label, _("Align left"));
1632
1633 begin_selection_op (label);
1634
1635 selection_list = gl_label_get_selection_list (label);
1636
1637 /* find left most edge */
1638 p = selection_list;
1639 object = GL_LABEL_OBJECT (p->data);
1640
1641 gl_label_object_get_extent (object, &obj_extent);
1642 x1_min = obj_extent.x1;
1643 for (p = p->next; p != NULL; p = p->next)
1644 {
1645 object = GL_LABEL_OBJECT (p->data);
1646
1647 gl_label_object_get_extent (object, &obj_extent);
1648 if ( obj_extent.x1 < x1_min ) x1_min = obj_extent.x1;
1649 }
1650
1651 /* now adjust the object positions to line up the left edges */
1652 for (p = selection_list; p != NULL; p = p->next)
1653 {
1654 object = GL_LABEL_OBJECT (p->data);
1655
1656 gl_label_object_get_extent (object, &obj_extent);
1657 dx = x1_min - obj_extent.x1;
1658 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1659 }
1660
1661 g_list_free (selection_list);
1662
1663 end_selection_op (label);
1664
1665 gl_debug (DEBUG_LABEL, "END");
1666 }
1667
1668
1669 /*****************************************************************************/
1670 /* Align selected objects to right most edge. */
1671 /*****************************************************************************/
1672 void
gl_label_align_selection_right(glLabel * label)1673 gl_label_align_selection_right (glLabel *label)
1674 {
1675 GList *selection_list;
1676 GList *p;
1677 glLabelObject *object;
1678 gdouble dx, x2_max;
1679 glLabelRegion obj_extent;
1680
1681 gl_debug (DEBUG_LABEL, "START");
1682
1683 g_return_if_fail (label && GL_IS_LABEL (label));
1684
1685 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1686 !gl_label_is_selection_atomic (label));
1687
1688 gl_label_checkpoint (label, _("Align right"));
1689
1690 begin_selection_op (label);
1691
1692 selection_list = gl_label_get_selection_list (label);
1693
1694 /* find left most edge */
1695 p = selection_list;
1696 object = GL_LABEL_OBJECT (p->data);
1697
1698 gl_label_object_get_extent (object, &obj_extent);
1699 x2_max = obj_extent.x2;
1700 for (p = p->next; p != NULL; p = p->next)
1701 {
1702 object = GL_LABEL_OBJECT (p->data);
1703
1704 gl_label_object_get_extent (object, &obj_extent);
1705 if ( obj_extent.x2 > x2_max ) x2_max = obj_extent.x2;
1706 }
1707
1708 /* now adjust the object positions to line up the left edges */
1709 for (p = selection_list; p != NULL; p = p->next)
1710 {
1711 object = GL_LABEL_OBJECT (p->data);
1712
1713 gl_label_object_get_extent (object, &obj_extent);
1714 dx = x2_max - obj_extent.x2;
1715 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1716 }
1717
1718 g_list_free (selection_list);
1719
1720 end_selection_op (label);
1721
1722 gl_debug (DEBUG_LABEL, "END");
1723 }
1724
1725
1726 /*****************************************************************************/
1727 /* Align selected objects to horizontal center of objects. */
1728 /*****************************************************************************/
1729 void
gl_label_align_selection_hcenter(glLabel * label)1730 gl_label_align_selection_hcenter (glLabel *label)
1731 {
1732 GList *selection_list;
1733 GList *p;
1734 glLabelObject *object;
1735 gdouble dx;
1736 gdouble dxmin;
1737 gdouble xsum, xavg;
1738 glLabelRegion obj_extent;
1739 gdouble xcenter;
1740 gint n;
1741
1742 gl_debug (DEBUG_LABEL, "START");
1743
1744 g_return_if_fail (label && GL_IS_LABEL (label));
1745
1746 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1747 !gl_label_is_selection_atomic (label));
1748
1749 gl_label_checkpoint (label, _("Align horizontal center"));
1750
1751 begin_selection_op (label);
1752
1753 selection_list = gl_label_get_selection_list (label);
1754
1755 /* find average center of objects */
1756 xsum = 0.0;
1757 n = 0;
1758 for (p = selection_list; p != NULL; p = p->next)
1759 {
1760 object = GL_LABEL_OBJECT (p->data);
1761
1762 gl_label_object_get_extent (object, &obj_extent);
1763 xsum += (obj_extent.x1 + obj_extent.x2) / 2.0;
1764 n++;
1765 }
1766 xavg = xsum / n;
1767
1768 /* find center of object closest to average center */
1769 p = selection_list;
1770 object = GL_LABEL_OBJECT (p->data);
1771
1772 gl_label_object_get_extent (object, &obj_extent);
1773 dxmin = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1774 xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1775 for (p = p->next; p != NULL; p = p->next)
1776 {
1777 object = GL_LABEL_OBJECT (p->data);
1778
1779 gl_label_object_get_extent (object, &obj_extent);
1780 dx = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
1781 if ( dx < dxmin )
1782 {
1783 dxmin = dx;
1784 xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
1785 }
1786 }
1787
1788 /* now adjust the object positions to line up this center */
1789 for (p = selection_list; p != NULL; p = p->next)
1790 {
1791 object = GL_LABEL_OBJECT (p->data);
1792
1793 gl_label_object_get_extent (object, &obj_extent);
1794 dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
1795 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
1796 }
1797
1798 g_list_free (selection_list);
1799
1800 end_selection_op (label);
1801
1802 gl_debug (DEBUG_LABEL, "END");
1803 }
1804
1805
1806 /*****************************************************************************/
1807 /* Align selected objects to top most edge. */
1808 /*****************************************************************************/
1809 void
gl_label_align_selection_top(glLabel * label)1810 gl_label_align_selection_top (glLabel *label)
1811 {
1812 GList *selection_list;
1813 GList *p;
1814 glLabelObject *object;
1815 gdouble dy, y1_min;
1816 glLabelRegion obj_extent;
1817
1818 gl_debug (DEBUG_LABEL, "START");
1819
1820 g_return_if_fail (label && GL_IS_LABEL (label));
1821
1822 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1823 !gl_label_is_selection_atomic (label));
1824
1825 gl_label_checkpoint (label, _("Align tops"));
1826
1827 begin_selection_op (label);
1828
1829 selection_list = gl_label_get_selection_list (label);
1830
1831 /* find top most edge */
1832 p = selection_list;
1833 object = GL_LABEL_OBJECT (p->data);
1834
1835 gl_label_object_get_extent (object, &obj_extent);
1836 y1_min = obj_extent.y1;
1837 for (p = p->next; p != NULL; p = p->next)
1838 {
1839 object = GL_LABEL_OBJECT (p->data);
1840
1841 gl_label_object_get_extent (object, &obj_extent);
1842 if ( obj_extent.y1 < y1_min ) y1_min = obj_extent.y1;
1843 }
1844
1845 /* now adjust the object positions to line up the top edges */
1846 for (p = selection_list; p != NULL; p = p->next)
1847 {
1848 object = GL_LABEL_OBJECT (p->data);
1849
1850 gl_label_object_get_extent (object, &obj_extent);
1851 dy = y1_min - obj_extent.y1;
1852 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1853 }
1854
1855 g_list_free (selection_list);
1856
1857 end_selection_op (label);
1858
1859 gl_debug (DEBUG_LABEL, "END");
1860 }
1861
1862
1863 /*****************************************************************************/
1864 /* Align selected objects to bottom most edge. */
1865 /*****************************************************************************/
1866 void
gl_label_align_selection_bottom(glLabel * label)1867 gl_label_align_selection_bottom (glLabel *label)
1868 {
1869 GList *selection_list;
1870 GList *p;
1871 glLabelObject *object;
1872 gdouble dy, y2_max;
1873 glLabelRegion obj_extent;
1874
1875 gl_debug (DEBUG_LABEL, "START");
1876
1877 g_return_if_fail (label && GL_IS_LABEL (label));
1878
1879 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1880 !gl_label_is_selection_atomic (label));
1881
1882 gl_label_checkpoint (label, _("Align bottoms"));
1883
1884 begin_selection_op (label);
1885
1886 selection_list = gl_label_get_selection_list (label);
1887
1888 /* find bottom most edge */
1889 p = selection_list;
1890 object = GL_LABEL_OBJECT (p->data);
1891
1892 gl_label_object_get_extent (object, &obj_extent);
1893 y2_max = obj_extent.y2;
1894 for (p = p->next; p != NULL; p = p->next)
1895 {
1896 object = GL_LABEL_OBJECT (p->data);
1897
1898 gl_label_object_get_extent (object, &obj_extent);
1899 if ( obj_extent.y2 > y2_max ) y2_max = obj_extent.y2;
1900 }
1901
1902 /* now adjust the object positions to line up the bottom edges */
1903 for (p = selection_list; p != NULL; p = p->next)
1904 {
1905 object = GL_LABEL_OBJECT (p->data);
1906
1907 gl_label_object_get_extent (object, &obj_extent);
1908 dy = y2_max - obj_extent.y2;
1909 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1910 }
1911
1912 g_list_free (selection_list);
1913
1914 end_selection_op (label);
1915
1916 gl_debug (DEBUG_LABEL, "END");
1917 }
1918
1919
1920 /*****************************************************************************/
1921 /* Align selected objects to viertical center of objects. */
1922 /*****************************************************************************/
1923 void
gl_label_align_selection_vcenter(glLabel * label)1924 gl_label_align_selection_vcenter (glLabel *label)
1925 {
1926 GList *selection_list;
1927 GList *p;
1928 glLabelObject *object;
1929 gdouble dy;
1930 gdouble dymin;
1931 gdouble ysum, yavg;
1932 glLabelRegion obj_extent;
1933 gdouble ycenter;
1934 gint n;
1935
1936 gl_debug (DEBUG_LABEL, "START");
1937
1938 g_return_if_fail (label && GL_IS_LABEL (label));
1939
1940 g_return_if_fail (!gl_label_is_selection_empty (label) &&
1941 !gl_label_is_selection_atomic (label));
1942
1943 gl_label_checkpoint (label, _("Align vertical center"));
1944
1945 begin_selection_op (label);
1946
1947 selection_list = gl_label_get_selection_list (label);
1948
1949 /* find average center of objects */
1950 ysum = 0.0;
1951 n = 0;
1952 for (p = selection_list; p != NULL; p = p->next)
1953 {
1954 object = GL_LABEL_OBJECT (p->data);
1955
1956 gl_label_object_get_extent (object, &obj_extent);
1957 ysum += (obj_extent.y1 + obj_extent.y2) / 2.0;
1958 n++;
1959 }
1960 yavg = ysum / n;
1961
1962 /* find center of object closest to average center */
1963 p = selection_list;
1964 object = GL_LABEL_OBJECT (p->data);
1965
1966 gl_label_object_get_extent (object, &obj_extent);
1967 dymin = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1968 ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1969 for (p = p->next; p != NULL; p = p->next)
1970 {
1971 object = GL_LABEL_OBJECT (p->data);
1972
1973 gl_label_object_get_extent (object, &obj_extent);
1974 dy = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
1975 if ( dy < dymin )
1976 {
1977 dymin = dy;
1978 ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
1979 }
1980 }
1981
1982 /* now adjust the object positions to line up this center */
1983 for (p = selection_list; p != NULL; p = p->next)
1984 {
1985 object = GL_LABEL_OBJECT (p->data);
1986
1987 gl_label_object_get_extent (object, &obj_extent);
1988 dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
1989 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
1990 }
1991
1992 g_list_free (selection_list);
1993
1994 end_selection_op (label);
1995
1996 gl_debug (DEBUG_LABEL, "END");
1997 }
1998
1999
2000 /*****************************************************************************/
2001 /* Center selected objects to in center of label. */
2002 /*****************************************************************************/
2003 void
gl_label_center_selection_horiz(glLabel * label)2004 gl_label_center_selection_horiz (glLabel *label)
2005 {
2006 GList *selection_list;
2007 GList *p;
2008 glLabelObject *object;
2009 gdouble dx;
2010 gdouble x_label_center;
2011 gdouble x_obj_center;
2012 glLabelRegion obj_extent;
2013 gdouble w, h;
2014
2015 gl_debug (DEBUG_LABEL, "START");
2016
2017 g_return_if_fail (label && GL_IS_LABEL (label));
2018
2019 g_return_if_fail (!gl_label_is_selection_empty (label));
2020
2021 gl_label_checkpoint (label, _("Center horizontally"));
2022
2023 begin_selection_op (label);
2024
2025 gl_label_get_size (label, &w, &h);
2026 x_label_center = w / 2.0;
2027
2028 /* adjust the object positions */
2029 selection_list = gl_label_get_selection_list (label);
2030 for (p = selection_list; p != NULL; p = p->next)
2031 {
2032 object = GL_LABEL_OBJECT (p->data);
2033
2034 gl_label_object_get_extent (object, &obj_extent);
2035 x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
2036 dx = x_label_center - x_obj_center;
2037 gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
2038 }
2039 g_list_free (selection_list);
2040
2041 end_selection_op (label);
2042
2043 gl_debug (DEBUG_LABEL, "END");
2044 }
2045
2046
2047 /*****************************************************************************/
2048 /* Center selected objects to in center of label. */
2049 /*****************************************************************************/
2050 void
gl_label_center_selection_vert(glLabel * label)2051 gl_label_center_selection_vert (glLabel *label)
2052 {
2053 GList *selection_list;
2054 GList *p;
2055 glLabelObject *object;
2056 gdouble dy;
2057 gdouble y_label_center;
2058 gdouble y_obj_center;
2059 glLabelRegion obj_extent;
2060 gdouble w, h;
2061
2062 gl_debug (DEBUG_LABEL, "START");
2063
2064 g_return_if_fail (label && GL_IS_LABEL (label));
2065
2066 g_return_if_fail (!gl_label_is_selection_empty (label));
2067
2068 gl_label_checkpoint (label, _("Center vertically"));
2069
2070 begin_selection_op (label);
2071
2072 gl_label_get_size (label, &w, &h);
2073 y_label_center = h / 2.0;
2074
2075 /* adjust the object positions */
2076 selection_list = gl_label_get_selection_list (label);
2077 for (p = selection_list; p != NULL; p = p->next)
2078 {
2079 object = GL_LABEL_OBJECT (p->data);
2080
2081 gl_label_object_get_extent (object, &obj_extent);
2082 y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
2083 dy = y_label_center - y_obj_center;
2084 gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
2085 }
2086 g_list_free (selection_list);
2087
2088 end_selection_op (label);
2089
2090 gl_debug (DEBUG_LABEL, "END");
2091 }
2092
2093
2094 /*****************************************************************************/
2095 /* Move selected objects */
2096 /*****************************************************************************/
2097 void
gl_label_move_selection(glLabel * label,gdouble dx,gdouble dy)2098 gl_label_move_selection (glLabel *label,
2099 gdouble dx,
2100 gdouble dy)
2101 {
2102 GList *selection_list;
2103 GList *p;
2104 glLabelObject *object;
2105
2106 gl_debug (DEBUG_LABEL, "START");
2107
2108 g_return_if_fail (label && GL_IS_LABEL (label));
2109
2110 begin_selection_op (label);
2111
2112 selection_list = gl_label_get_selection_list (label);
2113
2114 for (p = selection_list; p != NULL; p = p->next)
2115 {
2116 object = GL_LABEL_OBJECT (p->data);
2117
2118 gl_label_object_set_position_relative (object, dx, dy, TRUE);
2119 }
2120
2121 g_list_free (selection_list);
2122
2123 end_selection_op (label);
2124
2125 gl_debug (DEBUG_LABEL, "END");
2126 }
2127
2128
2129 /*****************************************************************************/
2130 /* Set font family for all text contained in selected objects. */
2131 /*****************************************************************************/
2132 void
gl_label_set_selection_font_family(glLabel * label,const gchar * font_family)2133 gl_label_set_selection_font_family (glLabel *label,
2134 const gchar *font_family)
2135 {
2136 GList *selection_list;
2137 GList *p;
2138 glLabelObject *object;
2139
2140 gl_debug (DEBUG_LABEL, "START");
2141
2142 g_return_if_fail (label && GL_IS_LABEL (label));
2143
2144 begin_selection_op (label);
2145
2146 selection_list = gl_label_get_selection_list (label);
2147
2148 for (p = selection_list; p != NULL; p = p->next)
2149 {
2150 object = GL_LABEL_OBJECT (p->data);
2151 gl_label_object_set_font_family (object, font_family, TRUE);
2152 }
2153
2154 g_list_free (selection_list);
2155
2156 end_selection_op (label);
2157
2158 gl_debug (DEBUG_LABEL, "END");
2159 }
2160
2161
2162 /*****************************************************************************/
2163 /* Set font size for all text contained in selected objects. */
2164 /*****************************************************************************/
2165 void
gl_label_set_selection_font_size(glLabel * label,gdouble font_size)2166 gl_label_set_selection_font_size (glLabel *label,
2167 gdouble font_size)
2168 {
2169 GList *selection_list;
2170 GList *p;
2171 glLabelObject *object;
2172
2173 gl_debug (DEBUG_LABEL, "START");
2174
2175 g_return_if_fail (label && GL_IS_LABEL (label));
2176
2177 begin_selection_op (label);
2178
2179 selection_list = gl_label_get_selection_list (label);
2180
2181 for (p = selection_list; p != NULL; p = p->next)
2182 {
2183 object = GL_LABEL_OBJECT (p->data);
2184 gl_label_object_set_font_size (object, font_size, TRUE);
2185 }
2186
2187 g_list_free (selection_list);
2188
2189 end_selection_op (label);
2190
2191 gl_debug (DEBUG_LABEL, "END");
2192 }
2193
2194
2195 /*****************************************************************************/
2196 /* Set font weight for all text contained in selected objects. */
2197 /*****************************************************************************/
2198 void
gl_label_set_selection_font_weight(glLabel * label,PangoWeight font_weight)2199 gl_label_set_selection_font_weight (glLabel *label,
2200 PangoWeight font_weight)
2201 {
2202 GList *selection_list;
2203 GList *p;
2204 glLabelObject *object;
2205
2206 gl_debug (DEBUG_LABEL, "START");
2207
2208 g_return_if_fail (label && GL_IS_LABEL (label));
2209
2210 begin_selection_op (label);
2211
2212 selection_list = gl_label_get_selection_list (label);
2213
2214 for (p = selection_list; p != NULL; p = p->next)
2215 {
2216 object = GL_LABEL_OBJECT (p->data);
2217 gl_label_object_set_font_weight (object, font_weight, TRUE);
2218 }
2219
2220 g_list_free (selection_list);
2221
2222 end_selection_op (label);
2223
2224 gl_debug (DEBUG_LABEL, "END");
2225 }
2226
2227
2228 /*****************************************************************************/
2229 /* Set font italic flag for all text contained in selected objects. */
2230 /*****************************************************************************/
2231 void
gl_label_set_selection_font_italic_flag(glLabel * label,gboolean font_italic_flag)2232 gl_label_set_selection_font_italic_flag (glLabel *label,
2233 gboolean font_italic_flag)
2234 {
2235 GList *selection_list;
2236 GList *p;
2237 glLabelObject *object;
2238
2239 gl_debug (DEBUG_LABEL, "START");
2240
2241 g_return_if_fail (label && GL_IS_LABEL (label));
2242
2243 begin_selection_op (label);
2244
2245 selection_list = gl_label_get_selection_list (label);
2246
2247 for (p = selection_list; p != NULL; p = p->next)
2248 {
2249 object = GL_LABEL_OBJECT (p->data);
2250 gl_label_object_set_font_italic_flag (object, font_italic_flag, TRUE);
2251 }
2252
2253 g_list_free (selection_list);
2254
2255 end_selection_op (label);
2256
2257 gl_debug (DEBUG_LABEL, "END");
2258 }
2259
2260
2261 /*****************************************************************************/
2262 /* Set text alignment for all text contained in selected objects. */
2263 /*****************************************************************************/
2264 void
gl_label_set_selection_text_alignment(glLabel * label,PangoAlignment text_alignment)2265 gl_label_set_selection_text_alignment (glLabel *label,
2266 PangoAlignment text_alignment)
2267 {
2268 GList *selection_list;
2269 GList *p;
2270 glLabelObject *object;
2271
2272 gl_debug (DEBUG_LABEL, "START");
2273
2274 g_return_if_fail (label && GL_IS_LABEL (label));
2275
2276 begin_selection_op (label);
2277
2278 selection_list = gl_label_get_selection_list (label);
2279
2280 for (p = selection_list; p != NULL; p = p->next)
2281 {
2282 object = GL_LABEL_OBJECT (p->data);
2283 gl_label_object_set_text_alignment (object, text_alignment, TRUE);
2284 }
2285
2286 g_list_free (selection_list);
2287
2288 end_selection_op (label);
2289
2290 gl_debug (DEBUG_LABEL, "END");
2291 }
2292
2293
2294 /*****************************************************************************/
2295 /* Set vertical text alignment for all text contained in selected objects. */
2296 /*****************************************************************************/
2297 void
gl_label_set_selection_text_valignment(glLabel * label,glValignment text_valignment)2298 gl_label_set_selection_text_valignment (glLabel *label,
2299 glValignment text_valignment)
2300 {
2301 GList *selection_list;
2302 GList *p;
2303 glLabelObject *object;
2304
2305 gl_debug (DEBUG_LABEL, "START");
2306
2307 g_return_if_fail (label && GL_IS_LABEL (label));
2308
2309 begin_selection_op (label);
2310
2311 selection_list = gl_label_get_selection_list (label);
2312
2313 for (p = selection_list; p != NULL; p = p->next)
2314 {
2315 object = GL_LABEL_OBJECT (p->data);
2316 gl_label_object_set_text_valignment (object, text_valignment, TRUE);
2317 }
2318
2319 g_list_free (selection_list);
2320
2321 end_selection_op (label);
2322
2323 gl_debug (DEBUG_LABEL, "END");
2324 }
2325
2326
2327 /*****************************************************************************/
2328 /* Set text line spacing for all text contained in selected objects. */
2329 /*****************************************************************************/
2330 void
gl_label_set_selection_text_line_spacing(glLabel * label,gdouble text_line_spacing)2331 gl_label_set_selection_text_line_spacing (glLabel *label,
2332 gdouble text_line_spacing)
2333 {
2334 GList *selection_list;
2335 GList *p;
2336 glLabelObject *object;
2337
2338 gl_debug (DEBUG_LABEL, "START");
2339
2340 g_return_if_fail (label && GL_IS_LABEL (label));
2341
2342 begin_selection_op (label);
2343
2344 selection_list = gl_label_get_selection_list (label);
2345
2346 for (p = selection_list; p != NULL; p = p->next)
2347 {
2348 object = GL_LABEL_OBJECT (p->data);
2349 gl_label_object_set_text_line_spacing (object, text_line_spacing, TRUE);
2350 }
2351
2352 g_list_free (selection_list);
2353
2354 end_selection_op (label);
2355
2356 gl_debug (DEBUG_LABEL, "END");
2357 }
2358
2359
2360 /*****************************************************************************/
2361 /* Set text color for all text contained in selected objects. */
2362 /*****************************************************************************/
2363 void
gl_label_set_selection_text_color(glLabel * label,glColorNode * text_color_node)2364 gl_label_set_selection_text_color (glLabel *label,
2365 glColorNode *text_color_node)
2366 {
2367 GList *selection_list;
2368 GList *p;
2369 glLabelObject *object;
2370
2371 gl_debug (DEBUG_LABEL, "START");
2372
2373 g_return_if_fail (label && GL_IS_LABEL (label));
2374
2375 begin_selection_op (label);
2376
2377 selection_list = gl_label_get_selection_list (label);
2378
2379 for (p = selection_list; p != NULL; p = p->next)
2380 {
2381 object = GL_LABEL_OBJECT (p->data);
2382 gl_label_object_set_text_color (object, text_color_node, TRUE);
2383 }
2384
2385 g_list_free (selection_list);
2386
2387 end_selection_op (label);
2388
2389 gl_debug (DEBUG_LABEL, "END");
2390 }
2391
2392
2393 /*****************************************************************************/
2394 /* Set fill color for all selected objects. */
2395 /*****************************************************************************/
2396 void
gl_label_set_selection_fill_color(glLabel * label,glColorNode * fill_color_node)2397 gl_label_set_selection_fill_color (glLabel *label,
2398 glColorNode *fill_color_node)
2399 {
2400 GList *selection_list;
2401 GList *p;
2402 glLabelObject *object;
2403
2404 gl_debug (DEBUG_LABEL, "START");
2405
2406 g_return_if_fail (label && GL_IS_LABEL (label));
2407
2408 begin_selection_op (label);
2409
2410 selection_list = gl_label_get_selection_list (label);
2411
2412 for (p = selection_list; p != NULL; p = p->next)
2413 {
2414 object = GL_LABEL_OBJECT (p->data);
2415 gl_label_object_set_fill_color (object, fill_color_node, TRUE);
2416 }
2417
2418 g_list_free (selection_list);
2419
2420 end_selection_op (label);
2421
2422 gl_debug (DEBUG_LABEL, "END");
2423 }
2424
2425
2426 /*****************************************************************************/
2427 /* Set line color for all selected objects. */
2428 /*****************************************************************************/
2429 void
gl_label_set_selection_line_color(glLabel * label,glColorNode * line_color_node)2430 gl_label_set_selection_line_color (glLabel *label,
2431 glColorNode *line_color_node)
2432 {
2433 GList *selection_list;
2434 GList *p;
2435 glLabelObject *object;
2436
2437 gl_debug (DEBUG_LABEL, "START");
2438
2439 g_return_if_fail (label && GL_IS_LABEL (label));
2440
2441 begin_selection_op (label);
2442
2443 selection_list = gl_label_get_selection_list (label);
2444
2445 for (p = selection_list; p != NULL; p = p->next)
2446 {
2447 object = GL_LABEL_OBJECT (p->data);
2448 gl_label_object_set_line_color (object, line_color_node, TRUE);
2449 }
2450
2451 g_list_free (selection_list);
2452
2453 end_selection_op (label);
2454
2455 gl_debug (DEBUG_LABEL, "END");
2456 }
2457
2458
2459 /*****************************************************************************/
2460 /* Set line width for all selected objects. */
2461 /*****************************************************************************/
2462 void
gl_label_set_selection_line_width(glLabel * label,gdouble line_width)2463 gl_label_set_selection_line_width (glLabel *label,
2464 gdouble line_width)
2465 {
2466 GList *selection_list;
2467 GList *p;
2468 glLabelObject *object;
2469
2470 gl_debug (DEBUG_LABEL, "START");
2471
2472 g_return_if_fail (label && GL_IS_LABEL (label));
2473
2474 begin_selection_op (label);
2475
2476 selection_list = gl_label_get_selection_list (label);
2477
2478 for (p = selection_list; p != NULL; p = p->next)
2479 {
2480 object = GL_LABEL_OBJECT (p->data);
2481 gl_label_object_set_line_width (object, line_width, TRUE);
2482 }
2483
2484 g_list_free (selection_list);
2485
2486 end_selection_op (label);
2487
2488 gl_debug (DEBUG_LABEL, "END");
2489 }
2490
2491
2492 /*****************************************************************************/
2493 /* "Cut" selected items and place on clipboard. */
2494 /*****************************************************************************/
2495 void
gl_label_cut_selection(glLabel * label)2496 gl_label_cut_selection (glLabel *label)
2497 {
2498 gl_debug (DEBUG_LABEL, "START");
2499
2500 g_return_if_fail (label && GL_IS_LABEL (label));
2501
2502 gl_label_copy_selection (label);
2503 gl_label_delete_selection (label);
2504
2505 gl_debug (DEBUG_LABEL, "END");
2506 }
2507
2508
2509 /*****************************************************************************/
2510 /* "Copy" selected items to clipboard. */
2511 /*****************************************************************************/
2512 void
gl_label_copy_selection(glLabel * label)2513 gl_label_copy_selection (glLabel *label)
2514 {
2515 GtkClipboard *clipboard;
2516 GList *selection_list;
2517 glLabel *label_copy;
2518 GList *p;
2519 glLabelObject *object;
2520 glXMLLabelStatus status;
2521
2522 ClipboardData *data;
2523
2524 static GtkTargetEntry glabels_targets[] = { { "application/glabels", 0, 0 },
2525 { "text/xml", 0, 0 },
2526 };
2527
2528 GtkTargetList *target_list;
2529 GtkTargetEntry *target_table;
2530 gint n_targets;
2531
2532 gl_debug (DEBUG_LABEL, "START");
2533
2534 g_return_if_fail (label && GL_IS_LABEL (label));
2535
2536 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2537
2538 selection_list = gl_label_get_selection_list (label);
2539
2540 if (selection_list)
2541 {
2542
2543 data = g_new0 (ClipboardData, 1);
2544
2545 target_list = gtk_target_list_new (glabels_targets, G_N_ELEMENTS(glabels_targets));
2546
2547 /*
2548 * Serialize selection by encoding as an XML label document.
2549 */
2550 label_copy = GL_LABEL(gl_label_new ());
2551
2552 gl_label_set_template (label_copy, label->priv->template, FALSE);
2553 gl_label_set_rotate_flag (label_copy, label->priv->rotate_flag, FALSE);
2554
2555 for (p = selection_list; p != NULL; p = p->next)
2556 {
2557 object = GL_LABEL_OBJECT (p->data);
2558
2559 gl_label_add_object (label_copy, gl_label_object_dup (object, label_copy));
2560 }
2561
2562 data->xml_buffer = gl_xml_label_save_buffer (label_copy, &status);
2563
2564 g_object_unref (G_OBJECT (label_copy));
2565
2566
2567 /*
2568 * Is it an atomic text selection? If so, also make available as text.
2569 */
2570 if ( gl_label_is_selection_atomic (label) &&
2571 GL_IS_LABEL_TEXT (selection_list->data) )
2572 {
2573 glLabelText *text_object = GL_LABEL_TEXT (selection_list->data);
2574
2575 gtk_target_list_add_text_targets (target_list, 1);
2576
2577 data->text = gl_label_text_get_text (text_object);
2578 }
2579
2580
2581 /*
2582 * Is it an atomic image selection? If so, also make available as pixbuf.
2583 */
2584 if ( gl_label_is_selection_atomic (label) &&
2585 GL_IS_LABEL_IMAGE (selection_list->data) )
2586 {
2587 glLabelImage *image_object = GL_LABEL_IMAGE (selection_list->data);
2588 GdkPixbuf *pixbuf = gl_label_image_get_pixbuf (image_object, NULL);
2589
2590 if (pixbuf)
2591 {
2592 gtk_target_list_add_image_targets (target_list, 2, TRUE);
2593 data->pixbuf = pixbuf;
2594 }
2595 }
2596
2597
2598 target_table = gtk_target_table_new_from_list (target_list, &n_targets);
2599
2600 gtk_clipboard_set_with_data (clipboard,
2601 target_table, n_targets,
2602 (GtkClipboardGetFunc)clipboard_get_cb,
2603 (GtkClipboardClearFunc)clipboard_clear_cb,
2604 data);
2605
2606 gtk_target_table_free (target_table, n_targets);
2607 gtk_target_list_unref (target_list);
2608 }
2609
2610
2611 g_list_free (selection_list);
2612
2613 gl_debug (DEBUG_LABEL, "END");
2614 }
2615
2616
2617 /*****************************************************************************/
2618 /* "Paste" from clipboard. */
2619 /*****************************************************************************/
2620 void
gl_label_paste(glLabel * label)2621 gl_label_paste (glLabel *label)
2622 {
2623 GtkClipboard *clipboard;
2624
2625 gl_debug (DEBUG_LABEL, "START");
2626
2627 g_return_if_fail (label && GL_IS_LABEL (label));
2628
2629 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2630
2631 gtk_clipboard_request_targets (clipboard,
2632 (GtkClipboardTargetsReceivedFunc)receive_targets_cb,
2633 label);
2634
2635 gl_debug (DEBUG_LABEL, "END");
2636 }
2637
2638
2639 /*****************************************************************************/
2640 /* Is there anything that can be pasted? */
2641 /*****************************************************************************/
2642 gboolean
gl_label_can_paste(glLabel * label)2643 gl_label_can_paste (glLabel *label)
2644 {
2645 GtkClipboard *clipboard;
2646 gboolean can_flag;
2647
2648 gl_debug (DEBUG_LABEL, "START");
2649
2650 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2651
2652 can_flag = gtk_clipboard_wait_is_target_available (clipboard,
2653 gdk_atom_intern("application/glabels", TRUE))
2654 || gtk_clipboard_wait_is_text_available (clipboard)
2655 || gtk_clipboard_wait_is_image_available (clipboard);
2656
2657 gl_debug (DEBUG_LABEL, "END");
2658 return can_flag;
2659 }
2660
2661
2662 /****************************************************************************/
2663 /* Clipboard "Get" function. */
2664 /****************************************************************************/
2665 static void
clipboard_get_cb(GtkClipboard * clipboard,GtkSelectionData * selection_data,guint info,ClipboardData * data)2666 clipboard_get_cb (GtkClipboard *clipboard,
2667 GtkSelectionData *selection_data,
2668 guint info,
2669 ClipboardData *data)
2670 {
2671 gl_debug (DEBUG_LABEL, "START");
2672
2673 switch (info)
2674 {
2675
2676 case 0:
2677 gtk_selection_data_set (selection_data,
2678 gtk_selection_data_get_target (selection_data),
2679 8,
2680 (guchar *)data->xml_buffer, strlen (data->xml_buffer));
2681 break;
2682
2683 case 1:
2684 gtk_selection_data_set_text (selection_data, data->text, -1);
2685 break;
2686
2687 case 2:
2688 gtk_selection_data_set_pixbuf (selection_data, data->pixbuf);
2689 break;
2690
2691 default:
2692 g_assert_not_reached ();
2693 break;
2694
2695 }
2696
2697 gl_debug (DEBUG_LABEL, "END");
2698 }
2699
2700
2701 /****************************************************************************/
2702 /* Clipboard "Clear" function. */
2703 /****************************************************************************/
2704 static void
clipboard_clear_cb(GtkClipboard * clipboard,ClipboardData * data)2705 clipboard_clear_cb (GtkClipboard *clipboard,
2706 ClipboardData *data)
2707 {
2708 gl_debug (DEBUG_LABEL, "START");
2709
2710 g_free (data->xml_buffer);
2711 g_free (data->text);
2712 if (data->pixbuf)
2713 {
2714 g_object_unref (data->pixbuf);
2715 }
2716
2717 g_free (data);
2718
2719 gl_debug (DEBUG_LABEL, "END");
2720 }
2721
2722
2723 /****************************************************************************/
2724 /* Deal with clipboard data. */
2725 /****************************************************************************/
2726 static void
receive_targets_cb(GtkClipboard * clipboard,GdkAtom * targets,gint n_targets,glLabel * label)2727 receive_targets_cb (GtkClipboard *clipboard,
2728 GdkAtom *targets,
2729 gint n_targets,
2730 glLabel *label)
2731 {
2732 gint i;
2733
2734 /*
2735 * Application/glabels
2736 */
2737 for ( i = 0; i < n_targets; i++ )
2738 {
2739 if ( strcmp(gdk_atom_name(targets[i]), "application/glabels") == 0 )
2740 {
2741 gtk_clipboard_request_contents (clipboard,
2742 gdk_atom_intern("application/glabels", TRUE),
2743 (GtkClipboardReceivedFunc)paste_xml_received_cb,
2744 label);
2745 return;
2746 }
2747 }
2748
2749 /*
2750 * Text
2751 */
2752 if ( gtk_targets_include_text (targets, n_targets) )
2753 {
2754 gtk_clipboard_request_text (clipboard,
2755 (GtkClipboardTextReceivedFunc)paste_text_received_cb,
2756 label);
2757 return;
2758 }
2759
2760 /*
2761 * Image
2762 */
2763 if ( gtk_targets_include_image (targets, n_targets, TRUE) )
2764 {
2765 gtk_clipboard_request_image (clipboard,
2766 (GtkClipboardImageReceivedFunc)paste_image_received_cb,
2767 label);
2768 return;
2769 }
2770 }
2771
2772
2773 /****************************************************************************/
2774 /* Paste received glabels XML callback. */
2775 /****************************************************************************/
2776 static void
paste_xml_received_cb(GtkClipboard * clipboard,GtkSelectionData * selection_data,glLabel * label)2777 paste_xml_received_cb (GtkClipboard *clipboard,
2778 GtkSelectionData *selection_data,
2779 glLabel *label)
2780 {
2781 gchar *xml_buffer;
2782 glLabel *label_copy;
2783 glXMLLabelStatus status;
2784 GList *p;
2785 glLabelObject *object, *newobject;
2786
2787 gl_debug (DEBUG_LABEL, "START");
2788
2789 gl_label_checkpoint (label, _("Paste"));
2790
2791 xml_buffer = (gchar *)gtk_selection_data_get_data (selection_data);
2792
2793 /*
2794 * Deserialize XML label document and extract objects.
2795 */
2796 label_copy = gl_xml_label_open_buffer (xml_buffer, &status);
2797 if ( label_copy )
2798 {
2799 gl_label_unselect_all (label);
2800
2801 for (p = label_copy->priv->object_list; p != NULL; p = p->next)
2802 {
2803 object = (glLabelObject *) p->data;
2804 newobject = gl_label_object_dup (object, label);
2805 gl_label_add_object( label, newobject );
2806
2807 gl_label_select_object (label, newobject);
2808
2809 gl_debug (DEBUG_LABEL, "object pasted");
2810 }
2811
2812 g_object_unref (G_OBJECT (label_copy));
2813 }
2814
2815 gl_debug (DEBUG_LABEL, "END");
2816 }
2817
2818
2819 /****************************************************************************/
2820 /* Paste received text callback. */
2821 /****************************************************************************/
2822 static void
paste_text_received_cb(GtkClipboard * clipboard,const gchar * text,glLabel * label)2823 paste_text_received_cb (GtkClipboard *clipboard,
2824 const gchar *text,
2825 glLabel *label)
2826 {
2827 glLabelObject *object;
2828
2829 gl_debug (DEBUG_LABEL, "START");
2830
2831 gl_label_checkpoint (label, _("Paste"));
2832
2833 gl_label_unselect_all (label);
2834
2835 object = GL_LABEL_OBJECT (gl_label_text_new (label, FALSE));
2836 gl_label_text_set_text (GL_LABEL_TEXT (object), text, FALSE);
2837 gl_label_object_set_position (object, 18, 18, FALSE);
2838
2839 gl_label_select_object (label, object);
2840
2841 gl_debug (DEBUG_LABEL, "END");
2842 }
2843
2844
2845 /****************************************************************************/
2846 /* Paste received image callback. */
2847 /****************************************************************************/
2848 static void
paste_image_received_cb(GtkClipboard * clipboard,GdkPixbuf * pixbuf,glLabel * label)2849 paste_image_received_cb (GtkClipboard *clipboard,
2850 GdkPixbuf *pixbuf,
2851 glLabel *label)
2852 {
2853 glLabelObject *object;
2854
2855 gl_debug (DEBUG_LABEL, "START");
2856
2857 gl_label_checkpoint (label, _("Paste"));
2858
2859 gl_label_unselect_all (label);
2860
2861 object = GL_LABEL_OBJECT (gl_label_image_new (label, FALSE));
2862 gl_label_image_set_pixbuf (GL_LABEL_IMAGE (object), pixbuf, FALSE);
2863 gl_label_object_set_position (object, 18, 18, FALSE);
2864
2865 gl_label_select_object (label, object);
2866
2867 gl_debug (DEBUG_LABEL, "END");
2868 }
2869
2870
2871 /****************************************************************************/
2872 /* Set default font family. */
2873 /****************************************************************************/
2874 void
gl_label_set_default_font_family(glLabel * label,const gchar * font_family)2875 gl_label_set_default_font_family (glLabel *label,
2876 const gchar *font_family)
2877 {
2878 gl_debug (DEBUG_LABEL, "START");
2879
2880 g_return_if_fail (label && GL_IS_LABEL (label));
2881
2882 g_free (label->priv->default_font_family);
2883 label->priv->default_font_family = g_strdup (font_family);
2884
2885 gl_debug (DEBUG_LABEL, "END");
2886 }
2887
2888
2889 /****************************************************************************/
2890 /* Set default font size. */
2891 /****************************************************************************/
2892 void
gl_label_set_default_font_size(glLabel * label,gdouble font_size)2893 gl_label_set_default_font_size (glLabel *label,
2894 gdouble font_size)
2895 {
2896 gl_debug (DEBUG_LABEL, "START");
2897
2898 g_return_if_fail (label && GL_IS_LABEL (label));
2899
2900 label->priv->default_font_size = font_size;
2901
2902 gl_debug (DEBUG_LABEL, "END");
2903 }
2904
2905
2906 /****************************************************************************/
2907 /* Set default font weight. */
2908 /****************************************************************************/
2909 void
gl_label_set_default_font_weight(glLabel * label,PangoWeight font_weight)2910 gl_label_set_default_font_weight (glLabel *label,
2911 PangoWeight font_weight)
2912 {
2913 gl_debug (DEBUG_LABEL, "START");
2914
2915 g_return_if_fail (label && GL_IS_LABEL (label));
2916
2917 label->priv->default_font_weight = font_weight;
2918
2919 gl_debug (DEBUG_LABEL, "END");
2920 }
2921
2922
2923 /****************************************************************************/
2924 /* Set default font italic flag. */
2925 /****************************************************************************/
2926 void
gl_label_set_default_font_italic_flag(glLabel * label,gboolean font_italic_flag)2927 gl_label_set_default_font_italic_flag (glLabel *label,
2928 gboolean font_italic_flag)
2929 {
2930 gl_debug (DEBUG_LABEL, "START");
2931
2932 g_return_if_fail (label && GL_IS_LABEL (label));
2933
2934 label->priv->default_font_italic_flag = font_italic_flag;
2935
2936 gl_debug (DEBUG_LABEL, "END");
2937 }
2938
2939
2940 /****************************************************************************/
2941 /* Set default text color. */
2942 /****************************************************************************/
2943 void
gl_label_set_default_text_color(glLabel * label,guint text_color)2944 gl_label_set_default_text_color (glLabel *label,
2945 guint text_color)
2946 {
2947 gl_debug (DEBUG_LABEL, "START");
2948
2949 g_return_if_fail (label && GL_IS_LABEL (label));
2950
2951 label->priv->default_text_color = text_color;
2952
2953 gl_debug (DEBUG_LABEL, "END");
2954 }
2955
2956
2957 /****************************************************************************/
2958 /* Set default text alignment. */
2959 /****************************************************************************/
2960 void
gl_label_set_default_text_alignment(glLabel * label,PangoAlignment text_alignment)2961 gl_label_set_default_text_alignment (glLabel *label,
2962 PangoAlignment text_alignment)
2963 {
2964 gl_debug (DEBUG_LABEL, "START");
2965
2966 g_return_if_fail (label && GL_IS_LABEL (label));
2967
2968 label->priv->default_text_alignment = text_alignment;
2969 gl_debug (DEBUG_LABEL, "END");
2970 }
2971
2972
2973 /****************************************************************************/
2974 /* Set default vertical text alignment. */
2975 /****************************************************************************/
2976 void
gl_label_set_default_text_valignment(glLabel * label,glValignment text_valignment)2977 gl_label_set_default_text_valignment (glLabel *label,
2978 glValignment text_valignment)
2979 {
2980 gl_debug (DEBUG_LABEL, "START");
2981
2982 g_return_if_fail (label && GL_IS_LABEL (label));
2983
2984 label->priv->default_text_valignment = text_valignment;
2985 gl_debug (DEBUG_LABEL, "END");
2986 }
2987
2988
2989 /****************************************************************************/
2990 /* Set default text line spacing. */
2991 /****************************************************************************/
2992 void
gl_label_set_default_text_line_spacing(glLabel * label,gdouble text_line_spacing)2993 gl_label_set_default_text_line_spacing (glLabel *label,
2994 gdouble text_line_spacing)
2995 {
2996 gl_debug (DEBUG_LABEL, "START");
2997
2998 g_return_if_fail (label && GL_IS_LABEL (label));
2999
3000 label->priv->default_text_line_spacing = text_line_spacing;
3001
3002 gl_debug (DEBUG_LABEL, "END");
3003 }
3004
3005
3006 /****************************************************************************/
3007 /* Set default line width. */
3008 /****************************************************************************/
3009 void
gl_label_set_default_line_width(glLabel * label,gdouble line_width)3010 gl_label_set_default_line_width (glLabel *label,
3011 gdouble line_width)
3012 {
3013 gl_debug (DEBUG_LABEL, "START");
3014
3015 g_return_if_fail (label && GL_IS_LABEL (label));
3016
3017 label->priv->default_line_width = line_width;
3018
3019 gl_debug (DEBUG_LABEL, "END");
3020 }
3021
3022
3023 /****************************************************************************/
3024 /* Set default line color. */
3025 /****************************************************************************/
3026 void
gl_label_set_default_line_color(glLabel * label,guint line_color)3027 gl_label_set_default_line_color (glLabel *label,
3028 guint line_color)
3029 {
3030 gl_debug (DEBUG_LABEL, "START");
3031
3032 g_return_if_fail (label && GL_IS_LABEL (label));
3033
3034 label->priv->default_line_color = line_color;
3035
3036 gl_debug (DEBUG_LABEL, "END");
3037 }
3038
3039
3040 /****************************************************************************/
3041 /* Set default fill color. */
3042 /****************************************************************************/
3043 void
gl_label_set_default_fill_color(glLabel * label,guint fill_color)3044 gl_label_set_default_fill_color (glLabel *label,
3045 guint fill_color)
3046 {
3047 gl_debug (DEBUG_LABEL, "START");
3048
3049 g_return_if_fail (label && GL_IS_LABEL (label));
3050
3051 label->priv->default_fill_color = fill_color;
3052
3053 gl_debug (DEBUG_LABEL, "END");
3054 }
3055
3056
3057 /****************************************************************************/
3058 /* Get default font family. */
3059 /****************************************************************************/
3060 gchar *
gl_label_get_default_font_family(glLabel * label)3061 gl_label_get_default_font_family (glLabel *label)
3062 {
3063 gl_debug (DEBUG_LABEL, "START");
3064
3065 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
3066
3067 gl_debug (DEBUG_LABEL, "END");
3068
3069 return g_strdup (label->priv->default_font_family);
3070 }
3071
3072
3073 /****************************************************************************/
3074 /* Get default font size. */
3075 /****************************************************************************/
3076 gdouble
gl_label_get_default_font_size(glLabel * label)3077 gl_label_get_default_font_size (glLabel *label)
3078 {
3079 gl_debug (DEBUG_LABEL, "START");
3080
3081 g_return_val_if_fail (label && GL_IS_LABEL (label), 12.0);
3082
3083 gl_debug (DEBUG_LABEL, "END");
3084
3085 return label->priv->default_font_size;
3086 }
3087
3088
3089 /****************************************************************************/
3090 /* Get default font weight. */
3091 /****************************************************************************/
3092 PangoWeight
gl_label_get_default_font_weight(glLabel * label)3093 gl_label_get_default_font_weight (glLabel *label)
3094 {
3095 gl_debug (DEBUG_LABEL, "START");
3096
3097 g_return_val_if_fail (label && GL_IS_LABEL (label), PANGO_WEIGHT_NORMAL);
3098
3099 gl_debug (DEBUG_LABEL, "END");
3100
3101 return label->priv->default_font_weight;
3102 }
3103
3104
3105 /****************************************************************************/
3106 /* Get default font italic flag. */
3107 /****************************************************************************/
3108 gboolean
gl_label_get_default_font_italic_flag(glLabel * label)3109 gl_label_get_default_font_italic_flag (glLabel *label)
3110 {
3111 gl_debug (DEBUG_LABEL, "START");
3112
3113 g_return_val_if_fail (label && GL_IS_LABEL (label), FALSE);
3114
3115 gl_debug (DEBUG_LABEL, "END");
3116
3117 return label->priv->default_font_italic_flag;
3118 }
3119
3120
3121 /****************************************************************************/
3122 /* Get default text color. */
3123 /****************************************************************************/
3124 guint
gl_label_get_default_text_color(glLabel * label)3125 gl_label_get_default_text_color (glLabel *label)
3126 {
3127 gl_debug (DEBUG_LABEL, "START");
3128
3129 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
3130
3131 gl_debug (DEBUG_LABEL, "END");
3132
3133 return label->priv->default_text_color;
3134 }
3135
3136
3137 /****************************************************************************/
3138 /* Get default text alignment. */
3139 /****************************************************************************/
3140 PangoAlignment
gl_label_get_default_text_alignment(glLabel * label)3141 gl_label_get_default_text_alignment (glLabel *label)
3142 {
3143 gl_debug (DEBUG_LABEL, "START");
3144
3145 g_return_val_if_fail (label && GL_IS_LABEL (label), PANGO_ALIGN_LEFT);
3146
3147 gl_debug (DEBUG_LABEL, "END");
3148
3149 return label->priv->default_text_alignment;
3150 }
3151
3152
3153 /****************************************************************************/
3154 /* Get default vertical text alignment. */
3155 /****************************************************************************/
3156 glValignment
gl_label_get_default_text_valignment(glLabel * label)3157 gl_label_get_default_text_valignment (glLabel *label)
3158 {
3159 gl_debug (DEBUG_LABEL, "START");
3160
3161 g_return_val_if_fail (label && GL_IS_LABEL (label), GL_VALIGN_TOP);
3162
3163 gl_debug (DEBUG_LABEL, "END");
3164
3165 return label->priv->default_text_valignment;
3166 }
3167
3168
3169 /****************************************************************************/
3170 /* Get default text line spacing. */
3171 /****************************************************************************/
3172 gdouble
gl_label_get_default_text_line_spacing(glLabel * label)3173 gl_label_get_default_text_line_spacing (glLabel *label)
3174 {
3175 gl_debug (DEBUG_LABEL, "START");
3176
3177 g_return_val_if_fail (label && GL_IS_LABEL (label), 1.0);
3178
3179 gl_debug (DEBUG_LABEL, "END");
3180
3181 return label->priv->default_text_line_spacing;
3182 }
3183
3184
3185 /****************************************************************************/
3186 /* Get default line width. */
3187 /****************************************************************************/
3188 gdouble
gl_label_get_default_line_width(glLabel * label)3189 gl_label_get_default_line_width (glLabel *label)
3190 {
3191 gl_debug (DEBUG_LABEL, "START");
3192
3193 g_return_val_if_fail (label && GL_IS_LABEL (label), 1.0);
3194
3195 gl_debug (DEBUG_LABEL, "END");
3196
3197 return label->priv->default_line_width;
3198 }
3199
3200
3201 /****************************************************************************/
3202 /* Get default line color. */
3203 /****************************************************************************/
3204 guint
gl_label_get_default_line_color(glLabel * label)3205 gl_label_get_default_line_color (glLabel *label)
3206 {
3207 gl_debug (DEBUG_LABEL, "START");
3208
3209 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
3210
3211 gl_debug (DEBUG_LABEL, "END");
3212
3213 return label->priv->default_line_color;
3214 }
3215
3216
3217 /****************************************************************************/
3218 /* Get default fill color. */
3219 /****************************************************************************/
3220 guint
gl_label_get_default_fill_color(glLabel * label)3221 gl_label_get_default_fill_color (glLabel *label)
3222 {
3223 gl_debug (DEBUG_LABEL, "START");
3224
3225 g_return_val_if_fail (label && GL_IS_LABEL (label), 0);
3226
3227 gl_debug (DEBUG_LABEL, "END");
3228
3229 return label->priv->default_fill_color;
3230 }
3231
3232
3233 /****************************************************************************/
3234 /* Draw label. */
3235 /****************************************************************************/
3236 void
gl_label_draw(glLabel * label,cairo_t * cr,gboolean screen_flag,glMergeRecord * record)3237 gl_label_draw (glLabel *label,
3238 cairo_t *cr,
3239 gboolean screen_flag,
3240 glMergeRecord *record)
3241 {
3242 GList *p_obj;
3243 glLabelObject *object;
3244
3245 g_return_if_fail (label && GL_IS_LABEL (label));
3246
3247 for (p_obj = label->priv->object_list; p_obj != NULL; p_obj = p_obj->next)
3248 {
3249 object = GL_LABEL_OBJECT (p_obj->data);
3250
3251 gl_label_object_draw (object, cr, screen_flag, record);
3252 }
3253 }
3254
3255
3256 /****************************************************************************/
3257 /* Get object located at coordinates. */
3258 /****************************************************************************/
gl_label_object_at(glLabel * label,cairo_t * cr,gdouble x_pixels,gdouble y_pixels)3259 glLabelObject *gl_label_object_at (glLabel *label,
3260 cairo_t *cr,
3261 gdouble x_pixels,
3262 gdouble y_pixels)
3263 {
3264 GList *p_obj;
3265 glLabelObject *object;
3266
3267 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
3268
3269 for (p_obj = g_list_last (label->priv->object_list); p_obj != NULL; p_obj = p_obj->prev)
3270 {
3271 object = GL_LABEL_OBJECT (p_obj->data);
3272
3273 if (gl_label_object_is_located_at (object, cr, x_pixels, y_pixels))
3274 {
3275 return object;
3276 }
3277
3278 }
3279
3280 return NULL;
3281 }
3282
3283
3284 /****************************************************************************/
3285 /* Return handle and associated object at coordinates. */
3286 /****************************************************************************/
3287 glLabelObject *
gl_label_get_handle_at(glLabel * label,cairo_t * cr,gdouble x_pixels,gdouble y_pixels,glLabelObjectHandle * handle)3288 gl_label_get_handle_at (glLabel *label,
3289 cairo_t *cr,
3290 gdouble x_pixels,
3291 gdouble y_pixels,
3292 glLabelObjectHandle *handle)
3293 {
3294 GList *selection_list;
3295 GList *p_obj;
3296 glLabelObject *object;
3297
3298 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
3299
3300 selection_list = gl_label_get_selection_list (label);
3301
3302 for (p_obj = g_list_last (selection_list); p_obj != NULL; p_obj = p_obj->prev)
3303 {
3304
3305 object = GL_LABEL_OBJECT (p_obj->data);
3306
3307 if ((*handle = gl_label_object_handle_at (object, cr, x_pixels, y_pixels)))
3308 {
3309 g_list_free (selection_list);
3310 return object;
3311 }
3312
3313 }
3314
3315 g_list_free (selection_list);
3316
3317 *handle = GL_LABEL_OBJECT_HANDLE_NONE;
3318 return NULL;
3319 }
3320
3321
3322 /****************************************************************************/
3323 /* Checkpoint state. */
3324 /****************************************************************************/
3325 void
gl_label_checkpoint(glLabel * this,const gchar * description)3326 gl_label_checkpoint (glLabel *this,
3327 const gchar *description)
3328 {
3329 State *state;
3330
3331 gl_debug (DEBUG_LABEL, "START");
3332
3333 /*
3334 * Do not perform consecutive checkpoints that are identical.
3335 * E.g. moving an object by dragging, would produce a large number
3336 * of incremental checkpoints -- what we really want is a single
3337 * checkpoint so that we can undo the entire dragging effort with
3338 * one "undo"
3339 */
3340 if ( this->priv->cp_cleared_flag
3341 || (this->priv->cp_desc == NULL)
3342 || (strcmp (description, this->priv->cp_desc) != 0) )
3343 {
3344
3345 /* Sever old redo "thread" */
3346 stack_clear (this->priv->redo_stack);
3347
3348 /* Save state onto undo stack. */
3349 state = state_new (this, description);
3350 stack_push_state (this->priv->undo_stack, state);
3351
3352 /* Track consecutive checkpoints. */
3353 this->priv->cp_cleared_flag = FALSE;
3354 this->priv->cp_desc = g_strdup (description);
3355 }
3356
3357 gl_debug (DEBUG_LABEL, "END");
3358 }
3359
3360
3361 /****************************************************************************/
3362 /* Undo. */
3363 /****************************************************************************/
3364 void
gl_label_undo(glLabel * this)3365 gl_label_undo (glLabel *this)
3366 {
3367 State *state_old;
3368 State *state_now;
3369
3370 gl_debug (DEBUG_LABEL, "START");
3371
3372 state_old = stack_pop_state (this->priv->undo_stack);
3373 state_now = state_new (this, state_old->description);
3374
3375 stack_push_state (this->priv->redo_stack, state_now);
3376
3377 state_restore (state_old, this);
3378 state_free (state_old);
3379
3380 this->priv->cp_cleared_flag = TRUE;
3381
3382 gl_debug (DEBUG_LABEL, "END");
3383 }
3384
3385
3386 /****************************************************************************/
3387 /* Redo. */
3388 /****************************************************************************/
3389 void
gl_label_redo(glLabel * this)3390 gl_label_redo (glLabel *this)
3391 {
3392 State *state_old;
3393 State *state_now;
3394
3395 gl_debug (DEBUG_LABEL, "START");
3396
3397 state_old = stack_pop_state (this->priv->redo_stack);
3398 state_now = state_new (this, state_old->description);
3399
3400 stack_push_state (this->priv->undo_stack, state_now);
3401
3402 state_restore (state_old, this);
3403 state_free (state_old);
3404
3405 this->priv->cp_cleared_flag = TRUE;
3406
3407 gl_debug (DEBUG_LABEL, "END");
3408 }
3409
3410
3411 /****************************************************************************/
3412 /* Can undo? */
3413 /****************************************************************************/
3414 gboolean
gl_label_can_undo(glLabel * this)3415 gl_label_can_undo (glLabel *this)
3416 {
3417 return (!g_queue_is_empty (this->priv->undo_stack));
3418 }
3419
3420
3421 /****************************************************************************/
3422 /* Can redo? */
3423 /****************************************************************************/
3424 gboolean
gl_label_can_redo(glLabel * this)3425 gl_label_can_redo (glLabel *this)
3426 {
3427 return (!g_queue_is_empty (this->priv->redo_stack));
3428 }
3429
3430
3431 /****************************************************************************/
3432 /* Get undo description string. */
3433 /****************************************************************************/
3434 gchar *
gl_label_get_undo_description(glLabel * this)3435 gl_label_get_undo_description (glLabel *this)
3436 {
3437 State *state;
3438 gchar *description;
3439
3440 state = g_queue_peek_head (this->priv->undo_stack);
3441 if ( state )
3442 {
3443 description = g_strdup (state->description);
3444 }
3445 else
3446 {
3447 description = g_strdup ("");
3448 }
3449
3450 return description;
3451 }
3452
3453
3454 /****************************************************************************/
3455 /* Get redo description string. */
3456 /****************************************************************************/
3457 gchar *
gl_label_get_redo_description(glLabel * this)3458 gl_label_get_redo_description (glLabel *this)
3459 {
3460 State *state;
3461 gchar *description;
3462
3463 state = g_queue_peek_head (this->priv->redo_stack);
3464 if ( state )
3465 {
3466 description = g_strdup (state->description);
3467 }
3468 else
3469 {
3470 description = g_strdup ("");
3471 }
3472
3473 return description;
3474 }
3475
3476
3477 /****************************************************************************/
3478 /* Clear undo or redo stack. */
3479 /****************************************************************************/
3480 static void
stack_clear(GQueue * stack)3481 stack_clear (GQueue *stack)
3482 {
3483 State *state;
3484
3485 gl_debug (DEBUG_LABEL, "START");
3486
3487 while ( (state = g_queue_pop_head (stack)) != NULL )
3488 {
3489 state_free (state);
3490 }
3491
3492 gl_debug (DEBUG_LABEL, "END");
3493 }
3494
3495
3496 /****************************************************************************/
3497 /* Push state onto stack. */
3498 /****************************************************************************/
3499 static void
stack_push_state(GQueue * stack,State * state)3500 stack_push_state (GQueue *stack,
3501 State *state)
3502 {
3503 gl_debug (DEBUG_LABEL, "START");
3504
3505 g_queue_push_head( stack, state );
3506
3507 gl_debug (DEBUG_LABEL, "END");
3508 }
3509
3510
3511 /****************************************************************************/
3512 /* Pop state from stack. */
3513 /****************************************************************************/
3514 static State *
stack_pop_state(GQueue * stack)3515 stack_pop_state (GQueue *stack)
3516 {
3517 State *state;
3518
3519 gl_debug (DEBUG_LABEL, "START");
3520
3521 state = g_queue_pop_head (stack);
3522
3523 gl_debug (DEBUG_LABEL, "END");
3524 return state;
3525 }
3526
3527
3528 /****************************************************************************/
3529 /* New state from label. */
3530 /****************************************************************************/
3531 static State *
state_new(glLabel * this,const gchar * description)3532 state_new (glLabel *this,
3533 const gchar *description)
3534 {
3535 State *state;
3536 GList *p_obj;
3537 glLabelObject *object;
3538
3539 gl_debug (DEBUG_LABEL, "START");
3540
3541 state = g_new0 (State, 1);
3542
3543 state->description = g_strdup (description);
3544
3545 state->template = lgl_template_dup (this->priv->template);
3546 state->rotate_flag = this->priv->rotate_flag;
3547
3548 for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_obj->next )
3549 {
3550 object = GL_LABEL_OBJECT (p_obj->data);
3551
3552 state->object_list = g_list_append (state->object_list,
3553 gl_label_object_dup (object, this));
3554 }
3555
3556 state->merge = gl_merge_dup (this->priv->merge);
3557
3558 state->modified_flag = this->priv->modified_flag;
3559 state->time_stamp = this->priv->time_stamp;
3560
3561
3562 gl_debug (DEBUG_LABEL, "END");
3563 return state;
3564 }
3565
3566
3567 /****************************************************************************/
3568 /* Restore label from saved state. */
3569 /****************************************************************************/
3570 static void
state_free(State * state)3571 state_free (State *state)
3572 {
3573 GList *p_obj;
3574
3575 gl_debug (DEBUG_LABEL, "START");
3576
3577 g_free (state->description);
3578
3579 lgl_template_free (state->template);
3580 if ( state->merge )
3581 {
3582 g_object_unref (G_OBJECT (state->merge));
3583 }
3584
3585 for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
3586 {
3587 g_object_unref (G_OBJECT (p_obj->data));
3588 }
3589 g_list_free (state->object_list);
3590
3591 g_free (state);
3592
3593 gl_debug (DEBUG_LABEL, "END");
3594 }
3595
3596
3597 /****************************************************************************/
3598 /* Restore label from saved state. */
3599 /****************************************************************************/
3600 static void
state_restore(State * state,glLabel * this)3601 state_restore (State *state,
3602 glLabel *this)
3603
3604 {
3605 GList *p_obj, *p_next;
3606 glLabelObject *object;
3607
3608 gl_debug (DEBUG_LABEL, "START");
3609
3610 gl_label_set_rotate_flag (this, state->rotate_flag, FALSE);
3611 gl_label_set_template (this, state->template, FALSE);
3612
3613 for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_next )
3614 {
3615 p_next = p_obj->next; /* Hold on to next; delete is destructive */
3616 object = GL_LABEL_OBJECT (p_obj->data);
3617
3618 gl_label_delete_object (this, object);
3619 }
3620
3621 for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
3622 {
3623 object = GL_LABEL_OBJECT (p_obj->data);
3624
3625 gl_label_add_object (this, gl_label_object_dup (object, this));
3626 }
3627 g_signal_emit (G_OBJECT(this), signals[SELECTION_CHANGED], 0);
3628
3629 gl_label_set_merge (this, state->merge, FALSE);
3630
3631
3632 if ( !state->modified_flag &&
3633 (state->time_stamp.tv_sec == this->priv->time_stamp.tv_sec) &&
3634 (state->time_stamp.tv_usec == this->priv->time_stamp.tv_usec) )
3635 {
3636 gl_label_clear_modified (this);
3637 }
3638
3639 gl_debug (DEBUG_LABEL, "END");
3640 }
3641
3642
3643
3644
3645 /*
3646 * Local Variables: -- emacs
3647 * mode: C -- emacs
3648 * c-basic-offset: 8 -- emacs
3649 * tab-width: 8 -- emacs
3650 * indent-tabs-mode: nil -- emacs
3651 * End: -- emacs
3652 */
3653