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