]> git.sur5r.net Git - glabels/blob - glabels2/src/view-image.c
2007-09-27 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / view-image.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  view_image.c:  GLabels label image object view
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <config.h>
25
26 #include "view-image.h"
27
28 #include <glib/gi18n.h>
29 #include <glib/gmem.h>
30
31 #include "color.h"
32 #include "object-editor.h"
33 #include "stock.h"
34
35 #include "pixmaps/cursor_image.xbm"
36 #include "pixmaps/cursor_image_mask.xbm"
37
38 #include "debug.h"
39
40 /*========================================================*/
41 /* Private macros and constants.                          */
42 /*========================================================*/
43
44
45 /*========================================================*/
46 /* Private types.                                         */
47 /*========================================================*/
48
49 struct _glViewImagePrivate {
50 };
51
52 /*========================================================*/
53 /* Private globals.                                       */
54 /*========================================================*/
55
56
57 /*========================================================*/
58 /* Private function prototypes.                           */
59 /*========================================================*/
60
61 static void       gl_view_image_finalize            (GObject          *object);
62
63 static GtkWidget *construct_properties_editor       (glViewObject     *view_object);
64
65 static void       update_object_from_editor_cb      (glObjectEditor   *editor,
66                                                      glLabelObject    *object);
67
68 static void       update_editor_from_object_cb      (glLabelObject    *object,
69                                                      glObjectEditor   *editor);
70
71 static void       update_editor_from_move_cb        (glLabelObject    *object,
72                                                      gdouble           dx,
73                                                      gdouble           dy,
74                                                      glObjectEditor   *editor);
75
76 static void       update_editor_from_label_cb       (glLabel          *label,
77                                                      glObjectEditor   *editor);
78
79 static gboolean   object_at                         (glViewObject     *view_object,
80                                                      cairo_t          *cr,
81                                                      gdouble           x,
82                                                      gdouble           y);
83
84
85 \f
86 /*****************************************************************************/
87 /* Boilerplate object stuff.                                                 */
88 /*****************************************************************************/
89 G_DEFINE_TYPE (glViewImage, gl_view_image, GL_TYPE_VIEW_OBJECT);
90
91
92 static void
93 gl_view_image_class_init (glViewImageClass *class)
94 {
95         GObjectClass      *object_class      = G_OBJECT_CLASS (class);
96         glViewObjectClass *view_object_class = GL_VIEW_OBJECT_CLASS (class);
97
98         gl_debug (DEBUG_VIEW, "START");
99
100         gl_view_image_parent_class = g_type_class_peek_parent (class);
101
102         object_class->finalize = gl_view_image_finalize;
103
104         view_object_class->construct_editor = construct_properties_editor;
105         view_object_class->object_at        = object_at;
106
107         gl_debug (DEBUG_VIEW, "END");
108 }
109
110 static void
111 gl_view_image_init (glViewImage *view_image)
112 {
113         gl_debug (DEBUG_VIEW, "START");
114
115         view_image->priv = g_new0 (glViewImagePrivate, 1);
116
117         gl_debug (DEBUG_VIEW, "END");
118 }
119
120 static void
121 gl_view_image_finalize (GObject *object)
122 {
123         glViewImage *view_image = GL_VIEW_IMAGE (object);
124
125         gl_debug (DEBUG_VIEW, "START");
126
127         g_return_if_fail (object && GL_IS_VIEW_IMAGE (object));
128
129         g_free (view_image->priv);
130
131         G_OBJECT_CLASS (gl_view_image_parent_class)->finalize (object);
132
133         gl_debug (DEBUG_VIEW, "END");
134 }
135
136 /*****************************************************************************/
137 /* NEW image object view.                                                    */
138 /*****************************************************************************/
139 glViewObject *
140 gl_view_image_new (glLabelImage *object,
141                    glView       *view)
142 {
143         glViewImage         *view_image;
144
145         gl_debug (DEBUG_VIEW, "START");
146
147         g_return_val_if_fail (object && GL_IS_LABEL_IMAGE (object), NULL);
148         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
149         
150         view_image = g_object_new (gl_view_image_get_type(), NULL);
151
152         gl_view_object_set_object (GL_VIEW_OBJECT(view_image),
153                                    GL_LABEL_OBJECT(object),
154                                    GL_VIEW_OBJECT_HANDLES_BOX);
155         gl_view_object_set_view (GL_VIEW_OBJECT(view_image), view);
156
157         gl_debug (DEBUG_VIEW, "END");
158
159         return GL_VIEW_OBJECT (view_image);
160 }
161
162 /*****************************************************************************/
163 /* Create a properties dialog for a image object.                            */
164 /*****************************************************************************/
165 static GtkWidget *
166 construct_properties_editor (glViewObject *view_object)
167 {
168         GtkWidget          *editor;
169         glViewImage        *view_image = (glViewImage *)view_object;
170         glLabelObject      *object;
171
172         gl_debug (DEBUG_VIEW, "START");
173
174         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
175
176         /* Build editor. */
177         editor = gl_object_editor_new (GL_STOCK_IMAGE, _("Image object properties"),
178                                        GL_OBJECT_EDITOR_POSITION_PAGE,
179                                        GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE,
180                                        GL_OBJECT_EDITOR_IMAGE_PAGE,
181                                        0);
182         
183         /* Update */
184         update_editor_from_label_cb (object->parent, GL_OBJECT_EDITOR(editor));
185         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
186         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
187
188         /* Connect signals. */
189         g_signal_connect (G_OBJECT (editor), "changed",
190                           G_CALLBACK(update_object_from_editor_cb), object);
191         g_signal_connect (G_OBJECT (object), "changed",
192                           G_CALLBACK (update_editor_from_object_cb), editor);
193         g_signal_connect (G_OBJECT (object), "moved",
194                           G_CALLBACK (update_editor_from_move_cb), editor);
195         g_signal_connect (G_OBJECT (object->parent), "size_changed",
196                           G_CALLBACK (update_editor_from_label_cb), editor);
197         g_signal_connect (G_OBJECT (object->parent), "merge_changed",
198                           G_CALLBACK (update_editor_from_label_cb), editor);
199
200         gl_debug (DEBUG_VIEW, "END");
201
202         return editor;
203 }
204
205 /*---------------------------------------------------------------------------*/
206 /* PRIVATE.  editor "changed" callback.                                      */
207 /*---------------------------------------------------------------------------*/
208 static void
209 update_object_from_editor_cb (glObjectEditor *editor,
210                               glLabelObject  *object)
211 {
212         gdouble            x, y, w, h;
213         glTextNode        *filename;
214         const GdkPixbuf   *pixbuf;
215         gdouble            image_w, image_h;
216
217         gl_debug (DEBUG_VIEW, "START");
218
219         g_signal_handlers_block_by_func (G_OBJECT(object),
220                                          update_editor_from_object_cb,
221                                          editor);
222         g_signal_handlers_block_by_func (G_OBJECT(object),
223                                          update_editor_from_move_cb,
224                                          editor);
225
226
227         gl_object_editor_get_position (editor, &x, &y);
228         gl_label_object_set_position (object, x, y);
229
230         gl_object_editor_get_size (editor, &w, &h);
231         gl_label_object_set_size (object, w, h);
232
233         filename = gl_object_editor_get_image (editor);
234         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
235         gl_text_node_free (&filename);
236
237         /* Setting filename may have modified the size. */
238         gl_label_object_get_size (object, &w, &h);
239         gl_object_editor_set_size (editor, w, h);
240
241         /* It may also have a new base size. */
242         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
243         image_w = gdk_pixbuf_get_width (pixbuf);
244         image_h = gdk_pixbuf_get_height (pixbuf);
245         gl_object_editor_set_base_size (editor, image_w, image_h);
246
247         g_signal_handlers_unblock_by_func (G_OBJECT(object),
248                                            update_editor_from_object_cb,
249                                            editor);
250         g_signal_handlers_unblock_by_func (G_OBJECT(object),
251                                            update_editor_from_move_cb,
252                                            editor);
253
254         gl_debug (DEBUG_VIEW, "END");
255 }
256
257 /*---------------------------------------------------------------------------*/
258 /* PRIVATE. label object "changed" callback.                                 */
259 /*---------------------------------------------------------------------------*/
260 static void
261 update_editor_from_object_cb (glLabelObject  *object,
262                               glObjectEditor *editor)
263 {
264         gdouble            w, h;
265         const GdkPixbuf   *pixbuf;
266         gdouble            image_w, image_h;
267         glTextNode        *filename;
268         glMerge           *merge;
269
270         gl_debug (DEBUG_VIEW, "START");
271
272         gl_label_object_get_size (object, &w, &h);
273         gl_object_editor_set_size (editor, w, h);
274
275         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
276         image_w = gdk_pixbuf_get_width (pixbuf);
277         image_h = gdk_pixbuf_get_height (pixbuf);
278         gl_object_editor_set_base_size (editor, image_w, image_h);
279
280         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
281         merge = gl_label_get_merge (GL_LABEL(object->parent));
282         if ( filename != NULL ) {
283                 gl_object_editor_set_image (editor, (merge != NULL), filename);
284         }
285
286         gl_debug (DEBUG_VIEW, "END");
287 }
288
289 /*---------------------------------------------------------------------------*/
290 /* PRIVATE. label object "moved" callback.                                   */
291 /*---------------------------------------------------------------------------*/
292 static void
293 update_editor_from_move_cb (glLabelObject    *object,
294                             gdouble           dx,
295                             gdouble           dy,
296                             glObjectEditor   *editor)
297 {
298         gdouble            x, y;
299
300         gl_debug (DEBUG_VIEW, "START");
301
302         gl_label_object_get_position (object, &x, &y);
303         gl_object_editor_set_position (editor, x, y);
304
305         gl_debug (DEBUG_VIEW, "END");
306 }
307
308 /*---------------------------------------------------------------------------*/
309 /* PRIVATE. label "changed" callback.                                        */
310 /*---------------------------------------------------------------------------*/
311 static void
312 update_editor_from_label_cb (glLabel        *label,
313                              glObjectEditor *editor)
314 {
315         gdouble            label_width, label_height;
316         glMerge                    *merge;
317
318         gl_debug (DEBUG_VIEW, "START");
319
320         gl_label_get_size (label, &label_width, &label_height);
321         gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
322                                            label_width, label_height);
323         gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
324                                        label_width, label_height);
325         
326         merge = gl_label_get_merge (label);
327         gl_object_editor_set_key_names (editor, merge);
328
329         gl_debug (DEBUG_VIEW, "END");
330 }
331
332 /*****************************************************************************/
333 /* Is object at (x,y)?                                                       */
334 /*****************************************************************************/
335 static gboolean
336 object_at (glViewObject  *view_object,
337            cairo_t       *cr,
338            gdouble        x,
339            gdouble        y)
340 {
341         glLabelObject    *object;
342         gdouble           w, h;
343
344         object = gl_view_object_get_object (view_object);
345
346         gl_label_object_get_size (object, &w, &h);
347
348         cairo_rectangle (cr, 0.0, 0.0, w, h);
349
350         if (cairo_in_fill (cr, x, y))
351         {
352                 return TRUE;
353         }
354
355         return FALSE;
356 }
357
358
359 /*****************************************************************************/
360 /* Return apropos cursor for create object mode.                             */
361 /*****************************************************************************/
362 GdkCursor *
363 gl_view_image_get_create_cursor (void)
364 {
365         GdkCursor       *cursor = NULL;
366         GdkPixmap       *pixmap_data, *pixmap_mask;
367         GdkColor         fg = { 0, 0, 0, 0 };
368         GdkColor         bg = { 0, 65535, 65535, 65535 };
369
370         gl_debug (DEBUG_VIEW, "START");
371
372         pixmap_data = gdk_bitmap_create_from_data (NULL,
373                                                    (gchar *)cursor_image_bits,
374                                                    cursor_image_width,
375                                                    cursor_image_height);
376         pixmap_mask = gdk_bitmap_create_from_data (NULL,
377                                                    (gchar *)cursor_image_mask_bits,
378                                                    cursor_image_mask_width,
379                                                    cursor_image_mask_height);
380         cursor = gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
381                                              &bg, cursor_image_x_hot,
382                                              cursor_image_y_hot);
383
384         gl_debug (DEBUG_VIEW, "END");
385
386         return cursor;
387 }
388
389 /*****************************************************************************/
390 /* Object creation handler: button press event.                              */
391 /*****************************************************************************/
392 void
393 gl_view_image_create_button_press_event   (glView *view,
394                                            gdouble x,
395                                            gdouble y)
396 {
397         GObject             *object;
398
399         gl_view_unselect_all (view);
400
401         object = gl_label_image_new (view->label);
402         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
403         gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
404
405         view->create_object = GL_LABEL_OBJECT (object);
406         view->create_x0 = x;
407         view->create_y0 = y;
408 }
409
410 /*****************************************************************************/
411 /* Object creation handler: motion event.                                    */
412 /*****************************************************************************/
413 void
414 gl_view_image_create_motion_event     (glView *view,
415                                        gdouble x,
416                                        gdouble y)
417 {
418         gdouble w, h;
419
420         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
421                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
422         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
423         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
424         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
425 }
426
427 /*****************************************************************************/
428 /* Object creation handler: button relesase event.                           */
429 /*****************************************************************************/
430 void
431 gl_view_image_create_button_release_event (glView *view,
432                                            gdouble x,
433                                            gdouble y)
434 {
435         gdouble              w, h;
436
437         if ((view->create_x0 == x) && (view->create_y0 == y)) {
438                 x = view->create_x0 + 36.0;
439                 y = view->create_y0 + 36.0;
440         }
441         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
442                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
443         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
444         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
445         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
446 }
447