2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * view_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 "view-object.h"
26 #include "libart_lgpl/libart.h"
30 /*========================================================*/
32 /*========================================================*/
34 struct _glViewObjectPrivate {
37 glLabelObject *object;
39 GnomeCanvasItem *group;
40 glViewHighlight *highlight;
45 GtkWidget *property_dialog;
47 glViewObjectDlgConstructor dialog_constructor;
50 /*========================================================*/
51 /* Private globals. */
52 /*========================================================*/
54 static GObjectClass *parent_class = NULL;
57 /*========================================================*/
58 /* Private function prototypes. */
59 /*========================================================*/
61 static void gl_view_object_class_init (glViewObjectClass *klass);
62 static void gl_view_object_instance_init (glViewObject *view_object);
63 static void gl_view_object_finalize (GObject *object);
65 static GtkMenu *new_menu (glViewObject *view_object);
67 static void object_moved_cb (glLabelObject *object,
70 glViewObject *view_object);
72 static void raise_object_cb (GtkWidget *widget,
73 glViewObject *view_object);
75 static void lower_object_cb (GtkWidget *widget,
76 glViewObject *view_object);
78 static void flip_rotate_object_cb (GtkWidget *widget,
79 glLabelObjectFlip flip,
81 glViewObject *view_object);
85 /*****************************************************************************/
86 /* Boilerplate object stuff. */
87 /*****************************************************************************/
89 gl_view_object_get_type (void)
91 static GType type = 0;
95 sizeof (glViewObjectClass),
98 (GClassInitFunc) gl_view_object_class_init,
101 sizeof (glViewObject),
103 (GInstanceInitFunc) gl_view_object_instance_init,
106 type = g_type_register_static (G_TYPE_OBJECT,
107 "glViewObject", &info, 0);
114 gl_view_object_class_init (glViewObjectClass *klass)
116 GObjectClass *object_class = (GObjectClass *) klass;
118 gl_debug (DEBUG_VIEW, "START");
120 parent_class = g_type_class_peek_parent (klass);
122 object_class->finalize = gl_view_object_finalize;
124 gl_debug (DEBUG_VIEW, "END");
128 gl_view_object_instance_init (glViewObject *view_object)
130 gl_debug (DEBUG_VIEW, "START");
132 view_object->private = g_new0 (glViewObjectPrivate, 1);
134 gl_debug (DEBUG_VIEW, "END");
138 gl_view_object_finalize (GObject *object)
143 gl_debug (DEBUG_VIEW, "START");
145 g_return_if_fail (object && GL_IS_VIEW_OBJECT (object));
147 view = GL_VIEW_OBJECT(object)->private->view;
148 view->object_list = g_list_remove (view->object_list, object);
149 view->selected_object_list =
150 g_list_remove (view->selected_object_list, object);
152 g_object_unref (GL_VIEW_OBJECT(object)->private->object);
153 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->group));
154 g_object_unref (G_OBJECT(GL_VIEW_OBJECT(object)->private->highlight));
155 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->menu));
156 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->property_dialog));
158 G_OBJECT_CLASS (parent_class)->finalize (object);
160 gl_debug (DEBUG_VIEW, "END");
163 /*****************************************************************************/
164 /* NEW object view. */
165 /*****************************************************************************/
167 gl_view_object_new (void)
169 glViewObject *view_object;
171 gl_debug (DEBUG_VIEW, "START");
173 view_object = g_object_new (gl_view_object_get_type(), NULL);
175 gl_debug (DEBUG_VIEW, "END");
177 return G_OBJECT (view_object);
180 /*****************************************************************************/
181 /* Set parent view to which this object view belongs. */
182 /*****************************************************************************/
184 gl_view_object_set_view (glViewObject *view_object,
187 gl_debug (DEBUG_VIEW, "START");
189 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
190 g_return_if_fail (view && GL_IS_VIEW (view));
192 view_object->private->view = view;
194 view->object_list = g_list_prepend (view->object_list, view_object);
196 gl_debug (DEBUG_VIEW, "END");
199 /*****************************************************************************/
200 /* Set Label object to follow. */
201 /*****************************************************************************/
203 gl_view_object_set_object (glViewObject *view_object,
204 glLabelObject *object,
205 glViewHighlightStyle style)
208 GnomeCanvasGroup *root;
210 glLabelObjectFlip flip;
213 gl_debug (DEBUG_VIEW, "START");
215 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
216 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
218 view_object->private->object = object;
220 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
221 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
223 /* create canvas group to contain items representing object */
224 canvas = GNOME_CANVAS (view_object->private->view->canvas);
225 root = gnome_canvas_root (canvas);
226 view_object->private->group =
227 gnome_canvas_item_new (root, gnome_canvas_group_get_type (),
232 /* create affine to handle flipping and rotation transformations */
233 art_affine_identity (view_object->private->affine);
235 /* Apply appropriate flipping */
236 flip = gl_label_object_get_flip (object);
237 g_print ("Flip = %d\n", flip);
238 if ( flip & GL_LABEL_OBJECT_FLIP_HORIZ ) {
239 art_affine_translate (a, -w, 0.0);
240 art_affine_multiply (view_object->private->affine,
241 view_object->private->affine, a);
242 art_affine_scale (a, -1.0, 1.0);
243 art_affine_multiply (view_object->private->affine,
244 view_object->private->affine, a);
246 if ( flip & GL_LABEL_OBJECT_FLIP_VERT ) {
247 art_affine_translate (a, 0.0, -h);
248 art_affine_multiply (view_object->private->affine,
249 view_object->private->affine, a);
250 art_affine_scale (a, 1.0, -1.0);
251 art_affine_multiply (view_object->private->affine,
252 view_object->private->affine, a);
256 /* Create appropriate selection highlight canvas item. */
257 view_object->private->highlight =
258 GL_VIEW_HIGHLIGHT (gl_view_highlight_new (view_object, style));
260 gl_view_raise_fg (view_object->private->view);
262 view_object->private->menu = GTK_WIDGET(new_menu (view_object));
264 g_signal_connect (G_OBJECT (object), "moved",
265 G_CALLBACK (object_moved_cb),
268 g_signal_connect (G_OBJECT (object), "top",
269 G_CALLBACK (raise_object_cb),
272 g_signal_connect (G_OBJECT (object), "bottom",
273 G_CALLBACK (lower_object_cb),
276 g_signal_connect (G_OBJECT (object), "flip_rotate",
277 G_CALLBACK (flip_rotate_object_cb),
280 g_signal_connect (G_OBJECT (view_object->private->group), "event",
281 G_CALLBACK (gl_view_item_event_handler),
284 gl_debug (DEBUG_VIEW, "END");
287 /*****************************************************************************/
288 /* Set dialog for controlling/viewing object properties. */
289 /*****************************************************************************/
291 gl_view_object_set_dlg_constructor (glViewObject *view_object,
292 glViewObjectDlgConstructor dlg_constructor)
295 gl_debug (DEBUG_VIEW, "START");
297 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
299 view_object->private->dialog_constructor = dlg_constructor;
301 gl_debug (DEBUG_VIEW, "END");
304 /*****************************************************************************/
305 /* Return parent view associated with this view. */
306 /*****************************************************************************/
308 gl_view_object_get_view (glViewObject *view_object)
310 gl_debug (DEBUG_VIEW, "START");
312 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
314 gl_debug (DEBUG_VIEW, "END");
316 return view_object->private->view;
319 /*****************************************************************************/
320 /* Return label object that we are following. */
321 /*****************************************************************************/
323 gl_view_object_get_object (glViewObject *view_object)
325 gl_debug (DEBUG_VIEW, "START");
327 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
329 gl_debug (DEBUG_VIEW, "END");
331 return view_object->private->object;
334 /*****************************************************************************/
335 /* Return canvas item representing our object in this view. */
336 /*****************************************************************************/
338 gl_view_object_get_group (glViewObject *view_object)
340 gl_debug (DEBUG_VIEW, "START");
342 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
344 gl_debug (DEBUG_VIEW, "END");
346 return view_object->private->group;
349 /*****************************************************************************/
350 /* Create canvas item for this object. */
351 /*****************************************************************************/
353 gl_view_object_item_new (glViewObject *view_object,
355 const gchar *first_arg_name,
358 GnomeCanvasItem *item;
361 gl_debug (DEBUG_VIEW, "START");
363 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
365 item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(view_object->private->group),
368 va_start (args, first_arg_name);
369 gnome_canvas_item_set_valist (item, first_arg_name, args);
372 g_print ("Affine = {%f, %f, %f, %f, %f, %f}\n",
373 view_object->private->affine[0],
374 view_object->private->affine[1],
375 view_object->private->affine[2],
376 view_object->private->affine[3],
377 view_object->private->affine[4],
378 view_object->private->affine[5]);
381 gnome_canvas_item_affine_absolute (item, view_object->private->affine);
384 gl_debug (DEBUG_VIEW, "END");
389 /*****************************************************************************/
390 /* Return dialog for controlling/viewing object properties. */
391 /*****************************************************************************/
393 gl_view_object_get_dialog (glViewObject *view_object)
395 gl_debug (DEBUG_VIEW, "START");
397 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
399 gl_debug (DEBUG_VIEW, "END");
401 return view_object->private->property_dialog;
404 /*****************************************************************************/
405 /* Popup menu for this object. */
406 /*****************************************************************************/
408 gl_view_object_get_menu (glViewObject *view_object)
410 gl_debug (DEBUG_VIEW, "START");
412 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
414 gl_debug (DEBUG_VIEW, "END");
416 return GTK_MENU(view_object->private->menu);
419 /*****************************************************************************/
420 /* Highlight view of object. */
421 /*****************************************************************************/
423 gl_view_object_show_highlight (glViewObject *view_object)
425 gl_debug (DEBUG_VIEW, "START");
427 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
428 g_return_if_fail (view_object->private->highlight);
430 gl_view_highlight_show (view_object->private->highlight);
432 gl_debug (DEBUG_VIEW, "END");
435 /*****************************************************************************/
436 /* Remove highlight from view of object. */
437 /*****************************************************************************/
439 gl_view_object_hide_highlight (glViewObject *view_object)
441 gl_debug (DEBUG_VIEW, "START");
443 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
444 g_return_if_fail (view_object->private->highlight);
446 gl_view_highlight_hide (view_object->private->highlight);
448 gl_debug (DEBUG_VIEW, "END");
452 /*---------------------------------------------------------------------------*/
453 /* Create a popup menu for this object view. */
454 /*---------------------------------------------------------------------------*/
456 new_menu (glViewObject *view_object)
458 GtkWidget *menu, *menuitem;
460 gl_debug (DEBUG_VIEW, "START");
462 g_return_val_if_fail (view_object && GL_VIEW_OBJECT(view_object), NULL);
464 menu = gtk_menu_new ();
466 menuitem = gtk_menu_item_new_with_label (_("Edit properties..."));
467 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
468 gtk_widget_show (menuitem);
469 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
470 G_CALLBACK (gl_view_object_show_dialog),
473 menuitem = gtk_menu_item_new ();
474 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
475 gtk_widget_show (menuitem);
477 menuitem = gtk_menu_item_new_with_label (_("Delete"));
478 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
479 gtk_widget_show (menuitem);
480 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
481 G_CALLBACK (g_object_unref), view_object);
483 menuitem = gtk_menu_item_new ();
484 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
485 gtk_widget_show (menuitem);
487 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
488 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
489 gtk_widget_show (menuitem);
490 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
491 G_CALLBACK (gl_label_object_raise_to_top),
492 view_object->private->object);
494 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
495 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
496 gtk_widget_show (menuitem);
497 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
498 G_CALLBACK (gl_label_object_lower_to_bottom),
499 view_object->private->object);
501 gl_debug (DEBUG_VIEW, "END");
503 return GTK_MENU(menu);
506 /*****************************************************************************/
507 /* Show property dialog. */
508 /*****************************************************************************/
510 gl_view_object_show_dialog (glViewObject *view_object)
512 gl_debug (DEBUG_VIEW, "START");
514 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
516 if (view_object->private->property_dialog != NULL) {
517 gtk_window_present (GTK_WINDOW (view_object->private->property_dialog));
521 view_object->private->property_dialog =
522 view_object->private->dialog_constructor (view_object);
524 g_signal_connect (G_OBJECT (view_object->private->property_dialog),
526 G_CALLBACK (gtk_widget_destroyed),
527 &view_object->private->property_dialog);
529 gtk_widget_show_all (view_object->private->property_dialog);
532 gl_debug (DEBUG_VIEW, "END");
536 /*---------------------------------------------------------------------------*/
537 /* PRIVATE. Object moved callback. */
538 /*---------------------------------------------------------------------------*/
540 object_moved_cb (glLabelObject *object,
543 glViewObject *view_object)
545 GnomeCanvasItem *item, *highlight;
547 gl_debug (DEBUG_VIEW, "START");
549 /* Adjust location of analogous canvas group. */
550 gnome_canvas_item_move (view_object->private->group, dx, dy);
552 gl_debug (DEBUG_VIEW, "END");
555 /*---------------------------------------------------------------------------*/
556 /* PRIVATE. raise item to front callback. */
557 /*---------------------------------------------------------------------------*/
559 raise_object_cb (GtkWidget *widget,
560 glViewObject *view_object)
562 glLabelObject *object;
564 gl_debug (DEBUG_VIEW, "START");
567 gnome_canvas_item_raise_to_top (view_object->private->group);
569 /* send highlight to top */
570 gl_view_highlight_show (view_object->private->highlight);
572 gl_debug (DEBUG_VIEW, "END");
575 /*---------------------------------------------------------------------------*/
576 /* PRIVATE. lower item to back callback. */
577 /*---------------------------------------------------------------------------*/
579 lower_object_cb (GtkWidget *widget,
580 glViewObject *view_object)
582 glLabelObject *object;
585 gl_debug (DEBUG_VIEW, "START");
588 gnome_canvas_item_lower_to_bottom (view_object->private->group);
590 /* now raise it above all items that form the backgound */
591 gnome_canvas_item_raise (view_object->private->group,
592 view_object->private->view->n_bg_items);
594 gl_debug (DEBUG_VIEW, "END");
597 /*---------------------------------------------------------------------------*/
598 /* PRIVATE. Flip/rotate object callback. */
599 /*---------------------------------------------------------------------------*/
601 flip_rotate_object_cb (GtkWidget *widget,
602 glLabelObjectFlip flip,
604 glViewObject *view_object)
606 glLabelObject *object;
609 GList *p, *item_list;
610 GnomeCanvasItem *item;
612 gl_debug (DEBUG_VIEW, "START");
614 gl_label_object_get_size (view_object->private->object, &w, &h);
616 /* Reset to identity affine */
617 art_affine_identity (view_object->private->affine);
619 /* Apply appropriate flipping */
620 if ( flip & GL_LABEL_OBJECT_FLIP_HORIZ ) {
621 art_affine_translate (a, -w, 0.0);
622 art_affine_multiply (view_object->private->affine, view_object->private->affine, a);
623 art_affine_scale (a, -1.0, 1.0);
624 art_affine_multiply (view_object->private->affine,
625 view_object->private->affine, a);
627 if ( flip & GL_LABEL_OBJECT_FLIP_VERT ) {
628 art_affine_translate (a, 0.0, -h);
629 art_affine_multiply (view_object->private->affine,
630 view_object->private->affine, a);
631 art_affine_scale (a, 1.0, -1.0);
632 art_affine_multiply (view_object->private->affine,
633 view_object->private->affine, a);
637 /* Apply newly constructed affine */
638 item_list = GNOME_CANVAS_GROUP(view_object->private->group)->item_list;
639 for ( p=item_list; p != NULL; p=p->next) {
640 item = GNOME_CANVAS_ITEM(p->data);
641 gnome_canvas_item_affine_absolute (item, view_object->private->affine);
645 gl_debug (DEBUG_VIEW, "END");
648 /*****************************************************************************/
650 /*****************************************************************************/
652 gl_view_object_select (glViewObject *view_object)
654 gl_debug (DEBUG_VIEW, "START");
656 gl_view_select_object(view_object->private->view, view_object);
658 gl_debug (DEBUG_VIEW, "END");