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;
53 /*========================================================*/
54 /* Private globals. */
55 /*========================================================*/
57 static GObjectClass *parent_class = NULL;
60 /*========================================================*/
61 /* Private function prototypes. */
62 /*========================================================*/
64 static void gl_view_object_class_init (glViewObjectClass *klass);
65 static void gl_view_object_instance_init (glViewObject *view_object);
66 static void gl_view_object_finalize (GObject *object);
68 static GtkMenu *new_menu (glViewObject *view_object);
70 static void object_moved_cb (glLabelObject *object,
73 glViewObject *view_object);
75 static void raise_object_cb (glLabelObject *object,
76 glViewObject *view_object);
78 static void lower_object_cb (glLabelObject *object,
79 glViewObject *view_object);
81 static void flip_rotate_object_cb (glLabelObject *object,
82 glViewObject *view_object);
86 /*****************************************************************************/
87 /* Boilerplate object stuff. */
88 /*****************************************************************************/
90 gl_view_object_get_type (void)
92 static GType type = 0;
96 sizeof (glViewObjectClass),
99 (GClassInitFunc) gl_view_object_class_init,
102 sizeof (glViewObject),
104 (GInstanceInitFunc) gl_view_object_instance_init,
107 type = g_type_register_static (G_TYPE_OBJECT,
108 "glViewObject", &info, 0);
115 gl_view_object_class_init (glViewObjectClass *klass)
117 GObjectClass *object_class = (GObjectClass *) klass;
119 gl_debug (DEBUG_VIEW, "START");
121 parent_class = g_type_class_peek_parent (klass);
123 object_class->finalize = gl_view_object_finalize;
125 gl_debug (DEBUG_VIEW, "END");
129 gl_view_object_instance_init (glViewObject *view_object)
131 gl_debug (DEBUG_VIEW, "START");
133 view_object->private = g_new0 (glViewObjectPrivate, 1);
135 gl_debug (DEBUG_VIEW, "END");
139 gl_view_object_finalize (GObject *object)
144 gl_debug (DEBUG_VIEW, "START");
146 g_return_if_fail (object && GL_IS_VIEW_OBJECT (object));
148 view = GL_VIEW_OBJECT(object)->private->view;
149 view->object_list = g_list_remove (view->object_list, object);
150 view->selected_object_list =
151 g_list_remove (view->selected_object_list, object);
153 g_object_unref (GL_VIEW_OBJECT(object)->private->object);
154 g_object_unref (G_OBJECT(GL_VIEW_OBJECT(object)->private->highlight));
155 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->group));
156 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->menu));
157 if (GL_VIEW_OBJECT(object)->private->property_dialog) {
158 gtk_object_destroy (GTK_OBJECT(GL_VIEW_OBJECT(object)->private->property_dialog));
161 G_OBJECT_CLASS (parent_class)->finalize (object);
163 gl_debug (DEBUG_VIEW, "END");
166 /*****************************************************************************/
167 /* NEW object view. */
168 /*****************************************************************************/
170 gl_view_object_new (void)
172 glViewObject *view_object;
174 gl_debug (DEBUG_VIEW, "START");
176 view_object = g_object_new (gl_view_object_get_type(), NULL);
178 gl_debug (DEBUG_VIEW, "END");
180 return G_OBJECT (view_object);
183 /*****************************************************************************/
184 /* Set parent view to which this object view belongs. */
185 /*****************************************************************************/
187 gl_view_object_set_view (glViewObject *view_object,
190 gl_debug (DEBUG_VIEW, "START");
192 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
193 g_return_if_fail (view && GL_IS_VIEW (view));
195 view_object->private->view = view;
197 view->object_list = g_list_prepend (view->object_list, view_object);
199 gl_debug (DEBUG_VIEW, "END");
202 /*****************************************************************************/
203 /* Set Label object to follow. */
204 /*****************************************************************************/
206 gl_view_object_set_object (glViewObject *view_object,
207 glLabelObject *object,
208 glViewHighlightStyle style)
211 GnomeCanvasGroup *root;
214 gl_debug (DEBUG_VIEW, "START");
216 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
217 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
219 view_object->private->object = object;
221 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
222 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
224 /* create canvas group to contain items representing object */
225 view_object->private->group =
226 gnome_canvas_item_new (view_object->private->view->label_group,
227 gnome_canvas_group_get_type (),
232 /* Create appropriate selection highlight canvas item. */
233 view_object->private->highlight =
234 GL_VIEW_HIGHLIGHT (gl_view_highlight_new (view_object, style));
236 view_object->private->menu = GTK_WIDGET(new_menu (view_object));
238 g_signal_connect (G_OBJECT (object), "moved",
239 G_CALLBACK (object_moved_cb),
242 g_signal_connect (G_OBJECT (object), "top",
243 G_CALLBACK (raise_object_cb),
246 g_signal_connect (G_OBJECT (object), "bottom",
247 G_CALLBACK (lower_object_cb),
250 g_signal_connect (G_OBJECT (object), "flip_rotate",
251 G_CALLBACK (flip_rotate_object_cb),
254 g_signal_connect (G_OBJECT (view_object->private->group), "event",
255 G_CALLBACK (gl_view_item_event_handler),
258 gl_debug (DEBUG_VIEW, "END");
261 /*****************************************************************************/
262 /* Return parent view associated with this view. */
263 /*****************************************************************************/
265 gl_view_object_get_view (glViewObject *view_object)
267 gl_debug (DEBUG_VIEW, "START");
269 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
271 gl_debug (DEBUG_VIEW, "END");
273 return view_object->private->view;
276 /*****************************************************************************/
277 /* Return label object that we are following. */
278 /*****************************************************************************/
280 gl_view_object_get_object (glViewObject *view_object)
282 gl_debug (DEBUG_VIEW, "START");
284 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
286 gl_debug (DEBUG_VIEW, "END");
288 return view_object->private->object;
291 /*****************************************************************************/
292 /* Return canvas item representing our object in this view. */
293 /*****************************************************************************/
295 gl_view_object_get_group (glViewObject *view_object)
297 gl_debug (DEBUG_VIEW, "START");
299 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
301 gl_debug (DEBUG_VIEW, "END");
303 return view_object->private->group;
306 /*****************************************************************************/
307 /* Create canvas item for this object. */
308 /*****************************************************************************/
310 gl_view_object_item_new (glViewObject *view_object,
312 const gchar *first_arg_name,
315 GnomeCanvasItem *item;
317 gdouble affine[6], delta_affine[6];
319 gl_debug (DEBUG_VIEW, "START");
321 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
323 item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(view_object->private->group),
326 va_start (args, first_arg_name);
327 gnome_canvas_item_set_valist (item, first_arg_name, args);
330 gl_label_object_get_applied_affine (view_object->private->object, affine);
332 /* Apply a very small rotation, fixes problems with flipped or rotated images */
333 art_affine_rotate (delta_affine, DELTA_DEG);
334 art_affine_multiply (affine, affine, delta_affine);
336 gnome_canvas_item_affine_absolute (item, affine);
338 gl_debug (DEBUG_VIEW, "END");
343 /*****************************************************************************/
344 /* Return dialog for controlling/viewing object properties. */
345 /*****************************************************************************/
347 gl_view_object_get_dialog (glViewObject *view_object)
349 gl_debug (DEBUG_VIEW, "START");
351 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
353 gl_debug (DEBUG_VIEW, "END");
355 return view_object->private->property_dialog;
358 /*****************************************************************************/
359 /* Popup menu for this object. */
360 /*****************************************************************************/
362 gl_view_object_get_menu (glViewObject *view_object)
364 gl_debug (DEBUG_VIEW, "START");
366 g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
368 gl_debug (DEBUG_VIEW, "END");
370 return GTK_MENU(view_object->private->menu);
373 /*****************************************************************************/
374 /* Highlight view of object. */
375 /*****************************************************************************/
377 gl_view_object_show_highlight (glViewObject *view_object)
379 gl_debug (DEBUG_VIEW, "START");
381 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
382 g_return_if_fail (view_object->private->highlight);
384 gl_view_highlight_show (view_object->private->highlight);
386 gl_debug (DEBUG_VIEW, "END");
389 /*****************************************************************************/
390 /* Remove highlight from view of object. */
391 /*****************************************************************************/
393 gl_view_object_hide_highlight (glViewObject *view_object)
395 gl_debug (DEBUG_VIEW, "START");
397 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
398 g_return_if_fail (view_object->private->highlight);
400 gl_view_highlight_hide (view_object->private->highlight);
402 gl_debug (DEBUG_VIEW, "END");
406 /*---------------------------------------------------------------------------*/
407 /* Create a popup menu for this object view. */
408 /*---------------------------------------------------------------------------*/
410 new_menu (glViewObject *view_object)
412 GtkWidget *menu, *menuitem;
414 gl_debug (DEBUG_VIEW, "START");
416 g_return_val_if_fail (view_object && GL_VIEW_OBJECT(view_object), NULL);
418 menu = gtk_menu_new ();
420 menuitem = gtk_menu_item_new_with_label (_("Edit properties..."));
421 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
422 gtk_widget_show (menuitem);
423 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
424 G_CALLBACK (gl_view_object_show_dialog),
427 menuitem = gtk_menu_item_new ();
428 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
429 gtk_widget_show (menuitem);
431 menuitem = gtk_menu_item_new_with_label (_("Delete"));
432 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
433 gtk_widget_show (menuitem);
434 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
435 G_CALLBACK (g_object_unref), view_object);
437 menuitem = gtk_menu_item_new ();
438 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
439 gtk_widget_show (menuitem);
441 menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
442 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
443 gtk_widget_show (menuitem);
444 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
445 G_CALLBACK (gl_label_object_raise_to_top),
446 view_object->private->object);
448 menuitem = gtk_menu_item_new_with_label (_("Send to back"));
449 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
450 gtk_widget_show (menuitem);
451 g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
452 G_CALLBACK (gl_label_object_lower_to_bottom),
453 view_object->private->object);
455 gl_debug (DEBUG_VIEW, "END");
457 return GTK_MENU(menu);
460 /*****************************************************************************/
461 /* Show property dialog. */
462 /*****************************************************************************/
464 gl_view_object_show_dialog (glViewObject *view_object)
466 gl_debug (DEBUG_VIEW, "START");
468 g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
470 if (view_object->private->property_dialog != NULL) {
471 gtk_window_present (GTK_WINDOW (view_object->private->property_dialog));
475 if ( GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_dialog != NULL ) {
477 view_object->private->property_dialog =
478 GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_dialog (view_object);
480 g_signal_connect (G_OBJECT (view_object->private->property_dialog),
482 G_CALLBACK (gtk_widget_destroyed),
483 &view_object->private->property_dialog);
485 gtk_widget_show_all (view_object->private->property_dialog);
490 gl_debug (DEBUG_VIEW, "END");
494 /*---------------------------------------------------------------------------*/
495 /* PRIVATE. Object moved callback. */
496 /*---------------------------------------------------------------------------*/
498 object_moved_cb (glLabelObject *object,
501 glViewObject *view_object)
503 gl_debug (DEBUG_VIEW, "START");
505 /* Adjust location of analogous canvas group. */
506 gnome_canvas_item_move (view_object->private->group, dx, dy);
508 gl_debug (DEBUG_VIEW, "END");
511 /*---------------------------------------------------------------------------*/
512 /* PRIVATE. raise item to front callback. */
513 /*---------------------------------------------------------------------------*/
515 raise_object_cb (glLabelObject *object,
516 glViewObject *view_object)
518 gl_debug (DEBUG_VIEW, "START");
521 gnome_canvas_item_raise_to_top (view_object->private->group);
523 gl_debug (DEBUG_VIEW, "END");
526 /*---------------------------------------------------------------------------*/
527 /* PRIVATE. lower item to back callback. */
528 /*---------------------------------------------------------------------------*/
530 lower_object_cb (glLabelObject *object,
531 glViewObject *view_object)
533 gl_debug (DEBUG_VIEW, "START");
536 gnome_canvas_item_lower_to_bottom (view_object->private->group);
538 gl_debug (DEBUG_VIEW, "END");
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE. Flip/rotate object callback. */
543 /*---------------------------------------------------------------------------*/
545 flip_rotate_object_cb (glLabelObject *object,
546 glViewObject *view_object)
548 gdouble affine[6], delta_affine[6];
550 GList *p, *item_list;
551 GnomeCanvasItem *item;
553 gl_debug (DEBUG_VIEW, "START");
555 gl_label_object_get_applied_affine (object, affine);
557 /* Apply a very small rotation, fixes problems with flipped or rotated images */
558 art_affine_rotate (delta_affine, DELTA_DEG);
559 art_affine_multiply (affine, affine, delta_affine);
561 item_list = GNOME_CANVAS_GROUP(view_object->private->group)->item_list;
562 for ( p=item_list; p != NULL; p=p->next ) {
563 item = GNOME_CANVAS_ITEM(p->data);
564 gnome_canvas_item_affine_absolute (item, affine);
567 gl_debug (DEBUG_VIEW, "END");
570 /*****************************************************************************/
572 /*****************************************************************************/
574 gl_view_object_select (glViewObject *view_object)
576 gl_debug (DEBUG_VIEW, "START");
578 gl_view_select_object(view_object->private->view, view_object);
580 gl_debug (DEBUG_VIEW, "END");