]> git.sur5r.net Git - glabels/blob - glabels2/src/view-line.c
2007-11-26 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / view-line.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_line.c:  GLabels label line 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-line.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_line.xbm"
36 #include "pixmaps/cursor_line_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 _glViewLinePrivate {
50 };
51
52 /*========================================================*/
53 /* Private globals.                                       */
54 /*========================================================*/
55
56
57 /*========================================================*/
58 /* Private function prototypes.                           */
59 /*========================================================*/
60
61 static void       gl_view_line_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 (glViewLine, gl_view_line, GL_TYPE_VIEW_OBJECT);
90
91
92 static void
93 gl_view_line_class_init (glViewLineClass *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_line_parent_class = g_type_class_peek_parent (class);
101
102         object_class->finalize = gl_view_line_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_line_init (glViewLine *view_line)
112 {
113         gl_debug (DEBUG_VIEW, "START");
114
115         view_line->priv = g_new0 (glViewLinePrivate, 1);
116
117         gl_debug (DEBUG_VIEW, "END");
118 }
119
120 static void
121 gl_view_line_finalize (GObject *object)
122 {
123         glViewLine *view_line = GL_VIEW_LINE (object);
124
125         gl_debug (DEBUG_VIEW, "START");
126
127         g_return_if_fail (object && GL_IS_VIEW_LINE (object));
128
129         g_free (view_line->priv);
130
131         G_OBJECT_CLASS (gl_view_line_parent_class)->finalize (object);
132
133         gl_debug (DEBUG_VIEW, "END");
134 }
135
136 /*****************************************************************************/
137 /* NEW line object view.                                                  */
138 /*****************************************************************************/
139 glViewObject *
140 gl_view_line_new (glLabelLine *object,
141                   glView     *view)
142 {
143         glViewLine         *view_line;
144
145         gl_debug (DEBUG_VIEW, "START");
146
147         g_return_val_if_fail (object && GL_IS_LABEL_LINE (object), NULL);
148         g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
149         
150         view_line = g_object_new (gl_view_line_get_type(), NULL);
151
152         gl_view_object_set_object (GL_VIEW_OBJECT(view_line),
153                                    GL_LABEL_OBJECT(object),
154                                    GL_VIEW_OBJECT_HANDLES_LINE);
155         gl_view_object_set_view (GL_VIEW_OBJECT(view_line), view);
156
157         gl_debug (DEBUG_VIEW, "END");
158
159         return GL_VIEW_OBJECT (view_line);
160 }
161
162 /*****************************************************************************/
163 /* Create a properties dialog for a line object.                             */
164 /*****************************************************************************/
165 static GtkWidget *
166 construct_properties_editor (glViewObject *view_object)
167 {
168         GtkWidget          *editor;
169         glViewLine         *view_line = (glViewLine *)view_object;
170         glLabelObject      *object;
171
172         gl_debug (DEBUG_VIEW, "START");
173
174         object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
175
176         /* Build editor. */
177         editor = gl_object_editor_new (GL_STOCK_LINE, _("Line object properties"),
178                                        GL_OBJECT_EDITOR_SHADOW_PAGE,
179                                        GL_OBJECT_EDITOR_POSITION_PAGE,
180                                        GL_OBJECT_EDITOR_SIZE_LINE_PAGE,
181                                        GL_OBJECT_EDITOR_LINE_PAGE,
182                                        0);
183         
184         /* Update */
185         update_editor_from_label_cb (object->parent, GL_OBJECT_EDITOR(editor));
186         update_editor_from_object_cb (object, GL_OBJECT_EDITOR(editor));
187         update_editor_from_move_cb (object, 0, 0, GL_OBJECT_EDITOR(editor));
188
189         /* Connect signals. */
190         g_signal_connect (G_OBJECT (editor), "changed",
191                           G_CALLBACK(update_object_from_editor_cb), object);
192         g_signal_connect (G_OBJECT (object), "changed",
193                           G_CALLBACK (update_editor_from_object_cb), editor);
194         g_signal_connect (G_OBJECT (object), "moved",
195                           G_CALLBACK (update_editor_from_move_cb), editor);
196         g_signal_connect (G_OBJECT (object->parent), "size_changed",
197                           G_CALLBACK (update_editor_from_label_cb), editor);
198         g_signal_connect (G_OBJECT (object->parent), "merge_changed",
199                           G_CALLBACK (update_editor_from_label_cb), editor);
200
201         gl_debug (DEBUG_VIEW, "END");
202
203         return editor;
204 }
205
206 /*---------------------------------------------------------------------------*/
207 /* PRIVATE.  editor "changed" callback.                                      */
208 /*---------------------------------------------------------------------------*/
209 static void
210 update_object_from_editor_cb (glObjectEditor *editor,
211                               glLabelObject  *object)
212 {
213         gdouble            x, y, w, h;
214         glColorNode       *line_color_node;
215         gdouble            line_width;
216         gboolean           shadow_state;
217         gdouble            shadow_x, shadow_y;
218         glColorNode       *shadow_color_node;
219         gdouble            shadow_opacity;
220         
221
222         gl_debug (DEBUG_VIEW, "START");
223
224         g_signal_handlers_block_by_func (G_OBJECT(object),
225                                          update_editor_from_object_cb,
226                                          editor);
227         g_signal_handlers_block_by_func (G_OBJECT(object),
228                                          update_editor_from_move_cb,
229                                          editor);
230
231         gl_object_editor_get_position (editor, &x, &y);
232         gl_label_object_set_position (object, x, y);
233
234         gl_object_editor_get_lsize (editor, &w, &h);
235         gl_label_object_set_size (object, w, h);
236
237         line_color_node = gl_object_editor_get_line_color (editor);
238         gl_label_object_set_line_color (object, line_color_node);
239         gl_color_node_free (&line_color_node);
240
241         line_width = gl_object_editor_get_line_width (editor);
242         gl_label_object_set_line_width (object, line_width);
243
244         shadow_state = gl_object_editor_get_shadow_state (editor);
245         gl_label_object_set_shadow_state (object, shadow_state);
246
247         gl_object_editor_get_shadow_offset (editor, &shadow_x, &shadow_y);
248         gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
249
250         shadow_color_node = gl_object_editor_get_shadow_color (editor);
251         gl_label_object_set_shadow_color (object, shadow_color_node);
252         gl_color_node_free (&shadow_color_node);
253
254         shadow_opacity = gl_object_editor_get_shadow_opacity (editor);
255         gl_label_object_set_shadow_opacity (object, shadow_opacity);
256
257         g_signal_handlers_unblock_by_func (G_OBJECT(object),
258                                            update_editor_from_object_cb,
259                                            editor);
260         g_signal_handlers_unblock_by_func (G_OBJECT(object),
261                                            update_editor_from_move_cb,
262                                            editor);
263
264         gl_debug (DEBUG_VIEW, "END");
265 }
266
267 /*---------------------------------------------------------------------------*/
268 /* PRIVATE. label object "changed" callback.                                 */
269 /*---------------------------------------------------------------------------*/
270 static void
271 update_editor_from_object_cb (glLabelObject  *object,
272                               glObjectEditor *editor)
273 {
274         gdouble            w, h;
275         glColorNode       *line_color_node;
276         gdouble            line_width;
277         gboolean           shadow_state;
278         gdouble            shadow_x, shadow_y;
279         glColorNode       *shadow_color_node;
280         gdouble            shadow_opacity;
281         glMerge           *merge;
282
283         gl_debug (DEBUG_VIEW, "START");
284
285         gl_label_object_get_size (object, &w, &h);
286         gl_object_editor_set_lsize (editor, w, h);
287         merge = gl_label_get_merge (GL_LABEL(object->parent));
288         
289         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
290         gl_object_editor_set_line_color (editor, (merge != NULL), line_color_node);
291         gl_color_node_free (&line_color_node);
292
293         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
294         gl_object_editor_set_line_width (editor, line_width);
295
296         shadow_state = gl_label_object_get_shadow_state (object);
297         gl_object_editor_set_shadow_state (editor, shadow_state);
298
299         gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
300         gl_object_editor_set_shadow_offset (editor, shadow_x, shadow_y);
301
302         shadow_color_node = gl_label_object_get_shadow_color (object);
303         gl_object_editor_set_shadow_color (editor, (merge != NULL), shadow_color_node);
304         gl_color_node_free (&shadow_color_node);
305
306         shadow_opacity = gl_label_object_get_shadow_opacity (object);
307         gl_object_editor_set_shadow_opacity (editor, shadow_opacity);
308
309         gl_debug (DEBUG_VIEW, "END");
310 }
311
312 /*---------------------------------------------------------------------------*/
313 /* PRIVATE. label object "moved" callback.                                   */
314 /*---------------------------------------------------------------------------*/
315 static void
316 update_editor_from_move_cb (glLabelObject    *object,
317                             gdouble           dx,
318                             gdouble           dy,
319                             glObjectEditor   *editor)
320 {
321         gdouble            x, y;
322
323         gl_debug (DEBUG_VIEW, "START");
324
325         gl_label_object_get_position (object, &x, &y);
326         gl_object_editor_set_position (editor, x, y);
327
328         gl_debug (DEBUG_VIEW, "END");
329 }
330
331 /*---------------------------------------------------------------------------*/
332 /* PRIVATE. label "changed" callback.                                        */
333 /*---------------------------------------------------------------------------*/
334 static void
335 update_editor_from_label_cb (glLabel        *label,
336                              glObjectEditor *editor)
337 {
338         gdouble            label_width, label_height;
339         glMerge                    *merge;
340
341         gl_debug (DEBUG_VIEW, "START");
342
343         gl_label_get_size (label, &label_width, &label_height);
344         gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
345                                            label_width, label_height);
346         gl_object_editor_set_max_lsize (GL_OBJECT_EDITOR (editor),
347                                         label_width, label_height);
348         gl_object_editor_set_max_shadow_offset (GL_OBJECT_EDITOR (editor),
349                                                 label_width, label_height);
350         
351         merge = gl_label_get_merge (label);
352         gl_object_editor_set_key_names (editor, merge);
353
354         gl_debug (DEBUG_VIEW, "END");
355 }
356
357 /*****************************************************************************/
358 /* Is object at (x,y)?                                                       */
359 /*****************************************************************************/
360 static gboolean
361 object_at (glViewObject  *view_object,
362            cairo_t       *cr,
363            gdouble        x,
364            gdouble        y)
365 {
366         glLabelObject    *object;
367         gdouble           w, h;
368         gdouble           line_width;
369
370         object = gl_view_object_get_object (view_object);
371
372         gl_label_object_get_size (object, &w, &h);
373
374         cairo_move_to (cr, 0.0, 0.0);
375         cairo_line_to (cr, w, h);
376
377         line_width = gl_label_object_get_line_width (object);
378         cairo_set_line_width (cr, line_width);
379         if (cairo_in_stroke (cr, x, y))
380         {
381                 return TRUE;
382         }
383
384         return FALSE;
385 }
386
387
388 /*****************************************************************************/
389 /* Return apropos cursor for create object mode.                             */
390 /*****************************************************************************/
391 GdkCursor *
392 gl_view_line_get_create_cursor (void)
393 {
394         GdkCursor       *cursor = NULL;
395         GdkPixmap       *pixmap_data, *pixmap_mask;
396         GdkColor         fg = { 0, 0, 0, 0 };
397         GdkColor         bg = { 0, 65535, 65535, 65535 };
398
399         gl_debug (DEBUG_VIEW, "START");
400
401         pixmap_data = gdk_bitmap_create_from_data (NULL,
402                                                    (gchar *)cursor_line_bits,
403                                                    cursor_line_width,
404                                                    cursor_line_height);
405         pixmap_mask = gdk_bitmap_create_from_data (NULL,
406                                                    (gchar *)cursor_line_mask_bits,
407                                                    cursor_line_mask_width,
408                                                    cursor_line_mask_height);
409         cursor = gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
410                                              &bg, cursor_line_x_hot,
411                                              cursor_line_y_hot);
412
413         gl_debug (DEBUG_VIEW, "END");
414
415         return cursor;
416 }
417
418 /*****************************************************************************/
419 /* Object creation handler: button press event.                              */
420 /*****************************************************************************/
421 void
422 gl_view_line_create_button_press_event   (glView *view,
423                                           gdouble x,
424                                           gdouble y)
425 {
426         GObject             *object;
427         glColorNode         *line_color_node;
428
429         gl_view_unselect_all (view);
430
431         line_color_node = gl_color_node_new_default ();
432                 
433         object = gl_label_line_new (view->label);
434         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
435         gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
436         line_color_node->color = gl_color_set_opacity (gl_view_get_default_line_color(view), 0.5);
437         gl_label_object_set_line_width (GL_LABEL_OBJECT(object),
438                                         gl_view_get_default_line_width(view));
439         gl_label_object_set_line_color (GL_LABEL_OBJECT(object),
440                                         line_color_node);
441
442         gl_color_node_free (&line_color_node);
443
444         view->create_object = GL_LABEL_OBJECT (object);
445         view->create_x0 = x;
446         view->create_y0 = y;
447 }
448
449 /*****************************************************************************/
450 /* Object creation handler: motion event.                                    */
451 /*****************************************************************************/
452 void
453 gl_view_line_create_motion_event     (glView *view,
454                                       gdouble x,
455                                       gdouble y)
456 {
457         gdouble w, h;
458
459         w = x - view->create_x0;
460         h = y - view->create_y0;
461         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
462 }
463
464 /*****************************************************************************/
465 /* Object creation handler: button relesase event.                           */
466 /*****************************************************************************/
467 void
468 gl_view_line_create_button_release_event (glView *view,
469                                           gdouble x,
470                                           gdouble y)
471 {
472         glColorNode         *line_color_node;
473         gdouble              w, h;
474
475         line_color_node = gl_color_node_new_default ();
476                 
477         if ((view->create_x0 == x) && (view->create_y0 == y)) {
478                 x = view->create_x0 + 36.0;
479                 y = view->create_y0 + 36.0;
480         }
481         w = x - view->create_x0;
482         h = y - view->create_y0;
483         gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
484         line_color_node->color = gl_view_get_default_line_color(view);
485         gl_label_object_set_line_color (GL_LABEL_OBJECT(view->create_object), line_color_node);
486         gl_color_node_free (&line_color_node);
487 }
488