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 /*========================================================*/
31 /* Private constants and macros. */
32 /*========================================================*/
34 /* Used for a workaround for a bug with images when flipped or rotated by 90 degrees. */
35 #define DELTA_DEG 0.001
37 /*========================================================*/
39 /*========================================================*/
41 struct _glViewObjectPrivate {
44 glLabelObject *object;
46 GnomeCanvasItem *group;
47 glViewHighlight *highlight;
50 GtkWidget *property_dialog;
52 glViewObjectDlgConstructor dialog_constructor;
55 /*========================================================*/
56 /* Private globals. */
57 /*========================================================*/
59 static GObjectClass *parent_class = NULL;
62 /*========================================================*/
63 /* Private function prototypes. */
64 /*========================================================*/
66 static void gl_view_object_class_init (glViewObjectClass *klass);
67 static void gl_view_object_instance_init (glViewObject *view_object);
68 static void gl_view_object_finalize (GObject *object);
70 static GtkMenu *new_menu (glViewObject *view_object);
72 static void object_moved_cb (glLabelObject *object,
75 glViewObject *view_object);
77 static void raise_object_cb (glLabelObject *object,
78 glViewObject *view_object);
80 static void lower_object_cb (glLabelObject *object,
81 glViewObject *view_object);
83 static void flip_rotate_object_cb (glLabelObject *object,
84 glViewObject *view_object);
88 /*****************************************************************************/
89 /* Boilerplate object stuff. */
90 /*****************************************************************************/
92 gl_view_object_get_type (void)
94 static GType type = 0;
98 sizeof (glViewObjectClass),
101 (GClassInitFunc) gl_view_object_class_init,
104 sizeof (glViewObject),
106 (GInstanceInitFunc) gl_view_object_instance_init,
109 type = g_type_register_static (G_TYPE_OBJECT,
110 "glViewObject", &info, 0);
117 gl_view_object_class_init (glViewObjectClass *klass)
119 GObjectClass *object_class = (GObjectClass *) klass;
121 gl_debug (DEBUG_VIEW, "START");
123 parent_class = g_type_class_peek_parent (klass);
125 object_class->finalize = gl_view_object_finalize;
127 gl_debug (DEBUG_VIEW, "END");
131 gl_view_object_instance_init (glViewObject *view_object)
133 gl_debug (DEBUG_VIEW, "START");
135 view_object->private = g_new0 (glViewObjectPrivate, 1);
137 gl_debug (DEBUG_VIEW, "END");
141 gl_view_object_finalize (GObject *object)
146 gl_debug (DEBUG_VIEW, "START");
148 g_return_if_fail (object && GL_IS_VIEW_OBJECT (object));
150 view = GL_VIEW_OBJECT(object)->private->view;
151 view->object_list = g_list_remove (view->object_list, object);
152 view->selected_object_list =
153 g_list_remove (view->selected_object_list, object);
155 g_object_unref (GL_VIEW_OBJECT(object)->private->object);
156 g_object_unref (G_OBJECT(GL_VIEW_OBJECT(object)->private->highlight));
157 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->group));
158 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->menu));
159 if (GL_VIEW_OBJECT(object)->private->property_dialog) {
160 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->property_dialog));
163 G_OBJECT_CLASS (parent_class)->finalize (object);
165 gl_debug (DEBUG_VIEW, "END");
168 /*****************************************************************************/
169 /* NEW object view. */
170 /*****************************************************************************/
172 gl_view_object_new (void)
174 glViewObject *view_object;
176 gl_debug (DEBUG_VIEW, "START");
178 view_object = g_object_new (gl_view_object_get_type(), NULL);
180 gl_debug (DEBUG_VIEW, "END");
182 return G_OBJECT (view_object);
185 /*****************************************************************************/
186 /* Set parent view to which this object view belongs. */
187 /*****************************************************************************/
189 gl_view_object_set_view (glViewObject *view_object,
192 gl_debug (DEBUG_VIEW, "START");
194 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
195 g_return_if_fail (view && GL_IS_VIEW (view));
197 view_object->private->view = view;
199 view->object_list = g_list_prepend (view->object_list, view_object);
201 gl_debug (DEBUG_VIEW, "END");
204 /*****************************************************************************/
205 /* Set Label object to follow. */
206 /*****************************************************************************/
208 gl_view_object_set_object (glViewObject *view_object,
209 glLabelObject *object,
210 glViewHighlightStyle style)
213 GnomeCanvasGroup *root;
216 gl_debug (DEBUG_VIEW, "START");
218 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
219 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
221 view_object->private->object = object;
223 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
224 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
226 /* create canvas group to contain items representing object */
227 view_object->private->group =
228 gnome_canvas_item_new (view_object->private->view->label_group,
229 gnome_canvas_group_get_type (),
234 /* Create appropriate selection highlight canvas item. */
235 view_object->private->highlight =
236 GL_VIEW_HIGHLIGHT (gl_view_highlight_new (view_object, style));
238 view_object->private->menu = GTK_WIDGET(new_menu (view_object));
240 g_signal_connect (G_OBJECT (object), "moved",
241 G_CALLBACK (object_moved_cb),
244 g_signal_connect (G_OBJECT (object), "top",
245 G_CALLBACK (raise_object_cb),
248 g_signal_connect (G_OBJECT (object), "bottom",
249 G_CALLBACK (lower_object_cb),
252 g_signal_connect (G_OBJECT (object), "flip_rotate",
253 G_CALLBACK (flip_rotate_object_cb),
256 g_signal_connect (G_OBJECT (view_object->private->group), "event",
257 G_CALLBACK (gl_view_item_event_handler),
260 gl_debug (DEBUG_VIEW, "END");
263 /*****************************************************************************/
264 /* Set dialog for controlling/viewing object properties. */
265 /*****************************************************************************/
267 gl_view_object_set_dlg_constructor (glViewObject *view_object,
268 glViewObjectDlgConstructor dlg_constructor)
271 gl_debug (DEBUG_VIEW, "START");
273 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
275 view_object->private->dialog_constructor = dlg_constructor;
277 gl_debug (DEBUG_VIEW, "END");
280 /*****************************************************************************/
281 /* Return parent view associated with this view. */
282 /*****************************************************************************/
284 gl_view_object_get_view (glViewObject *view_object)
286 gl_debug (DEBUG_VIEW, "START");
288 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
290 gl_debug (DEBUG_VIEW, "END");
292 return view_object->private->view;
295 /*****************************************************************************/
296 /* Return label object that we are following. */
297 /*****************************************************************************/
299 gl_view_object_get_object (glViewObject *view_object)
301 gl_debug (DEBUG_VIEW, "START");
303 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
305 gl_debug (DEBUG_VIEW, "END");
307 return view_object->private->object;
310 /*****************************************************************************/
311 /* Return canvas item representing our object in this view. */
312 /*****************************************************************************/
314 gl_view_object_get_group (glViewObject *view_object)
316 gl_debug (DEBUG_VIEW, "START");
318 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
320 gl_debug (DEBUG_VIEW, "END");
322 return view_object->private->group;
325 /*****************************************************************************/
326 /* Create canvas item for this object. */
327 /*****************************************************************************/
329 gl_view_object_item_new (glViewObject *view_object,
331 const gchar *first_arg_name,
334 GnomeCanvasItem *item;
336 gdouble affine[6], delta_affine[6];
338 gl_debug (DEBUG_VIEW, "START");
340 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
342 item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(view_object->private->group),
345 va_start (args, first_arg_name);
346 gnome_canvas_item_set_valist (item, first_arg_name, args);
349 gl_label_object_get_applied_affine (view_object->private->object, affine);
351 /* Apply a very small rotation, fixes problems with flipped or rotated images */
352 art_affine_rotate (delta_affine, DELTA_DEG);
353 art_affine_multiply (affine, affine, delta_affine);
355 gnome_canvas_item_affine_absolute (item, affine);
357 gl_debug (DEBUG_VIEW, "END");
362 /*****************************************************************************/
363 /* Return dialog for controlling/viewing object properties. */
364 /*****************************************************************************/
366 gl_view_object_get_dialog (glViewObject *view_object)
368 gl_debug (DEBUG_VIEW, "START");
370 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
372 gl_debug (DEBUG_VIEW, "END");
374 return view_object->private->property_dialog;
377 /*****************************************************************************/
378 /* Popup menu for this object. */
379 /*****************************************************************************/
381 gl_view_object_get_menu (glViewObject *view_object)
383 gl_debug (DEBUG_VIEW, "START");
385 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
387 gl_debug (DEBUG_VIEW, "END");
389 return GTK_MENU(view_object->private->menu);
392 /*****************************************************************************/
393 /* Highlight view of object. */
394 /*****************************************************************************/
396 gl_view_object_show_highlight (glViewObject *view_object)
398 gl_debug (DEBUG_VIEW, "START");
400 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
401 g_return_if_fail (view_object->private->highlight);
403 gl_view_highlight_show (view_object->private->highlight);
405 gl_debug (DEBUG_VIEW, "END");
408 /*****************************************************************************/
409 /* Remove highlight from view of object. */
410 /*****************************************************************************/
412 gl_view_object_hide_highlight (glViewObject *view_object)
414 gl_debug (DEBUG_VIEW, "START");
416 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
417 g_return_if_fail (view_object->private->highlight);
419 gl_view_highlight_hide (view_object->private->highlight);
421 gl_debug (DEBUG_VIEW, "END");
425 /*---------------------------------------------------------------------------*/
426 /* Create a popup menu for this object view. */
427 /*---------------------------------------------------------------------------*/
429 new_menu (glViewObject *view_object)
431 GtkWidget *menu, *menuitem;
433 gl_debug (DEBUG_VIEW, "START");
435 g_return_val_if_fail (view_object && GL_VIEW_OBJECT(view_object), NULL);
437 menu = gtk_menu_new ();
439 menuitem = gtk_menu_item_new_with_label (_("Edit properties..."));
440 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
441 gtk_widget_show (menuitem);
442 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
443 G_CALLBACK (gl_view_object_show_dialog),
446 menuitem = gtk_menu_item_new ();
447 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
448 gtk_widget_show (menuitem);
450 menuitem = gtk_menu_item_new_with_label (_("Delete"));
451 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
452 gtk_widget_show (menuitem);
453 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
454 G_CALLBACK (g_object_unref), view_object);
456 menuitem = gtk_menu_item_new ();
457 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
458 gtk_widget_show (menuitem);
460 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
461 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
462 gtk_widget_show (menuitem);
463 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
464 G_CALLBACK (gl_label_object_raise_to_top),
465 view_object->private->object);
467 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
468 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
469 gtk_widget_show (menuitem);
470 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
471 G_CALLBACK (gl_label_object_lower_to_bottom),
472 view_object->private->object);
474 gl_debug (DEBUG_VIEW, "END");
476 return GTK_MENU(menu);
479 /*****************************************************************************/
480 /* Show property dialog. */
481 /*****************************************************************************/
483 gl_view_object_show_dialog (glViewObject *view_object)
485 gl_debug (DEBUG_VIEW, "START");
487 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
489 if (view_object->private->property_dialog != NULL) {
490 gtk_window_present (GTK_WINDOW (view_object->private->property_dialog));
494 view_object->private->property_dialog =
495 view_object->private->dialog_constructor (view_object);
497 g_signal_connect (G_OBJECT (view_object->private->property_dialog),
499 G_CALLBACK (gtk_widget_destroyed),
500 &view_object->private->property_dialog);
502 gtk_widget_show_all (view_object->private->property_dialog);
505 gl_debug (DEBUG_VIEW, "END");
509 /*---------------------------------------------------------------------------*/
510 /* PRIVATE. Object moved callback. */
511 /*---------------------------------------------------------------------------*/
513 object_moved_cb (glLabelObject *object,
516 glViewObject *view_object)
518 gl_debug (DEBUG_VIEW, "START");
520 /* Adjust location of analogous canvas group. */
521 gnome_canvas_item_move (view_object->private->group, dx, dy);
523 gl_debug (DEBUG_VIEW, "END");
526 /*---------------------------------------------------------------------------*/
527 /* PRIVATE. raise item to front callback. */
528 /*---------------------------------------------------------------------------*/
530 raise_object_cb (glLabelObject *object,
531 glViewObject *view_object)
533 gl_debug (DEBUG_VIEW, "START");
536 gnome_canvas_item_raise_to_top (view_object->private->group);
538 gl_debug (DEBUG_VIEW, "END");
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE. lower item to back callback. */
543 /*---------------------------------------------------------------------------*/
545 lower_object_cb (glLabelObject *object,
546 glViewObject *view_object)
548 gl_debug (DEBUG_VIEW, "START");
551 gnome_canvas_item_lower_to_bottom (view_object->private->group);
553 gl_debug (DEBUG_VIEW, "END");
556 /*---------------------------------------------------------------------------*/
557 /* PRIVATE. Flip/rotate object callback. */
558 /*---------------------------------------------------------------------------*/
560 flip_rotate_object_cb (glLabelObject *object,
561 glViewObject *view_object)
563 gdouble affine[6], delta_affine[6];
565 GList *p, *item_list;
566 GnomeCanvasItem *item;
568 gl_debug (DEBUG_VIEW, "START");
570 gl_label_object_get_applied_affine (object, affine);
572 /* Apply a very small rotation, fixes problems with flipped or rotated images */
573 art_affine_rotate (delta_affine, DELTA_DEG);
574 art_affine_multiply (affine, affine, delta_affine);
576 item_list = GNOME_CANVAS_GROUP(view_object->private->group)->item_list;
577 for ( p=item_list; p != NULL; p=p->next ) {
578 item = GNOME_CANVAS_ITEM(p->data);
579 gnome_canvas_item_affine_absolute (item, affine);
582 gl_debug (DEBUG_VIEW, "END");
585 /*****************************************************************************/
587 /*****************************************************************************/
589 gl_view_object_select (glViewObject *view_object)
591 gl_debug (DEBUG_VIEW, "START");
593 gl_view_select_object(view_object->private->view, view_object);
595 gl_debug (DEBUG_VIEW, "END");