2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * label_object.c: GLabels label object base class
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
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.
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.
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
25 #include <libart_lgpl/libart.h>
27 #include "label-object.h"
32 /*========================================================*/
34 /*========================================================*/
36 struct _glLabelObjectPrivate {
52 /*========================================================*/
53 /* Private globals. */
54 /*========================================================*/
56 static GObjectClass *parent_class = NULL;
58 static guint signals[LAST_SIGNAL] = {0};
60 static guint instance = 0;
62 /*========================================================*/
63 /* Private function prototypes. */
64 /*========================================================*/
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);
70 static void merge_changed_cb (glLabel *label,
71 glLabelObject *object);
74 /*****************************************************************************/
75 /* Boilerplate object stuff. */
76 /*****************************************************************************/
78 gl_label_object_get_type (void)
80 static GType type = 0;
84 sizeof (glLabelObjectClass),
87 (GClassInitFunc) gl_label_object_class_init,
90 sizeof (glLabelObject),
92 (GInstanceInitFunc) gl_label_object_instance_init,
95 type = g_type_register_static (G_TYPE_OBJECT,
96 "glLabelObject", &info, 0);
103 gl_label_object_class_init (glLabelObjectClass *klass)
105 GObjectClass *object_class = (GObjectClass *) klass;
107 gl_debug (DEBUG_LABEL, "START");
109 parent_class = g_type_class_peek_parent (klass);
111 object_class->finalize = gl_label_object_finalize;
114 g_signal_new ("changed",
115 G_OBJECT_CLASS_TYPE (object_class),
117 G_STRUCT_OFFSET (glLabelObjectClass, changed),
119 gl_marshal_VOID__VOID,
124 g_signal_new ("moved",
125 G_OBJECT_CLASS_TYPE (object_class),
127 G_STRUCT_OFFSET (glLabelObjectClass, moved),
129 gl_marshal_VOID__DOUBLE_DOUBLE,
131 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
132 signals[FLIP_ROTATE] =
133 g_signal_new ("flip_rotate",
134 G_OBJECT_CLASS_TYPE (object_class),
136 G_STRUCT_OFFSET (glLabelObjectClass, flip_rotate),
138 gl_marshal_VOID__VOID,
143 G_OBJECT_CLASS_TYPE (object_class),
145 G_STRUCT_OFFSET (glLabelObjectClass, top),
147 gl_marshal_VOID__VOID,
152 g_signal_new ("bottom",
153 G_OBJECT_CLASS_TYPE (object_class),
155 G_STRUCT_OFFSET (glLabelObjectClass, bottom),
157 gl_marshal_VOID__VOID,
161 gl_debug (DEBUG_LABEL, "END");
165 gl_label_object_instance_init (glLabelObject *object)
167 gl_debug (DEBUG_LABEL, "START");
169 object->private = g_new0 (glLabelObjectPrivate, 1);
171 object->private->name = g_strdup_printf ("object%d", instance++);
173 art_affine_identity (object->private->affine);
175 gl_debug (DEBUG_LABEL, "END");
179 gl_label_object_finalize (GObject *object)
183 gl_debug (DEBUG_LABEL, "START");
185 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
187 parent = GL_LABEL_OBJECT(object)->parent;
188 gl_label_remove_object (parent, GL_LABEL_OBJECT(object));
190 g_free (GL_LABEL_OBJECT(object)->private);
192 G_OBJECT_CLASS (parent_class)->finalize (object);
194 gl_debug (DEBUG_LABEL, "END");
197 /*****************************************************************************/
198 /* New label object. */
199 /*****************************************************************************/
201 gl_label_object_new (glLabel *label)
203 glLabelObject *object;
205 gl_debug (DEBUG_LABEL, "START");
207 object = g_object_new (gl_label_object_get_type(), NULL);
209 gl_label_object_set_parent (object, label);
211 gl_debug (DEBUG_LABEL, "END");
213 return G_OBJECT (object);
216 /*****************************************************************************/
217 /* Copy properties of one label object to another. */
218 /*****************************************************************************/
220 gl_label_object_copy_props (glLabelObject *dst_object,
221 glLabelObject *src_object)
226 g_return_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object));
227 g_return_if_fail (dst_object && GL_IS_LABEL_OBJECT (dst_object));
229 gl_label_object_get_position (src_object, &x, &y);
230 gl_label_object_get_size (src_object, &w, &h);
231 gl_label_object_get_affine (src_object, affine);
233 gl_label_object_set_position (dst_object, x, y);
234 gl_label_object_set_size (dst_object, w, h);
235 gl_label_object_set_affine (dst_object, affine);
238 /*****************************************************************************/
239 /* Emit "changed" signal (for derived objects). */
240 /*****************************************************************************/
242 gl_label_object_emit_changed (glLabelObject *object)
244 gl_debug (DEBUG_LABEL, "START");
246 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
248 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
250 gl_debug (DEBUG_LABEL, "END");
253 /*****************************************************************************/
254 /* Set parent label of object. */
255 /*****************************************************************************/
257 gl_label_object_set_parent (glLabelObject *object,
262 gl_debug (DEBUG_LABEL, "START");
264 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
265 g_return_if_fail (label && GL_IS_LABEL (label));
267 old_parent = object->parent;
268 if ( old_parent != NULL ) {
269 g_signal_handlers_disconnect_by_func (old_parent,
270 G_CALLBACK(merge_changed_cb),
272 gl_label_remove_object( old_parent, object );
274 gl_label_add_object( label, object );
276 g_signal_connect (G_OBJECT(label), "merge_changed",
277 G_CALLBACK(merge_changed_cb), object);
279 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
281 gl_debug (DEBUG_LABEL, "END");
284 /*****************************************************************************/
285 /* Get parent label of object. */
286 /*****************************************************************************/
288 gl_label_object_get_parent (glLabelObject *object)
290 gl_debug (DEBUG_LABEL, "START");
292 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
294 gl_debug (DEBUG_LABEL, "END");
296 return object->parent;
299 /*****************************************************************************/
300 /* Set name of object. */
301 /*****************************************************************************/
303 gl_label_object_set_name (glLabelObject *object,
306 gl_debug (DEBUG_LABEL, "START");
308 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
310 g_free(object->private->name);
311 object->private->name = name;
313 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
315 gl_debug (DEBUG_LABEL, "END");
318 /*****************************************************************************/
319 /* Get name of object. */
320 /*****************************************************************************/
322 gl_label_object_get_name (glLabelObject *object)
324 gl_debug (DEBUG_LABEL, "START");
326 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
328 gl_debug (DEBUG_LABEL, "END");
330 return g_strdup(object->private->name);
333 /*****************************************************************************/
334 /* Set position of object. */
335 /*****************************************************************************/
337 gl_label_object_set_position (glLabelObject *object,
343 gl_debug (DEBUG_LABEL, "START");
345 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
347 dx = x - object->private->x;
348 dy = y - object->private->y;
350 object->private->x = x;
351 object->private->y = y;
353 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
355 gl_debug (DEBUG_LABEL, "END");
358 /*****************************************************************************/
359 /* Set position of object relative to old position. */
360 /*****************************************************************************/
362 gl_label_object_set_position_relative (glLabelObject *object,
366 gl_debug (DEBUG_LABEL, "START");
368 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
370 object->private->x += dx;
371 object->private->y += dy;
373 gl_debug (DEBUG_LABEL, " x = %f, y= %f",
377 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
379 gl_debug (DEBUG_LABEL, "END");
382 /*****************************************************************************/
383 /* Get position of object. */
384 /*****************************************************************************/
386 gl_label_object_get_position (glLabelObject *object,
390 gl_debug (DEBUG_LABEL, "START");
392 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
394 *x = object->private->x;
395 *y = object->private->y;
397 gl_debug (DEBUG_LABEL, "END");
400 /*****************************************************************************/
401 /* Set size of object. */
402 /*****************************************************************************/
404 gl_label_object_set_size (glLabelObject *object,
408 gl_debug (DEBUG_LABEL, "START");
410 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
412 object->private->w = w;
413 object->private->h = h;
415 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
417 gl_debug (DEBUG_LABEL, "END");
420 /*****************************************************************************/
421 /* Get size of object. */
422 /*****************************************************************************/
424 gl_label_object_get_size (glLabelObject *object,
428 gl_debug (DEBUG_LABEL, "START");
430 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
432 *w = object->private->w;
433 *h = object->private->h;
435 gl_debug (DEBUG_LABEL, "END");
438 /*****************************************************************************/
439 /* Get extent of object. */
440 /*****************************************************************************/
442 gl_label_object_get_extent (glLabelObject *object,
448 ArtPoint a1, a2, a3, a4, b1, b2, b3, b4;
451 gl_debug (DEBUG_LABEL, "START");
453 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
455 /* setup untransformed corners of bounding box */
458 a2.x = object->private->w;
460 a3.x = object->private->w;
461 a3.y = object->private->h;
463 a4.y = object->private->h;
465 /* transform these points */
466 gl_label_object_get_applied_affine (object, affine);
467 art_affine_point (&b1, &a1, affine);
468 art_affine_point (&b2, &a2, affine);
469 art_affine_point (&b3, &a3, affine);
470 art_affine_point (&b4, &a4, affine);
472 /* now find the maximum extent of these points in x and y */
473 *x1 = MIN (b1.x, MIN (b2.x, MIN (b3.x, b4.x))) + object->private->x;
474 *y1 = MIN (b1.y, MIN (b2.y, MIN (b3.y, b4.y))) + object->private->y;
475 *x2 = MAX (b1.x, MAX (b2.x, MAX (b3.x, b4.x))) + object->private->x;
476 *y2 = MAX (b1.y, MAX (b2.y, MAX (b3.y, b4.y))) + object->private->y;
478 gl_debug (DEBUG_LABEL, "END");
481 /****************************************************************************/
482 /* Flip object horizontally. */
483 /****************************************************************************/
485 gl_label_object_flip_horiz (glLabelObject *object)
487 gl_debug (DEBUG_LABEL, "START");
489 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
491 art_affine_flip (object->private->affine, object->private->affine, TRUE, FALSE);
493 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
495 gl_debug (DEBUG_LABEL, "END");
498 /****************************************************************************/
499 /* Flip object vertically. */
500 /****************************************************************************/
502 gl_label_object_flip_vert (glLabelObject *object)
504 gl_debug (DEBUG_LABEL, "START");
506 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
508 art_affine_flip (object->private->affine, object->private->affine, FALSE, TRUE);
510 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
512 gl_debug (DEBUG_LABEL, "END");
515 /****************************************************************************/
517 /****************************************************************************/
519 gl_label_object_rotate (glLabelObject *object,
522 gdouble rotate_affine[6];
524 gl_debug (DEBUG_LABEL, "START");
526 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
528 art_affine_rotate (rotate_affine, theta_degs);
529 art_affine_multiply (object->private->affine, object->private->affine, rotate_affine);
531 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
533 gl_debug (DEBUG_LABEL, "END");
536 /****************************************************************************/
538 /****************************************************************************/
540 gl_label_object_set_affine (glLabelObject *object,
543 gl_debug (DEBUG_LABEL, "");
545 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
547 object->private->affine[0] = affine[0];
548 object->private->affine[1] = affine[1];
549 object->private->affine[2] = affine[2];
550 object->private->affine[3] = affine[3];
551 object->private->affine[4] = affine[4];
552 object->private->affine[5] = affine[5];
555 /****************************************************************************/
557 /****************************************************************************/
559 gl_label_object_get_affine (glLabelObject *object,
562 gl_debug (DEBUG_LABEL, "");
564 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
566 affine[0] = object->private->affine[0];
567 affine[1] = object->private->affine[1];
568 affine[2] = object->private->affine[2];
569 affine[3] = object->private->affine[3];
570 affine[4] = object->private->affine[4];
571 affine[5] = object->private->affine[5];
574 /****************************************************************************/
575 /* Get applied affine, i.e. translated to center of object and back */
576 /****************************************************************************/
578 gl_label_object_get_applied_affine (glLabelObject *object,
581 gdouble to_center[6], to_origin[6];
583 gl_debug (DEBUG_LABEL, "");
585 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
587 /* setup transformation affine */
588 art_affine_translate (to_center, -object->private->w/2.0, -object->private->h/2.0);
589 art_affine_multiply (affine, to_center, object->private->affine);
590 art_affine_translate (to_origin, object->private->w/2.0, object->private->h/2.0);
591 art_affine_multiply (affine, affine, to_origin);
594 /****************************************************************************/
595 /* Bring label object to front/top. */
596 /****************************************************************************/
598 gl_label_object_raise_to_top (glLabelObject *object)
602 gl_debug (DEBUG_LABEL, "START");
604 label = object->parent;
606 gl_label_raise_object_to_top (label, object);
608 g_signal_emit (G_OBJECT(object), signals[TOP], 0);
610 gl_debug (DEBUG_LABEL, "END");
613 /****************************************************************************/
614 /* Send label object to rear/bottom. */
615 /****************************************************************************/
617 gl_label_object_lower_to_bottom (glLabelObject *object)
621 gl_debug (DEBUG_LABEL, "START");
623 label = object->parent;
625 gl_label_lower_object_to_bottom (label, object);
627 g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
629 gl_debug (DEBUG_LABEL, "END");
632 /*--------------------------------------------------------------------------*/
633 /* PRIVATE. Label's merge data changed callback. */
634 /*--------------------------------------------------------------------------*/
636 merge_changed_cb (glLabel *label,
637 glLabelObject *object)
639 gl_label_object_emit_changed (object);