]> git.sur5r.net Git - glabels/blob - glabels2/src/view-object.c
Made set_size and get_size into child methods for label-object, and construct_dialog...
[glabels] / glabels2 / src / view-object.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  view_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
23 #include <glib.h>
24
25 #include "view-object.h"
26 #include "libart_lgpl/libart.h"
27
28 #include "debug.h"
29
30 /*========================================================*/
31 /* Private constants and macros.                          */
32 /*========================================================*/
33
34 /* Used for a workaround for a bug with images when flipped or rotated by 90 degrees. */
35 #define DELTA_DEG 0.001
36
37 /*========================================================*/
38 /* Private types.                                         */
39 /*========================================================*/
40
41 struct _glViewObjectPrivate {
42
43         glView                     *view;
44         glLabelObject              *object;
45
46         GnomeCanvasItem            *group;
47         glViewHighlight            *highlight;
48
49         GtkWidget                  *menu;
50         GtkWidget                  *property_dialog;
51 };
52
53 /*========================================================*/
54 /* Private globals.                                       */
55 /*========================================================*/
56
57 static GObjectClass *parent_class = NULL;
58
59
60 /*========================================================*/
61 /* Private function prototypes.                           */
62 /*========================================================*/
63
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);
67
68 static GtkMenu *new_menu                     (glViewObject        *view_object);
69
70 static void     object_moved_cb              (glLabelObject       *object,
71                                               gdouble              x,
72                                               gdouble              y,
73                                               glViewObject        *view_object);
74
75 static void     raise_object_cb              (glLabelObject       *object,
76                                               glViewObject        *view_object);
77
78 static void     lower_object_cb              (glLabelObject       *object,
79                                               glViewObject        *view_object);
80
81 static void     flip_rotate_object_cb        (glLabelObject       *object,
82                                               glViewObject        *view_object);
83
84
85 \f
86 /*****************************************************************************/
87 /* Boilerplate object stuff.                                                 */
88 /*****************************************************************************/
89 GType
90 gl_view_object_get_type (void)
91 {
92         static GType type = 0;
93
94         if (!type) {
95                 GTypeInfo info = {
96                         sizeof (glViewObjectClass),
97                         NULL,
98                         NULL,
99                         (GClassInitFunc) gl_view_object_class_init,
100                         NULL,
101                         NULL,
102                         sizeof (glViewObject),
103                         0,
104                         (GInstanceInitFunc) gl_view_object_instance_init,
105                 };
106
107                 type = g_type_register_static (G_TYPE_OBJECT,
108                                                "glViewObject", &info, 0);
109         }
110
111         return type;
112 }
113
114 static void
115 gl_view_object_class_init (glViewObjectClass *klass)
116 {
117         GObjectClass *object_class = (GObjectClass *) klass;
118
119         gl_debug (DEBUG_VIEW, "START");
120
121         parent_class = g_type_class_peek_parent (klass);
122
123         object_class->finalize = gl_view_object_finalize;
124
125         gl_debug (DEBUG_VIEW, "END");
126 }
127
128 static void
129 gl_view_object_instance_init (glViewObject *view_object)
130 {
131         gl_debug (DEBUG_VIEW, "START");
132
133         view_object->private = g_new0 (glViewObjectPrivate, 1);
134
135         gl_debug (DEBUG_VIEW, "END");
136 }
137
138 static void
139 gl_view_object_finalize (GObject *object)
140 {
141         glLabel       *parent;
142         glView        *view;
143
144         gl_debug (DEBUG_VIEW, "START");
145
146         g_return_if_fail (object && GL_IS_VIEW_OBJECT (object));
147
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);
152
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));
159         }
160
161         G_OBJECT_CLASS (parent_class)->finalize (object);
162
163         gl_debug (DEBUG_VIEW, "END");
164 }
165
166 /*****************************************************************************/
167 /* NEW object view.                                                          */
168 /*****************************************************************************/
169 GObject *
170 gl_view_object_new (void)
171 {
172         glViewObject *view_object;
173
174         gl_debug (DEBUG_VIEW, "START");
175
176         view_object = g_object_new (gl_view_object_get_type(), NULL);
177
178         gl_debug (DEBUG_VIEW, "END");
179
180         return G_OBJECT (view_object);
181 }
182
183 /*****************************************************************************/
184 /* Set parent view to which this object view belongs.                        */
185 /*****************************************************************************/
186 void
187 gl_view_object_set_view       (glViewObject *view_object,
188                                glView *view)
189 {
190         gl_debug (DEBUG_VIEW, "START");
191
192         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
193         g_return_if_fail (view && GL_IS_VIEW (view));
194         
195         view_object->private->view = view;
196
197         view->object_list = g_list_prepend (view->object_list, view_object);
198
199         gl_debug (DEBUG_VIEW, "END");
200 }
201
202 /*****************************************************************************/
203 /* Set Label object to follow.                                               */
204 /*****************************************************************************/
205 void
206 gl_view_object_set_object     (glViewObject         *view_object,
207                                glLabelObject        *object,
208                                glViewHighlightStyle style)
209 {
210         GnomeCanvas        *canvas;
211         GnomeCanvasGroup   *root;
212         gdouble            x, y, w, h;
213
214         gl_debug (DEBUG_VIEW, "START");
215
216         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
217         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
218         
219         view_object->private->object = object;
220
221         gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
222         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
223
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 (),
228                                        "x", x,
229                                        "y", y,
230                                        NULL);
231
232         /* Create appropriate selection highlight canvas item. */
233         view_object->private->highlight =
234                 GL_VIEW_HIGHLIGHT (gl_view_highlight_new (view_object, style));
235
236         view_object->private->menu = GTK_WIDGET(new_menu (view_object));
237
238         g_signal_connect (G_OBJECT (object), "moved",
239                           G_CALLBACK (object_moved_cb),
240                           view_object);
241
242         g_signal_connect (G_OBJECT (object), "top",
243                           G_CALLBACK (raise_object_cb),
244                           view_object);
245
246         g_signal_connect (G_OBJECT (object), "bottom",
247                           G_CALLBACK (lower_object_cb),
248                           view_object);
249
250         g_signal_connect (G_OBJECT (object), "flip_rotate",
251                           G_CALLBACK (flip_rotate_object_cb),
252                           view_object);
253
254         g_signal_connect (G_OBJECT (view_object->private->group), "event",
255                           G_CALLBACK (gl_view_item_event_handler),
256                           view_object);
257
258         gl_debug (DEBUG_VIEW, "END");
259 }
260
261 /*****************************************************************************/
262 /* Return parent view associated with this view.                             */
263 /*****************************************************************************/
264 glView *
265 gl_view_object_get_view   (glViewObject *view_object)
266 {
267         gl_debug (DEBUG_VIEW, "START");
268
269         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
270
271         gl_debug (DEBUG_VIEW, "END");
272
273         return view_object->private->view;
274 }
275
276 /*****************************************************************************/
277 /* Return label object that we are following.                                */
278 /*****************************************************************************/
279 glLabelObject *
280 gl_view_object_get_object (glViewObject *view_object)
281 {
282         gl_debug (DEBUG_VIEW, "START");
283
284         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
285         
286         gl_debug (DEBUG_VIEW, "END");
287
288         return view_object->private->object;
289 }
290
291 /*****************************************************************************/
292 /* Return canvas item representing our object in this view.                  */
293 /*****************************************************************************/
294 GnomeCanvasItem *
295 gl_view_object_get_group   (glViewObject *view_object)
296 {
297         gl_debug (DEBUG_VIEW, "START");
298
299         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
300         
301         gl_debug (DEBUG_VIEW, "END");
302
303         return view_object->private->group;
304 }
305
306 /*****************************************************************************/
307 /* Create canvas item for this object.                                       */
308 /*****************************************************************************/
309 GnomeCanvasItem *
310 gl_view_object_item_new (glViewObject *view_object,
311                          GType         type,
312                          const gchar  *first_arg_name,
313                          ...)
314 {
315         GnomeCanvasItem *item;
316         va_list          args;
317         gdouble          affine[6], delta_affine[6];
318
319         gl_debug (DEBUG_VIEW, "START");
320
321         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
322
323         item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(view_object->private->group),
324                                       type, NULL);
325         
326         va_start (args, first_arg_name);
327         gnome_canvas_item_set_valist (item, first_arg_name, args);
328         va_end (args);
329
330         gl_label_object_get_applied_affine (view_object->private->object, affine);
331
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);
335         
336         gnome_canvas_item_affine_absolute (item, affine);
337
338         gl_debug (DEBUG_VIEW, "END");
339
340         return item;
341 }
342
343 /*****************************************************************************/
344 /* Return dialog for controlling/viewing object properties.                  */
345 /*****************************************************************************/
346 GtkWidget *
347 gl_view_object_get_dialog (glViewObject *view_object)
348 {
349         gl_debug (DEBUG_VIEW, "START");
350
351         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
352         
353         gl_debug (DEBUG_VIEW, "END");
354
355         return view_object->private->property_dialog;
356 }
357
358 /*****************************************************************************/
359 /* Popup menu for this object.                                               */
360 /*****************************************************************************/
361 GtkMenu *
362 gl_view_object_get_menu (glViewObject *view_object)
363 {
364         gl_debug (DEBUG_VIEW, "START");
365
366         g_return_val_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object), NULL);
367
368         gl_debug (DEBUG_VIEW, "END");
369
370         return GTK_MENU(view_object->private->menu);
371 }
372
373 /*****************************************************************************/
374 /* Highlight view of object.                                                 */
375 /*****************************************************************************/
376 void
377 gl_view_object_show_highlight     (glViewObject *view_object)
378 {
379         gl_debug (DEBUG_VIEW, "START");
380
381         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
382         g_return_if_fail (view_object->private->highlight);
383         
384         gl_view_highlight_show (view_object->private->highlight);
385
386         gl_debug (DEBUG_VIEW, "END");
387 }
388
389 /*****************************************************************************/
390 /* Remove highlight from view of object.                                     */
391 /*****************************************************************************/
392 void
393 gl_view_object_hide_highlight   (glViewObject *view_object)
394 {
395         gl_debug (DEBUG_VIEW, "START");
396
397         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
398         g_return_if_fail (view_object->private->highlight);
399         
400         gl_view_highlight_hide (view_object->private->highlight);
401
402         gl_debug (DEBUG_VIEW, "END");
403 }
404
405
406 /*---------------------------------------------------------------------------*/
407 /* Create a popup menu for this object view.                                 */
408 /*---------------------------------------------------------------------------*/
409 static GtkMenu *
410 new_menu (glViewObject *view_object)
411 {
412         GtkWidget *menu, *menuitem;
413
414         gl_debug (DEBUG_VIEW, "START");
415
416         g_return_val_if_fail (view_object && GL_VIEW_OBJECT(view_object), NULL);
417
418         menu = gtk_menu_new ();
419
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),
425                                   view_object);
426
427         menuitem = gtk_menu_item_new ();
428         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
429         gtk_widget_show (menuitem);
430
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);
436
437         menuitem = gtk_menu_item_new ();
438         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
439         gtk_widget_show (menuitem);
440
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);
447
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);
454
455         gl_debug (DEBUG_VIEW, "END");
456
457         return GTK_MENU(menu);
458 }
459
460 /*****************************************************************************/
461 /* Show property dialog.                                                     */
462 /*****************************************************************************/
463 void
464 gl_view_object_show_dialog (glViewObject *view_object)
465 {
466         gl_debug (DEBUG_VIEW, "START");
467
468         g_return_if_fail (view_object && GL_IS_VIEW_OBJECT (view_object));
469
470         if (view_object->private->property_dialog != NULL) {
471                 gtk_window_present (GTK_WINDOW (view_object->private->property_dialog));
472                 return;
473         }
474
475         if ( GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_dialog != NULL ) {
476
477                 view_object->private->property_dialog =
478                         GL_VIEW_OBJECT_GET_CLASS(view_object)->construct_dialog (view_object);
479
480                 g_signal_connect (G_OBJECT (view_object->private->property_dialog),
481                                   "destroy",
482                                   G_CALLBACK (gtk_widget_destroyed),
483                                   &view_object->private->property_dialog);
484         
485                 gtk_widget_show_all (view_object->private->property_dialog);
486
487         }
488
489
490         gl_debug (DEBUG_VIEW, "END");
491 }
492
493
494 /*---------------------------------------------------------------------------*/
495 /* PRIVATE.  Object moved callback.                                          */
496 /*---------------------------------------------------------------------------*/
497 static void
498 object_moved_cb (glLabelObject *object,
499                  gdouble        dx,
500                  gdouble        dy,
501                  glViewObject  *view_object)
502 {
503         gl_debug (DEBUG_VIEW, "START");
504
505         /* Adjust location of analogous canvas group. */
506         gnome_canvas_item_move (view_object->private->group, dx, dy);
507
508         gl_debug (DEBUG_VIEW, "END");
509 }
510
511 /*---------------------------------------------------------------------------*/
512 /* PRIVATE.  raise item to front callback.                                   */
513 /*---------------------------------------------------------------------------*/
514 static void
515 raise_object_cb (glLabelObject *object,
516                  glViewObject  *view_object)
517 {
518         gl_debug (DEBUG_VIEW, "START");
519
520         /* send to top */
521         gnome_canvas_item_raise_to_top (view_object->private->group);
522
523         gl_debug (DEBUG_VIEW, "END");
524 }
525
526 /*---------------------------------------------------------------------------*/
527 /* PRIVATE.  lower item to back callback.                                    */
528 /*---------------------------------------------------------------------------*/
529 static void
530 lower_object_cb (glLabelObject *object,
531                  glViewObject  *view_object)
532 {
533         gl_debug (DEBUG_VIEW, "START");
534
535         /* Send to bottom */
536         gnome_canvas_item_lower_to_bottom (view_object->private->group);
537
538         gl_debug (DEBUG_VIEW, "END");
539 }
540
541 /*---------------------------------------------------------------------------*/
542 /* PRIVATE.  Flip/rotate object callback.                                    */
543 /*---------------------------------------------------------------------------*/
544 static void
545 flip_rotate_object_cb (glLabelObject *object,
546                        glViewObject  *view_object)
547 {
548         gdouble          affine[6], delta_affine[6];
549         gdouble          w, h;
550         GList           *p, *item_list;
551         GnomeCanvasItem *item;
552
553         gl_debug (DEBUG_VIEW, "START");
554
555         gl_label_object_get_applied_affine (object, affine);
556
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);
560         
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);
565         }
566
567         gl_debug (DEBUG_VIEW, "END");
568 }
569
570 /*****************************************************************************/
571 /* Select object.                                                            */
572 /*****************************************************************************/
573 void
574 gl_view_object_select (glViewObject *view_object)
575 {
576         gl_debug (DEBUG_VIEW, "START");
577
578         gl_view_select_object(view_object->private->view, view_object);
579
580         gl_debug (DEBUG_VIEW, "END");
581 }
582