]> git.sur5r.net Git - glabels/blob - glabels2/src/view-image.c
7612284d7564d050c7a3750191af62f8a1b4b362
[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 gboolean   object_at                         (glViewObject     *view_object,
77                                                      cairo_t          *cr,
78                                                      gdouble           x,
79                                                      gdouble           y);
80
81
82 \f
83 /*****************************************************************************/
84 /* Boilerplate object stuff.                                                 */
85 /*****************************************************************************/
86 G_DEFINE_TYPE (glViewImage, gl_view_image, GL_TYPE_VIEW_OBJECT);
87
88
89 static void
90 gl_view_image_class_init (glViewImageClass *class)
91 {
92         GObjectClass      *object_class      = G_OBJECT_CLASS (class);
93         glViewObjectClass *view_object_class = GL_VIEW_OBJECT_CLASS (class);
94
95         gl_debug (DEBUG_VIEW, "START");
96
97         gl_view_image_parent_class = g_type_class_peek_parent (class);
98
99         object_class->finalize = gl_view_image_finalize;
100
101         view_object_class->construct_editor = construct_properties_editor;
102         view_object_class->object_at        = object_at;
103
104         gl_debug (DEBUG_VIEW, "END");
105 }
106
107 static void
108 gl_view_image_init (glViewImage *view_image)
109 {
110         gl_debug (DEBUG_VIEW, "START");
111
112         view_image->priv = g_new0 (glViewImagePrivate, 1);
113
114         gl_debug (DEBUG_VIEW, "END");
115 }
116
117 static void
118 gl_view_image_finalize (GObject *object)
119 {
120         glViewImage *view_image = GL_VIEW_IMAGE (object);
121
122         gl_debug (DEBUG_VIEW, "START");
123
124         g_return_if_fail (object && GL_IS_VIEW_IMAGE (object));
125
126         g_free (view_image->priv);
127
128         G_OBJECT_CLASS (gl_view_image_parent_class)->finalize (object);
129
130         gl_debug (DEBUG_VIEW, "END");
131 }
132
133 /*****************************************************************************/
134 /* NEW image object view.                                                    */
135 /*****************************************************************************/
136 glViewObject *
137 gl_view_image_new (glLabelImage *object,
138                    glView       *view)
139 {
140         glViewImage         *view_image;
141
142         gl_debug (DEBUG_VIEW, "START");
143
144         g_return_val_if_fail (object && GL_IS_LABEL_IMAGE (object), NULL);
145         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
146         
147         view_image = g_object_new (gl_view_image_get_type(), NULL);
148
149         gl_view_object_set_object (GL_VIEW_OBJECT(view_image),
150                                    GL_LABEL_OBJECT(object),
151                                    GL_VIEW_OBJECT_HANDLES_BOX);
152         gl_view_object_set_view (GL_VIEW_OBJECT(view_image), view);
153
154         gl_debug (DEBUG_VIEW, "END");
155
156         return GL_VIEW_OBJECT (view_image);
157 }
158
159 /*****************************************************************************/
160 /* Create a properties dialog for a image object.                            */
161 /*****************************************************************************/
162 static GtkWidget *
163 construct_properties_editor (glViewObject *view_object)
164 {
165         GtkWidget          *editor;
166         glViewImage        *view_image = (glViewImage *)view_object;
167         glLabelObject      *object;
168
169         gl_debug (DEBUG_VIEW, "START");
170
171         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_image));
172
173         /* Build editor. */
174         editor = gl_object_editor_new (GL_STOCK_IMAGE, _("Image object properties"),
175                                        object->parent,
176                                        GL_OBJECT_EDITOR_POSITION_PAGE,
177                                        GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE,
178                                        GL_OBJECT_EDITOR_IMAGE_PAGE,
179                                        0);
180         
181         /* Update */
182         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
183         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
184
185         /* Connect signals. */
186         g_signal_connect (G_OBJECT (editor), "changed",
187                           G_CALLBACK(update_object_from_editor_cb), object);
188         g_signal_connect (G_OBJECT (object), "changed",
189                           G_CALLBACK (update_editor_from_object_cb), editor);
190         g_signal_connect (G_OBJECT (object), "moved",
191                           G_CALLBACK (update_editor_from_move_cb), editor);
192
193         gl_debug (DEBUG_VIEW, "END");
194
195         return editor;
196 }
197
198 /*---------------------------------------------------------------------------*/
199 /* PRIVATE.  editor "changed" callback.                                      */
200 /*---------------------------------------------------------------------------*/
201 static void
202 update_object_from_editor_cb (glObjectEditor *editor,
203                               glLabelObject  *object)
204 {
205         gdouble            x, y, w, h;
206         glTextNode        *filename;
207         const GdkPixbuf   *pixbuf;
208         gdouble            image_w, image_h;
209         gdouble            new_w, new_h;
210
211         gl_debug (DEBUG_VIEW, "START");
212
213         g_signal_handlers_block_by_func (G_OBJECT(object),
214                                          update_editor_from_object_cb,
215                                          editor);
216         g_signal_handlers_block_by_func (G_OBJECT(object),
217                                          update_editor_from_move_cb,
218                                          editor);
219
220
221         gl_object_editor_get_position (editor, &x, &y);
222         gl_label_object_set_position (object, x, y);
223
224         gl_object_editor_get_size (editor, &w, &h);
225         gl_label_object_set_size (object, w, h);
226
227         filename = gl_object_editor_get_image (editor);
228         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
229         gl_text_node_free (&filename);
230
231         /* Setting filename may have modified the size. */
232         gl_label_object_get_size (object, &new_w, &new_h);
233         if ( (new_w != w) || (new_h != h) )
234         {
235                 gl_object_editor_set_size (editor, new_w, new_h);
236         }
237
238         /* It may also have a new base size. */
239         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
240         image_w = gdk_pixbuf_get_width (pixbuf);
241         image_h = gdk_pixbuf_get_height (pixbuf);
242         gl_object_editor_set_base_size (editor, image_w, image_h);
243
244         g_signal_handlers_unblock_by_func (G_OBJECT(object),
245                                            update_editor_from_object_cb,
246                                            editor);
247         g_signal_handlers_unblock_by_func (G_OBJECT(object),
248                                            update_editor_from_move_cb,
249                                            editor);
250
251         gl_debug (DEBUG_VIEW, "END");
252 }
253
254 /*---------------------------------------------------------------------------*/
255 /* PRIVATE. label object "changed" callback.                                 */
256 /*---------------------------------------------------------------------------*/
257 static void
258 update_editor_from_object_cb (glLabelObject  *object,
259                               glObjectEditor *editor)
260 {
261         gdouble            w, h;
262         const GdkPixbuf   *pixbuf;
263         gdouble            image_w, image_h;
264         glTextNode        *filename;
265         glMerge           *merge;
266
267         gl_debug (DEBUG_VIEW, "START");
268
269         gl_label_object_get_size (object, &w, &h);
270         gl_object_editor_set_size (editor, w, h);
271
272         pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
273         image_w = gdk_pixbuf_get_width (pixbuf);
274         image_h = gdk_pixbuf_get_height (pixbuf);
275         gl_object_editor_set_base_size (editor, image_w, image_h);
276
277         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
278         merge = gl_label_get_merge (GL_LABEL(object->parent));
279         if ( filename != NULL ) {
280                 gl_object_editor_set_image (editor, (merge != NULL), filename);
281         }
282
283         gl_debug (DEBUG_VIEW, "END");
284 }
285
286 /*---------------------------------------------------------------------------*/
287 /* PRIVATE. label object "moved" callback.                                   */
288 /*---------------------------------------------------------------------------*/
289 static void
290 update_editor_from_move_cb (glLabelObject    *object,
291                             gdouble           dx,
292                             gdouble           dy,
293                             glObjectEditor   *editor)
294 {
295         gdouble            x, y;
296
297         gl_debug (DEBUG_VIEW, "START");
298
299         gl_label_object_get_position (object, &x, &y);
300         gl_object_editor_set_position (editor, x, y);
301
302         gl_debug (DEBUG_VIEW, "END");
303 }
304
305 /*****************************************************************************/
306 /* Is object at (x,y)?                                                       */
307 /*****************************************************************************/
308 static gboolean
309 object_at (glViewObject  *view_object,
310            cairo_t       *cr,
311            gdouble        x,
312            gdouble        y)
313 {
314         glLabelObject    *object;
315         gdouble           w, h;
316
317         object = gl_view_object_get_object (view_object);
318
319         gl_label_object_get_size (object, &w, &h);
320
321         cairo_rectangle (cr, 0.0, 0.0, w, h);
322
323         if (cairo_in_fill (cr, x, y))
324         {
325                 return TRUE;
326         }
327
328         return FALSE;
329 }
330
331
332 /*****************************************************************************/
333 /* Return apropos cursor for create object mode.                             */
334 /*****************************************************************************/
335 GdkCursor *
336 gl_view_image_get_create_cursor (void)
337 {
338         GdkCursor       *cursor = NULL;
339         GdkPixmap       *pixmap_data, *pixmap_mask;
340         GdkColor         fg = { 0, 0, 0, 0 };
341         GdkColor         bg = { 0, 65535, 65535, 65535 };
342
343         gl_debug (DEBUG_VIEW, "START");
344
345         pixmap_data = gdk_bitmap_create_from_data (NULL,
346                                                    (gchar *)cursor_image_bits,
347                                                    cursor_image_width,
348                                                    cursor_image_height);
349         pixmap_mask = gdk_bitmap_create_from_data (NULL,
350                                                    (gchar *)cursor_image_mask_bits,
351                                                    cursor_image_mask_width,
352                                                    cursor_image_mask_height);
353         cursor = gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
354                                              &bg, cursor_image_x_hot,
355                                              cursor_image_y_hot);
356
357         gl_debug (DEBUG_VIEW, "END");
358
359         return cursor;
360 }
361
362 /*****************************************************************************/
363 /* Object creation handler: button press event.                              */
364 /*****************************************************************************/
365 void
366 gl_view_image_create_button_press_event   (glView *view,
367                                            gdouble x,
368                                            gdouble y)
369 {
370         GObject             *object;
371
372         gl_view_unselect_all (view);
373
374         object = gl_label_image_new (view->label);
375         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
376         gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
377
378         view->create_object = GL_LABEL_OBJECT (object);
379         view->create_x0 = x;
380         view->create_y0 = y;
381 }
382
383 /*****************************************************************************/
384 /* Object creation handler: motion event.                                    */
385 /*****************************************************************************/
386 void
387 gl_view_image_create_motion_event     (glView *view,
388                                        gdouble x,
389                                        gdouble y)
390 {
391         gdouble w, h;
392
393         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
394                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
395         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
396         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
397         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
398 }
399
400 /*****************************************************************************/
401 /* Object creation handler: button relesase event.                           */
402 /*****************************************************************************/
403 void
404 gl_view_image_create_button_release_event (glView *view,
405                                            gdouble x,
406                                            gdouble y)
407 {
408         gdouble              w, h;
409
410         if ((view->create_x0 == x) && (view->create_y0 == y)) {
411                 x = view->create_x0 + 36.0;
412                 y = view->create_y0 + 36.0;
413         }
414         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
415                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
416         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
417         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
418         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
419 }
420