]> git.sur5r.net Git - glabels/blob - glabels2/src/view-ellipse.c
2007-09-27 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / view-ellipse.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_ellipse.c:  GLabels label ellipse 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-ellipse.h"
27
28 #include <glib/gi18n.h>
29 #include <glib/gmem.h>
30 #include <math.h>
31
32 #include "cairo-ellipse-path.h"
33 #include "color.h"
34 #include "object-editor.h"
35 #include "stock.h"
36
37 #include "pixmaps/cursor_ellipse.xbm"
38 #include "pixmaps/cursor_ellipse_mask.xbm"
39
40 #include "debug.h"
41
42 /*========================================================*/
43 /* Private macros and constants.                          */
44 /*========================================================*/
45
46 /*========================================================*/
47 /* Private types.                                         */
48 /*========================================================*/
49
50 struct _glViewEllipsePrivate {
51 };
52
53 /*========================================================*/
54 /* Private globals.                                       */
55 /*========================================================*/
56
57
58 /*========================================================*/
59 /* Private function prototypes.                           */
60 /*========================================================*/
61
62 static void       gl_view_ellipse_finalize          (GObject          *object);
63
64 static GtkWidget *construct_properties_editor       (glViewObject     *view_object);
65
66 static void       update_object_from_editor_cb      (glObjectEditor   *editor,
67                                                      glLabelObject    *object);
68
69 static void       update_editor_from_object_cb      (glLabelObject    *object,
70                                                      glObjectEditor   *editor);
71
72 static void       update_editor_from_move_cb        (glLabelObject    *object,
73                                                      gdouble           dx,
74                                                      gdouble           dy,
75                                                      glObjectEditor   *editor);
76
77 static void       update_editor_from_label_cb       (glLabel          *label,
78                                                      glObjectEditor   *editor);
79
80 static gboolean   object_at                         (glViewObject     *view_object,
81                                                      cairo_t          *cr,
82                                                      gdouble           x,
83                                                      gdouble           y);
84
85
86 \f
87 /*****************************************************************************/
88 /* Boilerplate object stuff.                                                 */
89 /*****************************************************************************/
90 G_DEFINE_TYPE (glViewEllipse, gl_view_ellipse, GL_TYPE_VIEW_OBJECT);
91
92
93 static void
94 gl_view_ellipse_class_init (glViewEllipseClass *class)
95 {
96         GObjectClass      *object_class      = G_OBJECT_CLASS (class);
97         glViewObjectClass *view_object_class = GL_VIEW_OBJECT_CLASS (class);
98
99         gl_debug (DEBUG_VIEW, "START");
100
101         gl_view_ellipse_parent_class = g_type_class_peek_parent (class);
102
103         object_class->finalize = gl_view_ellipse_finalize;
104
105         view_object_class->construct_editor = construct_properties_editor;
106         view_object_class->object_at        = object_at;
107
108         gl_debug (DEBUG_VIEW, "END");
109 }
110
111 static void
112 gl_view_ellipse_init (glViewEllipse *view_ellipse)
113 {
114         gl_debug (DEBUG_VIEW, "START");
115
116         view_ellipse->priv = g_new0 (glViewEllipsePrivate, 1);
117
118         gl_debug (DEBUG_VIEW, "END");
119 }
120
121 static void
122 gl_view_ellipse_finalize (GObject *object)
123 {
124         glViewEllipse *view_ellipse = GL_VIEW_ELLIPSE (object);
125
126         gl_debug (DEBUG_VIEW, "START");
127
128         g_return_if_fail (object && GL_IS_VIEW_ELLIPSE (object));
129
130         g_free (view_ellipse->priv);
131
132         G_OBJECT_CLASS (gl_view_ellipse_parent_class)->finalize (object);
133
134         gl_debug (DEBUG_VIEW, "END");
135 }
136
137 /*****************************************************************************/
138 /* NEW ellipse object view.                                                  */
139 /*****************************************************************************/
140 glViewObject *
141 gl_view_ellipse_new (glLabelEllipse *object,
142                      glView         *view)
143 {
144         glViewEllipse         *view_ellipse;
145
146         gl_debug (DEBUG_VIEW, "START");
147
148         g_return_val_if_fail (object && GL_IS_LABEL_ELLIPSE (object), NULL);
149         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
150         
151         view_ellipse = g_object_new (gl_view_ellipse_get_type(), NULL);
152
153         gl_view_object_set_object (GL_VIEW_OBJECT(view_ellipse),
154                                    GL_LABEL_OBJECT(object),
155                                    GL_VIEW_OBJECT_HANDLES_BOX);
156         gl_view_object_set_view (GL_VIEW_OBJECT(view_ellipse), view);
157
158         gl_debug (DEBUG_VIEW, "END");
159
160         return GL_VIEW_OBJECT (view_ellipse);
161 }
162
163 /*****************************************************************************/
164 /* Create a properties dialog for a ellipse object.                          */
165 /*****************************************************************************/
166 static GtkWidget *
167 construct_properties_editor (glViewObject *view_object)
168 {
169         GtkWidget          *editor;
170         glViewEllipse      *view_ellipse = (glViewEllipse *)view_object;
171         glLabelObject      *object;
172
173         gl_debug (DEBUG_VIEW, "START");
174
175         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_ellipse));
176
177         /* Build editor. */
178         editor = gl_object_editor_new (GL_STOCK_ELLIPSE, _("Ellipse object properties"),
179                                        GL_OBJECT_EDITOR_SHADOW_PAGE,
180                                        GL_OBJECT_EDITOR_POSITION_PAGE,
181                                        GL_OBJECT_EDITOR_SIZE_PAGE,
182                                        GL_OBJECT_EDITOR_FILL_PAGE,
183                                        GL_OBJECT_EDITOR_LINE_PAGE,
184                                        0);
185         
186         /* Update */
187         update_editor_from_label_cb (object->parent, GL_OBJECT_EDITOR(editor));
188         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
189         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
190
191         /* Connect signals. */
192         g_signal_connect (G_OBJECT (editor), "changed",
193                           G_CALLBACK(update_object_from_editor_cb), object);
194         g_signal_connect (G_OBJECT (object), "changed",
195                           G_CALLBACK (update_editor_from_object_cb), editor);
196         g_signal_connect (G_OBJECT (object), "moved",
197                           G_CALLBACK (update_editor_from_move_cb), editor);
198         g_signal_connect (G_OBJECT (object->parent), "size_changed",
199                           G_CALLBACK (update_editor_from_label_cb), editor);
200         g_signal_connect (G_OBJECT (object->parent), "merge_changed",
201                           G_CALLBACK (update_editor_from_label_cb), editor);
202
203         gl_debug (DEBUG_VIEW, "END");
204
205         return editor;
206 }
207
208 /*---------------------------------------------------------------------------*/
209 /* PRIVATE.  editor "changed" callback.                                      */
210 /*---------------------------------------------------------------------------*/
211 static void
212 update_object_from_editor_cb (glObjectEditor *editor,
213                               glLabelObject  *object)
214 {
215         gdouble            x, y, w, h;
216         glColorNode       *line_color_node;
217         gdouble            line_width;
218         glColorNode       *fill_color_node;
219         gboolean           shadow_state;
220         gdouble            shadow_x, shadow_y;
221         glColorNode       *shadow_color_node;
222         gdouble            shadow_opacity;
223         
224
225         gl_debug (DEBUG_VIEW, "START");
226
227         g_signal_handlers_block_by_func (G_OBJECT(object),
228                                          update_editor_from_object_cb,
229                                          editor);
230         g_signal_handlers_block_by_func (G_OBJECT(object),
231                                          update_editor_from_move_cb,
232                                          editor);
233
234         gl_object_editor_get_position (editor, &x, &y);
235         gl_label_object_set_position (object, x, y);
236
237         gl_object_editor_get_size (editor, &w, &h);
238         gl_label_object_set_size (object, w, h);
239
240         fill_color_node = gl_object_editor_get_fill_color (editor);
241         gl_label_object_set_fill_color (object, fill_color_node);
242         gl_color_node_free (&fill_color_node);
243
244         line_color_node = gl_object_editor_get_line_color (editor);
245         gl_label_object_set_line_color (object, line_color_node);
246         gl_color_node_free (&line_color_node);
247
248         line_width = gl_object_editor_get_line_width (editor);
249         gl_label_object_set_line_width (object, line_width);
250
251         shadow_state = gl_object_editor_get_shadow_state (editor);
252         gl_label_object_set_shadow_state (object, shadow_state);
253
254         gl_object_editor_get_shadow_offset (editor, &shadow_x, &shadow_y);
255         gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
256
257         shadow_color_node = gl_object_editor_get_shadow_color (editor);
258         gl_label_object_set_shadow_color (object, shadow_color_node);
259         gl_color_node_free (&shadow_color_node);
260
261         shadow_opacity = gl_object_editor_get_shadow_opacity (editor);
262         gl_label_object_set_shadow_opacity (object, shadow_opacity);
263
264         g_signal_handlers_unblock_by_func (G_OBJECT(object),
265                                            update_editor_from_object_cb,
266                                            editor);
267         g_signal_handlers_unblock_by_func (G_OBJECT(object),
268                                            update_editor_from_move_cb,
269                                            editor);
270
271         gl_debug (DEBUG_VIEW, "END");
272 }
273
274 /*---------------------------------------------------------------------------*/
275 /* PRIVATE. label object "changed" callback.                                 */
276 /*---------------------------------------------------------------------------*/
277 static void
278 update_editor_from_object_cb (glLabelObject  *object,
279                               glObjectEditor *editor)
280 {
281         gdouble            w, h;
282         glColorNode       *line_color_node;
283         gdouble            line_width;
284         glColorNode       *fill_color_node;
285         gboolean           shadow_state;
286         gdouble            shadow_x, shadow_y;
287         glColorNode       *shadow_color_node;
288         gdouble            shadow_opacity;
289         glMerge           *merge;
290
291         gl_debug (DEBUG_VIEW, "START");
292
293         gl_label_object_get_size (object, &w, &h);
294         gl_object_editor_set_size (editor, w, h);
295         merge = gl_label_get_merge (GL_LABEL(object->parent));
296         
297         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
298         gl_object_editor_set_fill_color (editor, (merge != NULL), fill_color_node);
299         gl_color_node_free (&fill_color_node);
300
301         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
302         gl_object_editor_set_line_color (editor, (merge != NULL), line_color_node);
303         gl_color_node_free (&line_color_node);
304
305         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
306         gl_object_editor_set_line_width (editor, line_width);
307
308         shadow_state = gl_label_object_get_shadow_state (object);
309         gl_object_editor_set_shadow_state (editor, shadow_state);
310
311         gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
312         gl_object_editor_set_shadow_offset (editor, shadow_x, shadow_y);
313
314         shadow_color_node = gl_label_object_get_shadow_color (object);
315         gl_object_editor_set_shadow_color (editor, (merge != NULL), shadow_color_node);
316         gl_color_node_free (&shadow_color_node);
317
318         shadow_opacity = gl_label_object_get_shadow_opacity (object);
319         gl_object_editor_set_shadow_opacity (editor, shadow_opacity);
320
321         gl_debug (DEBUG_VIEW, "END");
322 }
323
324 /*---------------------------------------------------------------------------*/
325 /* PRIVATE. label object "moved" callback.                                   */
326 /*---------------------------------------------------------------------------*/
327 static void
328 update_editor_from_move_cb (glLabelObject    *object,
329                             gdouble           dx,
330                             gdouble           dy,
331                             glObjectEditor   *editor)
332 {
333         gdouble            x, y;
334
335         gl_debug (DEBUG_VIEW, "START");
336
337         gl_label_object_get_position (object, &x, &y);
338         gl_object_editor_set_position (editor, x, y);
339
340         gl_debug (DEBUG_VIEW, "END");
341 }
342
343 /*---------------------------------------------------------------------------*/
344 /* PRIVATE. label "changed" callback.                                        */
345 /*---------------------------------------------------------------------------*/
346 static void
347 update_editor_from_label_cb (glLabel        *label,
348                              glObjectEditor *editor)
349 {
350         gdouble            label_width, label_height;
351         glMerge                    *merge;
352
353         gl_debug (DEBUG_VIEW, "START");
354
355         gl_label_get_size (label, &label_width, &label_height);
356         gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
357                                            label_width, label_height);
358         gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
359                                        label_width, label_height);
360         gl_object_editor_set_max_shadow_offset (GL_OBJECT_EDITOR (editor),
361                                                 label_width, label_height);
362         
363         merge = gl_label_get_merge (label);
364         gl_object_editor_set_key_names (editor, merge);
365
366         gl_debug (DEBUG_VIEW, "END");
367 }
368
369 /*****************************************************************************/
370 /* Is object at (x,y)?                                                       */
371 /*****************************************************************************/
372 static gboolean
373 object_at (glViewObject  *view_object,
374            cairo_t       *cr,
375            gdouble        x,
376            gdouble        y)
377 {
378         glLabelObject    *object;
379         gdouble           w, h;
380         gdouble           line_width;
381
382         object = gl_view_object_get_object (view_object);
383
384         gl_label_object_get_size (object, &w, &h);
385
386         gl_cairo_ellipse_path (cr, w/2, h/2);
387
388         if (cairo_in_fill (cr, x, y))
389         {
390                 return TRUE;
391         }
392
393         line_width = gl_label_object_get_line_width (object);
394         cairo_set_line_width (cr, line_width);
395         if (cairo_in_stroke (cr, x, y))
396         {
397                 return TRUE;
398         }
399
400         return FALSE;
401 }
402
403
404 /*****************************************************************************/
405 /* Return apropos cursor for create object mode.                             */
406 /*****************************************************************************/
407 GdkCursor *
408 gl_view_ellipse_get_create_cursor (void)
409 {
410         GdkCursor       *cursor = NULL;
411         GdkPixmap       *pixmap_data, *pixmap_mask;
412         GdkColor         fg = { 0, 0, 0, 0 };
413         GdkColor         bg = { 0, 65535, 65535, 65535 };
414
415         gl_debug (DEBUG_VIEW, "START");
416
417         pixmap_data = gdk_bitmap_create_from_data (NULL,
418                                                    (gchar *)cursor_ellipse_bits,
419                                                    cursor_ellipse_width,
420                                                    cursor_ellipse_height);
421         pixmap_mask = gdk_bitmap_create_from_data (NULL,
422                                                    (gchar *)cursor_ellipse_mask_bits,
423                                                    cursor_ellipse_mask_width,
424                                                    cursor_ellipse_mask_height);
425         cursor = gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
426                                              &bg, cursor_ellipse_x_hot,
427                                              cursor_ellipse_y_hot);
428
429         gl_debug (DEBUG_VIEW, "END");
430
431         return cursor;
432 }
433
434 /*****************************************************************************/
435 /* Object creation handler: button press event.                              */
436 /*****************************************************************************/
437 void
438 gl_view_ellipse_create_button_press_event   (glView *view,
439                                              gdouble x,
440                                              gdouble y)
441 {
442         GObject             *object;
443         glColorNode         *fill_color_node;
444         glColorNode         *line_color_node;
445
446         gl_view_unselect_all (view);
447
448         fill_color_node = gl_color_node_new_default ();
449         line_color_node = gl_color_node_new_default ();
450                 
451         object = gl_label_ellipse_new (view->label);
452         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
453         gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
454         line_color_node->color = gl_color_set_opacity (gl_view_get_default_line_color(view), 0.5);
455         fill_color_node->color = gl_color_set_opacity (gl_view_get_default_fill_color(view), 0.5);
456         gl_label_object_set_line_width (GL_LABEL_OBJECT(object),
457                                         gl_view_get_default_line_width(view));
458         gl_label_object_set_line_color (GL_LABEL_OBJECT(object),
459                                         line_color_node);
460         gl_label_object_set_fill_color (GL_LABEL_OBJECT(object),
461                                         fill_color_node);
462
463         gl_color_node_free (&fill_color_node);
464         gl_color_node_free (&line_color_node);
465
466         view->create_object = GL_LABEL_OBJECT (object);
467         view->create_x0 = x;
468         view->create_y0 = y;
469 }
470
471 /*****************************************************************************/
472 /* Object creation handler: motion event.                                    */
473 /*****************************************************************************/
474 void
475 gl_view_ellipse_create_motion_event     (glView *view,
476                                          gdouble x,
477                                          gdouble y)
478 {
479         gdouble w, h;
480
481         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
482                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
483         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
484         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
485         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
486 }
487
488 /*****************************************************************************/
489 /* Object creation handler: button relesase event.                           */
490 /*****************************************************************************/
491 void
492 gl_view_ellipse_create_button_release_event (glView *view,
493                                              gdouble x,
494                                              gdouble y)
495 {
496         glColorNode         *fill_color_node;
497         glColorNode         *line_color_node;
498         gdouble              w, h;
499
500         fill_color_node = gl_color_node_new_default ();
501         line_color_node = gl_color_node_new_default ();
502                 
503         if ((view->create_x0 == x) && (view->create_y0 == y)) {
504                 x = view->create_x0 + 36.0;
505                 y = view->create_y0 + 36.0;
506         }
507         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
508                                       MIN (x, view->create_x0), MIN (y, view->create_y0));
509         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
510         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
511         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
512         line_color_node->color = gl_view_get_default_line_color(view);
513         gl_label_object_set_line_color (GL_LABEL_OBJECT(view->create_object), line_color_node);
514         fill_color_node->color = gl_view_get_default_fill_color(view);
515         gl_label_object_set_fill_color (GL_LABEL_OBJECT(view->create_object), fill_color_node);
516         gl_color_node_free (&fill_color_node);
517         gl_color_node_free (&line_color_node);
518 }
519