]> git.sur5r.net Git - glabels/blob - glabels2/src/label-object.c
2003-12-30 Wayne Schuller <k_wayne@linuxpower.org>
[glabels] / glabels2 / src / label-object.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label_object.c:  GLabels label object base class
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22 #include <config.h>
23
24 #include <glib.h>
25 #include <libart_lgpl/libart.h>
26
27 #include "label-object.h"
28 #include "marshal.h"
29
30 #include "debug.h"
31
32 /*========================================================*/
33 /* Private types.                                         */
34 /*========================================================*/
35
36 struct _glLabelObjectPrivate {
37         gchar             *name;
38         gdouble            x, y;
39         gdouble            w, h;
40         gdouble            affine[6];
41 };
42
43 enum {
44         CHANGED,
45         MOVED,
46         FLIP_ROTATE,
47         TOP,
48         BOTTOM,
49         LAST_SIGNAL
50 };
51
52 /*========================================================*/
53 /* Private globals.                                       */
54 /*========================================================*/
55
56 static GObjectClass *parent_class = NULL;
57
58 static guint signals[LAST_SIGNAL] = {0};
59
60 static guint instance = 0;
61
62 /*========================================================*/
63 /* Private function prototypes.                           */
64 /*========================================================*/
65
66 static void gl_label_object_class_init    (glLabelObjectClass *klass);
67 static void gl_label_object_instance_init (glLabelObject      *object);
68 static void gl_label_object_finalize      (GObject            *object);
69
70 static void merge_changed_cb              (glLabel            *label,
71                                            glLabelObject      *object);
72
73 static void set_size                      (glLabelObject      *object,
74                                            gdouble             w,
75                                            gdouble             h);
76
77 static void get_size                      (glLabelObject      *object,
78                                            gdouble            *w,
79                                            gdouble            *h);
80
81 \f
82 /*****************************************************************************/
83 /* Boilerplate object stuff.                                                 */
84 /*****************************************************************************/
85 GType
86 gl_label_object_get_type (void)
87 {
88         static GType type = 0;
89
90         if (!type) {
91                 GTypeInfo info = {
92                         sizeof (glLabelObjectClass),
93                         NULL,
94                         NULL,
95                         (GClassInitFunc) gl_label_object_class_init,
96                         NULL,
97                         NULL,
98                         sizeof (glLabelObject),
99                         0,
100                         (GInstanceInitFunc) gl_label_object_instance_init,
101                 };
102
103                 type = g_type_register_static (G_TYPE_OBJECT,
104                                                "glLabelObject", &info, 0);
105         }
106
107         return type;
108 }
109
110 static void
111 gl_label_object_class_init (glLabelObjectClass *klass)
112 {
113         GObjectClass       *gobject_class = (GObjectClass *) klass;
114         glLabelObjectClass *object_class  = (glLabelObjectClass *) klass;
115
116         gl_debug (DEBUG_LABEL, "START");
117
118         parent_class = g_type_class_peek_parent (klass);
119
120         gobject_class->finalize = gl_label_object_finalize;
121
122         object_class->set_size = set_size;
123         object_class->get_size = get_size;
124
125         signals[CHANGED] =
126                 g_signal_new ("changed",
127                               G_OBJECT_CLASS_TYPE (gobject_class),
128                               G_SIGNAL_RUN_LAST,
129                               G_STRUCT_OFFSET (glLabelObjectClass, changed),
130                               NULL, NULL,
131                               gl_marshal_VOID__VOID,
132                               G_TYPE_NONE,
133                               0);
134
135         signals[MOVED] =
136                 g_signal_new ("moved",
137                               G_OBJECT_CLASS_TYPE (gobject_class),
138                               G_SIGNAL_RUN_LAST,
139                               G_STRUCT_OFFSET (glLabelObjectClass, moved),
140                               NULL, NULL,
141                               gl_marshal_VOID__DOUBLE_DOUBLE,
142                               G_TYPE_NONE,
143                               2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
144         signals[FLIP_ROTATE] =
145                 g_signal_new ("flip_rotate",
146                               G_OBJECT_CLASS_TYPE (gobject_class),
147                               G_SIGNAL_RUN_LAST,
148                               G_STRUCT_OFFSET (glLabelObjectClass, flip_rotate),
149                               NULL, NULL,
150                               gl_marshal_VOID__VOID,
151                               G_TYPE_NONE,
152                               0);
153         signals[TOP] =
154                 g_signal_new ("top",
155                               G_OBJECT_CLASS_TYPE (gobject_class),
156                               G_SIGNAL_RUN_LAST,
157                               G_STRUCT_OFFSET (glLabelObjectClass, top),
158                               NULL, NULL,
159                               gl_marshal_VOID__VOID,
160                               G_TYPE_NONE,
161                               0);
162
163         signals[BOTTOM] =
164                 g_signal_new ("bottom",
165                               G_OBJECT_CLASS_TYPE (gobject_class),
166                               G_SIGNAL_RUN_LAST,
167                               G_STRUCT_OFFSET (glLabelObjectClass, bottom),
168                               NULL, NULL,
169                               gl_marshal_VOID__VOID,
170                               G_TYPE_NONE,
171                               0);
172
173         gl_debug (DEBUG_LABEL, "END");
174 }
175
176 static void
177 gl_label_object_instance_init (glLabelObject *object)
178 {
179         gl_debug (DEBUG_LABEL, "START");
180
181         object->private = g_new0 (glLabelObjectPrivate, 1);
182
183         object->private->name = g_strdup_printf ("object%d", instance++);
184
185         art_affine_identity (object->private->affine);
186
187         gl_debug (DEBUG_LABEL, "END");
188 }
189
190 static void
191 gl_label_object_finalize (GObject *object)
192 {
193         glLabel       *parent;
194
195         gl_debug (DEBUG_LABEL, "START");
196
197         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
198
199         parent = GL_LABEL_OBJECT(object)->parent;
200         gl_label_remove_object (parent, GL_LABEL_OBJECT(object));
201
202         g_free (GL_LABEL_OBJECT(object)->private->name);
203         g_free (GL_LABEL_OBJECT(object)->private);
204
205         G_OBJECT_CLASS (parent_class)->finalize (object);
206
207         gl_debug (DEBUG_LABEL, "END");
208 }
209
210 /*****************************************************************************/
211 /* New label object.                                                         */
212 /*****************************************************************************/
213 GObject *
214 gl_label_object_new (glLabel *label)
215 {
216         glLabelObject *object;
217
218         gl_debug (DEBUG_LABEL, "START");
219
220         object = g_object_new (gl_label_object_get_type(), NULL);
221
222         gl_label_object_set_parent (object, label);
223
224         gl_debug (DEBUG_LABEL, "END");
225
226         return G_OBJECT (object);
227 }
228
229 /*****************************************************************************/
230 /* Duplicate object.                                                         */
231 /*****************************************************************************/
232 glLabelObject *
233 gl_label_object_dup (glLabelObject *src_object,
234                      glLabel       *label)
235 {
236         glLabelObject    *dst_object;
237         gdouble           x, y, w, h;
238         gdouble           affine[6];
239
240         gl_debug (DEBUG_LABEL, "START");
241
242         g_return_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object));
243
244         dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
245
246         gl_label_object_set_parent (dst_object, label);
247
248         gl_label_object_get_position (src_object, &x, &y);
249         gl_label_object_get_size     (src_object, &w, &h);
250         gl_label_object_get_affine   (src_object, affine);
251
252         gl_label_object_set_position (dst_object, x, y);
253         gl_label_object_set_size     (dst_object, w, h);
254         gl_label_object_set_affine   (dst_object, affine);
255
256         if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL ) {
257
258                 /* We have an object specific method, use it */
259                 GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
260
261         }
262
263         gl_debug (DEBUG_LABEL, "END");
264
265         return dst_object;
266 }
267
268 /*****************************************************************************/
269 /* Emit "changed" signal (for derived objects).                              */
270 /*****************************************************************************/
271 void
272 gl_label_object_emit_changed (glLabelObject *object)
273 {
274         gl_debug (DEBUG_LABEL, "START");
275
276         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
277
278         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
279
280         gl_debug (DEBUG_LABEL, "END");
281 }
282
283 /*****************************************************************************/
284 /* Set parent label of object.                                               */
285 /*****************************************************************************/
286 void
287 gl_label_object_set_parent (glLabelObject *object,
288                             glLabel       *label)
289 {
290         glLabel *old_parent;
291
292         gl_debug (DEBUG_LABEL, "START");
293
294         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
295         g_return_if_fail (label && GL_IS_LABEL (label));
296
297         old_parent = object->parent;
298         if ( old_parent != NULL ) {
299                 g_signal_handlers_disconnect_by_func (old_parent,
300                                                       G_CALLBACK(merge_changed_cb),
301                                                       object);
302                 gl_label_remove_object( old_parent, object );
303         }
304         gl_label_add_object( label, object );
305
306         g_signal_connect (G_OBJECT(label), "merge_changed",
307                           G_CALLBACK(merge_changed_cb), object);
308
309         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
310
311         gl_debug (DEBUG_LABEL, "END");
312 }
313
314 /*****************************************************************************/
315 /* Get parent label of object.                                               */
316 /*****************************************************************************/
317 glLabel *
318 gl_label_object_get_parent (glLabelObject *object)
319 {
320         gl_debug (DEBUG_LABEL, "START");
321
322         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
323
324         gl_debug (DEBUG_LABEL, "END");
325
326         return object->parent;
327 }
328
329 /*****************************************************************************/
330 /* Set name of object.                                                       */
331 /*****************************************************************************/
332 void
333 gl_label_object_set_name (glLabelObject *object,
334                           gchar         *name)
335 {
336         gl_debug (DEBUG_LABEL, "START");
337
338         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
339
340         g_free(object->private->name);
341         object->private->name = name;
342
343         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
344
345         gl_debug (DEBUG_LABEL, "END");
346 }
347
348 /*****************************************************************************/
349 /* Get name of object.                                                       */
350 /*****************************************************************************/
351 gchar *
352 gl_label_object_get_name (glLabelObject *object)
353 {
354         gl_debug (DEBUG_LABEL, "START");
355
356         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
357
358         gl_debug (DEBUG_LABEL, "END");
359
360         return g_strdup(object->private->name);
361 }
362
363 /*****************************************************************************/
364 /* Set position of object.                                                   */
365 /*****************************************************************************/
366 void
367 gl_label_object_set_position (glLabelObject *object,
368                               gdouble        x,
369                               gdouble        y)
370 {
371         gdouble dx, dy;
372
373         gl_debug (DEBUG_LABEL, "START");
374
375         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
376
377         dx = x - object->private->x;
378         dy = y - object->private->y;
379
380         object->private->x = x;
381         object->private->y = y;
382
383         g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
384
385         gl_debug (DEBUG_LABEL, "END");
386 }
387
388 /*****************************************************************************/
389 /* Set position of object relative to old position.                          */
390 /*****************************************************************************/
391 void
392 gl_label_object_set_position_relative (glLabelObject *object,
393                                        gdouble        dx,
394                                        gdouble        dy)
395 {
396         gl_debug (DEBUG_LABEL, "START");
397
398         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
399
400         object->private->x += dx;
401         object->private->y += dy;
402
403         gl_debug (DEBUG_LABEL, "       x = %f, y= %f",
404                   object->private->x,
405                   object->private->y);
406
407         g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
408
409         gl_debug (DEBUG_LABEL, "END");
410 }
411
412 /*****************************************************************************/
413 /* Get position of object.                                                   */
414 /*****************************************************************************/
415 void
416 gl_label_object_get_position (glLabelObject *object,
417                               gdouble       *x,
418                               gdouble       *y)
419 {
420         gl_debug (DEBUG_LABEL, "START");
421
422         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
423
424         *x = object->private->x;
425         *y = object->private->y;
426
427         gl_debug (DEBUG_LABEL, "END");
428 }
429
430 /*---------------------------------------------------------------------------*/
431 /* PRIVATE.  Default set size method.                                        */
432 /*---------------------------------------------------------------------------*/
433 static void
434 set_size (glLabelObject *object,
435           gdouble        w,
436           gdouble        h)
437 {
438         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
439
440         object->private->w = w;
441         object->private->h = h;
442 }
443
444 /*****************************************************************************/
445 /* Set size of object.                                                       */
446 /*****************************************************************************/
447 void
448 gl_label_object_set_size (glLabelObject *object,
449                           gdouble        w,
450                           gdouble        h)
451 {
452         gl_debug (DEBUG_LABEL, "START");
453
454         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
455
456         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
457
458                 /* We have an object specific method, use it */
459                 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
460
461         } else {
462
463                 set_size (object, w, h);
464
465         }
466
467         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
468
469         gl_debug (DEBUG_LABEL, "END");
470 }
471
472 /*---------------------------------------------------------------------------*/
473 /* PRIVATE.  Default get size method.                                        */
474 /*---------------------------------------------------------------------------*/
475 static void
476 get_size (glLabelObject *object,
477           gdouble       *w,
478           gdouble       *h)
479 {
480         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
481
482         *w = object->private->w;
483         *h = object->private->h;
484 }
485
486 /*****************************************************************************/
487 /* Get size of object.                                                       */
488 /*****************************************************************************/
489 void
490 gl_label_object_get_size (glLabelObject *object,
491                           gdouble       *w,
492                           gdouble       *h)
493 {
494         gl_debug (DEBUG_LABEL, "START");
495
496         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
497
498         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL ) {
499
500                 /* We have an object specific method, use it */
501                 GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
502
503         } else {
504
505                 get_size (object, w, h);
506
507         }
508
509         gl_debug (DEBUG_LABEL, "END");
510 }
511
512 /*****************************************************************************/
513 /* Get extent of object.                                                     */
514 /*****************************************************************************/
515 void
516 gl_label_object_get_extent (glLabelObject *object,
517                             gdouble       *x1,
518                             gdouble       *y1,
519                             gdouble       *x2,
520                             gdouble       *y2)
521 {
522         gdouble  w, h;
523         ArtPoint a1, a2, a3, a4, b1, b2, b3, b4;
524         gdouble  affine[6];
525
526         gl_debug (DEBUG_LABEL, "START");
527
528         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
529
530         gl_label_object_get_size (object, &w, &h);
531
532         /* setup untransformed corners of bounding box */
533         a1.x = 0.0;
534         a1.y = 0.0;
535         a2.x = w;
536         a2.y = 0.0;
537         a3.x = w;
538         a3.y = h;
539         a4.x = 0.0;
540         a4.y = h;
541
542         /* transform these points */
543         gl_label_object_get_affine (object, affine);
544         art_affine_point (&b1, &a1, affine);
545         art_affine_point (&b2, &a2, affine);
546         art_affine_point (&b3, &a3, affine);
547         art_affine_point (&b4, &a4, affine);
548
549         /* now find the maximum extent of these points in x and y */
550         *x1 = MIN (b1.x, MIN (b2.x, MIN (b3.x, b4.x))) + object->private->x;
551         *y1 = MIN (b1.y, MIN (b2.y, MIN (b3.y, b4.y))) + object->private->y;
552         *x2 = MAX (b1.x, MAX (b2.x, MAX (b3.x, b4.x))) + object->private->x;
553         *y2 = MAX (b1.y, MAX (b2.y, MAX (b3.y, b4.y))) + object->private->y;
554         
555         gl_debug (DEBUG_LABEL, "END");
556 }
557
558 /*****************************************************************************/
559 /* Can text properties be set for this object?                               */
560 /*****************************************************************************/
561 gboolean
562 gl_label_object_can_text (glLabelObject     *object)
563 {
564         gl_debug (DEBUG_LABEL, "");
565
566         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
567
568         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
569
570                 return TRUE;
571
572         } else {
573
574                 return FALSE;
575
576         }
577
578 }
579
580 /*****************************************************************************/
581 /* Set font family for all text contained in object.                         */
582 /*****************************************************************************/
583 void
584 gl_label_object_set_font_family (glLabelObject     *object,
585                                  const gchar       *font_family)
586 {
587         gl_debug (DEBUG_LABEL, "START");
588
589         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
590
591         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
592
593                 /* We have an object specific method, use it */
594                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
595
596         }
597
598         gl_debug (DEBUG_LABEL, "END");
599 }
600
601 /****************************************************************************/
602 /* Set font size for all text contained in object.                          */
603 /****************************************************************************/
604 void
605 gl_label_object_set_font_size (glLabelObject     *object,
606                                gdouble            font_size)
607 {
608         gl_debug (DEBUG_LABEL, "START");
609
610         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
611
612         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL ) {
613
614                 /* We have an object specific method, use it */
615                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
616
617         }
618
619         gl_debug (DEBUG_LABEL, "END");
620 }
621
622 /****************************************************************************/
623 /* Set font weight for all text contained in object.                        */
624 /****************************************************************************/
625 void
626 gl_label_object_set_font_weight (glLabelObject     *object,
627                                  GnomeFontWeight    font_weight)
628 {
629         gl_debug (DEBUG_LABEL, "START");
630
631         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
632
633         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL ) {
634
635                 /* We have an object specific method, use it */
636                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
637
638         }
639
640         gl_debug (DEBUG_LABEL, "END");
641 }
642
643 /****************************************************************************/
644 /* Set font italic flag for all text contained in object.                   */
645 /****************************************************************************/
646 void
647 gl_label_object_set_font_italic_flag (glLabelObject     *object,
648                                       gboolean           font_italic_flag)
649 {
650         gl_debug (DEBUG_LABEL, "START");
651
652         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
653
654         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL ) {
655
656                 /* We have an object specific method, use it */
657                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object,
658                                                                          font_italic_flag);
659
660         }
661
662         gl_debug (DEBUG_LABEL, "END");
663 }
664
665 /****************************************************************************/
666 /* Set text alignment for all text contained in object.                     */
667 /****************************************************************************/
668 void
669 gl_label_object_set_text_alignment (glLabelObject     *object,
670                                     GtkJustification   text_alignment)
671 {
672         gl_debug (DEBUG_LABEL, "START");
673
674         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
675
676         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL ) {
677
678                 /* We have an object specific method, use it */
679                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object,
680                                                                        text_alignment);
681
682         }
683
684         gl_debug (DEBUG_LABEL, "END");
685 }
686
687 /****************************************************************************/
688 /* Set text line spacing for all text contained in object.                  */
689 /****************************************************************************/
690 void
691 gl_label_object_set_text_line_spacing (glLabelObject     *object,
692                                        gdouble            text_line_spacing)
693 {
694         gl_debug (DEBUG_LABEL, "START");
695
696         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
697
698         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL ) {
699
700                 /* We have an object specific method, use it */
701                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
702
703         }
704
705         gl_debug (DEBUG_LABEL, "END");
706 }
707
708 /****************************************************************************/
709 /* Set text color for all text contained in object.                         */
710 /****************************************************************************/
711 void
712 gl_label_object_set_text_color (glLabelObject     *object,
713                                 guint              text_color)
714 {
715         gl_debug (DEBUG_LABEL, "START");
716
717         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
718
719         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL ) {
720
721                 /* We have an object specific method, use it */
722                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color);
723
724         }
725
726         gl_debug (DEBUG_LABEL, "END");
727 }
728
729 /*****************************************************************************/
730 /* Get font family for all text contained in object.                         */
731 /*****************************************************************************/
732 gchar *
733 gl_label_object_get_font_family (glLabelObject     *object)
734 {
735         gchar *ret = NULL;
736
737         gl_debug (DEBUG_LABEL, "START");
738
739         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
740
741         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL ) {
742
743                 /* We have an object specific method, use it */
744                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
745
746         }
747
748         gl_debug (DEBUG_LABEL, "END");
749
750         return ret;
751 }
752
753 /****************************************************************************/
754 /* Get font size for all text contained in object.                          */
755 /****************************************************************************/
756 gdouble
757 gl_label_object_get_font_size (glLabelObject     *object)
758 {
759         gdouble ret = 0.0;
760
761         gl_debug (DEBUG_LABEL, "START");
762
763         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
764
765         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL ) {
766
767                 /* We have an object specific method, use it */
768                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
769
770         }
771
772         gl_debug (DEBUG_LABEL, "END");
773
774         return ret;
775 }
776
777 /****************************************************************************/
778 /* Get font weight for all text contained in object.                        */
779 /****************************************************************************/
780 GnomeFontWeight
781 gl_label_object_get_font_weight (glLabelObject     *object)
782 {
783         GnomeFontWeight ret = GNOME_FONT_BOOK;
784
785         gl_debug (DEBUG_LABEL, "START");
786
787         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), GNOME_FONT_BOOK);
788
789         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL ) {
790
791                 /* We have an object specific method, use it */
792                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
793
794         }
795
796         gl_debug (DEBUG_LABEL, "END");
797
798         return ret;
799 }
800
801 /****************************************************************************/
802 /* Get font italic flag for all text contained in object.                   */
803 /****************************************************************************/
804 gboolean
805 gl_label_object_get_font_italic_flag (glLabelObject     *object)
806 {
807         gboolean ret = FALSE;
808
809         gl_debug (DEBUG_LABEL, "START");
810
811         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
812
813         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL ) {
814
815                 /* We have an object specific method, use it */
816                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
817
818         }
819
820         gl_debug (DEBUG_LABEL, "END");
821
822         return ret;
823 }
824
825 /****************************************************************************/
826 /* Get text alignment for all text contained in object.                     */
827 /****************************************************************************/
828 GtkJustification
829 gl_label_object_get_text_alignment (glLabelObject     *object)
830 {
831         GtkJustification ret = GTK_JUSTIFY_LEFT;
832
833         gl_debug (DEBUG_LABEL, "START");
834
835         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), GTK_JUSTIFY_LEFT);
836
837         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL ) {
838
839                 /* We have an object specific method, use it */
840                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
841
842         }
843
844         gl_debug (DEBUG_LABEL, "END");
845
846         return ret;
847 }
848
849 /****************************************************************************/
850 /* Get text line spacing for all text contained in object.                  */
851 /****************************************************************************/
852 gdouble
853 gl_label_object_get_text_line_spacing (glLabelObject     *object)
854 {
855         gdouble ret = 0.0;
856
857         gl_debug (DEBUG_LABEL, "START");
858
859         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
860
861         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL ) {
862
863                 /* We have an object specific method, use it */
864                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
865
866         }
867
868         gl_debug (DEBUG_LABEL, "END");
869
870         return ret;
871 }
872
873 /****************************************************************************/
874 /* Get text color for all text contained in object.                         */
875 /****************************************************************************/
876 guint
877 gl_label_object_get_text_color (glLabelObject     *object)
878 {
879         guint ret = 0;
880
881         gl_debug (DEBUG_LABEL, "START");
882
883         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
884
885         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL ) {
886
887                 /* We have an object specific method, use it */
888                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
889
890         }
891
892         gl_debug (DEBUG_LABEL, "END");
893
894         return ret;
895 }
896
897 /*****************************************************************************/
898 /* Can fill properties be set for this object?                               */
899 /*****************************************************************************/
900 gboolean
901 gl_label_object_can_fill (glLabelObject     *object)
902 {
903         gl_debug (DEBUG_LABEL, "");
904
905         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
906
907         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
908
909                 return TRUE;
910
911         } else {
912
913                 return FALSE;
914
915         }
916
917 }
918
919 /****************************************************************************/
920 /* Set fill color for object.                                               */
921 /****************************************************************************/
922 void
923 gl_label_object_set_fill_color (glLabelObject     *object,
924                                 guint              fill_color)
925 {
926         gl_debug (DEBUG_LABEL, "START");
927
928         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
929
930         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
931
932                 /* We have an object specific method, use it */
933                 GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color);
934
935         }
936
937         gl_debug (DEBUG_LABEL, "END");
938 }
939
940 /****************************************************************************/
941 /* Get fill color for object.                                               */
942 /****************************************************************************/
943 guint
944 gl_label_object_get_fill_color (glLabelObject     *object)
945 {
946         guint ret = 0;
947
948         gl_debug (DEBUG_LABEL, "START");
949
950         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
951
952         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL ) {
953
954                 /* We have an object specific method, use it */
955                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
956
957         }
958
959         gl_debug (DEBUG_LABEL, "END");
960
961         return ret;
962 }
963
964 /*****************************************************************************/
965 /* Can line color property be set for this object?                           */
966 /*****************************************************************************/
967 gboolean
968 gl_label_object_can_line_color (glLabelObject     *object)
969 {
970         gl_debug (DEBUG_LABEL, "");
971
972         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
973
974         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
975
976                 return TRUE;
977
978         } else {
979
980                 return FALSE;
981
982         }
983
984 }
985
986 /****************************************************************************/
987 /* Set line color for object.                                               */
988 /****************************************************************************/
989 void
990 gl_label_object_set_line_color (glLabelObject     *object,
991                                 guint              line_color)
992 {
993         gl_debug (DEBUG_LABEL, "START");
994
995         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
996
997         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
998
999                 /* We have an object specific method, use it */
1000                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color);
1001
1002         }
1003
1004         gl_debug (DEBUG_LABEL, "END");
1005 }
1006
1007 /****************************************************************************/
1008 /* Get line color for object.                                               */
1009 /****************************************************************************/
1010 guint
1011 gl_label_object_get_line_color (glLabelObject     *object)
1012 {
1013         guint ret = 0;
1014
1015         gl_debug (DEBUG_LABEL, "START");
1016
1017         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1018
1019         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL ) {
1020
1021                 /* We have an object specific method, use it */
1022                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
1023
1024         }
1025
1026         gl_debug (DEBUG_LABEL, "END");
1027
1028         return ret;
1029 }
1030
1031 /*****************************************************************************/
1032 /* Can line width property be set for this object?                           */
1033 /*****************************************************************************/
1034 gboolean
1035 gl_label_object_can_line_width (glLabelObject     *object)
1036 {
1037         gl_debug (DEBUG_LABEL, "");
1038
1039         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1040
1041         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1042
1043                 return TRUE;
1044
1045         } else {
1046
1047                 return FALSE;
1048
1049         }
1050
1051 }
1052
1053 /****************************************************************************/
1054 /* Set line width for object.                                               */
1055 /****************************************************************************/
1056 void
1057 gl_label_object_set_line_width (glLabelObject     *object,
1058                                 gdouble            line_width)
1059 {
1060         gl_debug (DEBUG_LABEL, "START");
1061
1062         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1063
1064         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1065
1066                 /* We have an object specific method, use it */
1067                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
1068
1069         }
1070
1071         gl_debug (DEBUG_LABEL, "END");
1072 }
1073
1074 /****************************************************************************/
1075 /* Get line width for object.                                               */
1076 /****************************************************************************/
1077 gdouble
1078 gl_label_object_get_line_width (glLabelObject     *object)
1079 {
1080         gdouble ret = 0.0;
1081
1082         gl_debug (DEBUG_LABEL, "START");
1083
1084         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1085
1086         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL ) {
1087
1088                 /* We have an object specific method, use it */
1089                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
1090
1091         }
1092
1093         gl_debug (DEBUG_LABEL, "END");
1094
1095         return ret;
1096 }
1097
1098 /****************************************************************************/
1099 /* Flip object horizontally.                                                */
1100 /****************************************************************************/
1101 void
1102 gl_label_object_flip_horiz (glLabelObject *object)
1103 {
1104         gdouble flip_affine[6];
1105
1106         gl_debug (DEBUG_LABEL, "START");
1107
1108         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1109
1110         art_affine_scale (flip_affine, -1.0, 1.0);
1111         art_affine_multiply (object->private->affine, object->private->affine, flip_affine);
1112
1113         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1114
1115         gl_debug (DEBUG_LABEL, "END");
1116 }
1117
1118 /****************************************************************************/
1119 /* Flip object vertically.                                                  */
1120 /****************************************************************************/
1121 void
1122 gl_label_object_flip_vert (glLabelObject *object)
1123 {
1124         gdouble flip_affine[6];
1125
1126         gl_debug (DEBUG_LABEL, "START");
1127
1128         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1129
1130         art_affine_scale (flip_affine, 1.0, -1.0);
1131         art_affine_multiply (object->private->affine, object->private->affine, flip_affine);
1132
1133         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1134
1135         gl_debug (DEBUG_LABEL, "END");
1136 }
1137
1138 /****************************************************************************/
1139 /* Rotate object.                                                           */
1140 /****************************************************************************/
1141 void
1142 gl_label_object_rotate (glLabelObject *object,
1143                         gdouble        theta_degs)
1144 {
1145         gdouble rotate_affine[6];
1146
1147         gl_debug (DEBUG_LABEL, "START");
1148
1149         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1150
1151         art_affine_rotate (rotate_affine, theta_degs);
1152         art_affine_multiply (object->private->affine, object->private->affine, rotate_affine);
1153
1154         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1155
1156         gl_debug (DEBUG_LABEL, "END");
1157 }
1158
1159 /****************************************************************************/
1160 /* Set raw affine                                                           */
1161 /****************************************************************************/
1162 void
1163 gl_label_object_set_affine (glLabelObject *object,
1164                             gdouble        affine[6])
1165 {
1166         gl_debug (DEBUG_LABEL, "");
1167
1168         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1169
1170         object->private->affine[0] = affine[0];
1171         object->private->affine[1] = affine[1];
1172         object->private->affine[2] = affine[2];
1173         object->private->affine[3] = affine[3];
1174         object->private->affine[4] = affine[4];
1175         object->private->affine[5] = affine[5];
1176 }
1177
1178 /****************************************************************************/
1179 /* Get raw affine                                                           */
1180 /****************************************************************************/
1181 void
1182 gl_label_object_get_affine (glLabelObject *object,
1183                             gdouble        affine[6])
1184 {
1185         gl_debug (DEBUG_LABEL, "");
1186
1187         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1188
1189         affine[0] = object->private->affine[0];
1190         affine[1] = object->private->affine[1];
1191         affine[2] = object->private->affine[2];
1192         affine[3] = object->private->affine[3];
1193         affine[4] = object->private->affine[4];
1194         affine[5] = object->private->affine[5];
1195 }
1196
1197 /****************************************************************************/
1198 /* Get i2w affine, i.e. applied affine + translation.                       */
1199 /****************************************************************************/
1200 void
1201 gl_label_object_get_i2w_affine (glLabelObject *object,
1202                                 gdouble        affine[6])
1203 {
1204         gdouble x, y;
1205         gdouble translation[6];
1206
1207         gl_debug (DEBUG_LABEL, "");
1208
1209         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1210
1211         gl_label_object_get_affine (object, affine);
1212         gl_label_object_get_position (object, &x, &y);
1213
1214         art_affine_translate (translation, x, y);
1215         art_affine_multiply (affine, affine, translation);
1216 }
1217
1218 /****************************************************************************/
1219 /* Get w2i affine, i.e. inverse of applied affine + translation.            */
1220 /****************************************************************************/
1221 void
1222 gl_label_object_get_w2i_affine (glLabelObject *object,
1223                                 gdouble        affine[6])
1224 {
1225         gdouble i2w[6];
1226         gl_debug (DEBUG_LABEL, "");
1227
1228         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1229
1230         gl_label_object_get_i2w_affine (object, i2w);
1231         art_affine_invert (affine, i2w);
1232 }
1233
1234 /****************************************************************************/
1235 /* Bring label object to front/top.                                         */
1236 /****************************************************************************/
1237 void
1238 gl_label_object_raise_to_top (glLabelObject *object)
1239 {
1240         glLabel *label;
1241
1242         gl_debug (DEBUG_LABEL, "START");
1243
1244         label = object->parent;
1245
1246         gl_label_raise_object_to_top (label, object);
1247
1248         g_signal_emit (G_OBJECT(object), signals[TOP], 0);
1249
1250         gl_debug (DEBUG_LABEL, "END");
1251 }
1252
1253 /****************************************************************************/
1254 /* Send label object to rear/bottom.                                        */
1255 /****************************************************************************/
1256 void
1257 gl_label_object_lower_to_bottom (glLabelObject *object)
1258 {
1259         glLabel *label;
1260
1261         gl_debug (DEBUG_LABEL, "START");
1262
1263         label = object->parent;
1264
1265         gl_label_lower_object_to_bottom (label, object);
1266
1267         g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
1268
1269         gl_debug (DEBUG_LABEL, "END");
1270 }
1271
1272 /*--------------------------------------------------------------------------*/
1273 /* PRIVATE.  Label's merge data changed callback.                           */
1274 /*--------------------------------------------------------------------------*/
1275 static void
1276 merge_changed_cb (glLabel       *label,
1277                   glLabelObject *object)
1278 {
1279         gl_label_object_emit_changed (object);
1280 }
1281