2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * view_line.c: GLabels label line object widget
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "view-line.h"
27 #include "view-highlight.h"
29 #include "wdgt-line.h"
30 #include "wdgt-vector.h"
31 #include "wdgt-position.h"
35 #include "pixmaps/cursor_line.xbm"
36 #include "pixmaps/cursor_line_mask.xbm"
40 /*========================================================*/
41 /* Private macros and constants. */
42 /*========================================================*/
44 /*========================================================*/
46 /*========================================================*/
48 struct _glViewLinePrivate {
49 GnomeCanvasItem *item;
51 /* Property dialog Page 0 widgets */
54 /* Property dialog Page 1 widgets */
59 /*========================================================*/
60 /* Private globals. */
61 /*========================================================*/
63 static glViewObjectClass *parent_class = NULL;
66 /*========================================================*/
67 /* Private function prototypes. */
68 /*========================================================*/
70 static void gl_view_line_class_init (glViewLineClass *klass);
71 static void gl_view_line_instance_init (glViewLine *view_line);
72 static void gl_view_line_finalize (GObject *object);
74 static void update_view_line_cb (glLabelObject *object,
75 glViewLine *view_line);
77 static GtkWidget *construct_properties_dialog (glViewLine *view_line);
79 static void response_cb (GtkDialog *dialog,
81 glViewLine *view_line);
83 static void line_changed_cb (glWdgtLine *line,
84 glViewLine *view_line);
86 static void position_changed_cb (glWdgtPosition *position,
87 glViewLine *view_line);
89 static void vector_changed_cb (glWdgtVector *vector,
90 glViewLine *view_line);
92 static void update_dialog_cb (glLabelObject *object,
93 glViewLine *view_line);
95 static void update_dialog_from_move_cb (glLabelObject *object,
98 glViewLine *view_line);
101 /*****************************************************************************/
102 /* Boilerplate object stuff. */
103 /*****************************************************************************/
105 gl_view_line_get_type (void)
107 static GType type = 0;
111 sizeof (glViewLineClass),
114 (GClassInitFunc) gl_view_line_class_init,
119 (GInstanceInitFunc) gl_view_line_instance_init,
122 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
123 "glViewLine", &info, 0);
130 gl_view_line_class_init (glViewLineClass *klass)
132 GObjectClass *object_class = (GObjectClass *) klass;
134 gl_debug (DEBUG_VIEW, "START");
136 parent_class = g_type_class_peek_parent (klass);
138 object_class->finalize = gl_view_line_finalize;
140 gl_debug (DEBUG_VIEW, "END");
144 gl_view_line_instance_init (glViewLine *view_line)
146 gl_debug (DEBUG_VIEW, "START");
148 view_line->private = g_new0 (glViewLinePrivate, 1);
150 gl_debug (DEBUG_VIEW, "END");
154 gl_view_line_finalize (GObject *object)
158 gl_debug (DEBUG_VIEW, "START");
160 g_return_if_fail (object && GL_IS_VIEW_LINE (object));
162 G_OBJECT_CLASS (parent_class)->finalize (object);
164 gl_debug (DEBUG_VIEW, "END");
167 /*****************************************************************************/
168 /* NEW line object view. */
169 /*****************************************************************************/
171 gl_view_line_new (glLabelLine *object,
174 glViewLine *view_line;
179 GnomeCanvasPoints *points;
181 gl_debug (DEBUG_VIEW, "START");
182 g_return_if_fail (object && GL_IS_LABEL_LINE (object));
183 g_return_if_fail (view && GL_IS_VIEW (view));
185 view_line = g_object_new (gl_view_line_get_type(), NULL);
187 gl_view_object_set_view (GL_VIEW_OBJECT(view_line), view);
188 gl_view_object_set_object (GL_VIEW_OBJECT(view_line),
189 GL_LABEL_OBJECT(object),
190 GL_VIEW_HIGHLIGHT_LINE_RESIZABLE);
192 /* Query properties of object. */
193 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
194 line_width = gl_label_line_get_line_width(object);
195 line_color = gl_label_line_get_line_color(object);
197 /* Create analogous canvas item. */
198 points = gnome_canvas_points_new (2);
199 points->coords[0] = 0.0;
200 points->coords[1] = 0.0;
201 points->coords[2] = w;
202 points->coords[3] = h;
203 view_line->private->item =
204 gl_view_object_item_new (GL_VIEW_OBJECT(view_line),
205 gnome_canvas_line_get_type (),
207 "width_units", line_width,
208 "fill_color_rgba", line_color,
210 gnome_canvas_points_free (points);
212 g_signal_connect (G_OBJECT (object), "changed",
213 G_CALLBACK (update_view_line_cb), view_line);
215 /* Create a dialog for controlling/viewing object properties. */
216 gl_view_object_set_dlg_constructor (GL_VIEW_OBJECT(view_line),
217 GL_VIEW_OBJECT_DLG_CONSTRUCTOR(construct_properties_dialog));
219 gl_debug (DEBUG_VIEW, "END");
221 return GL_VIEW_OBJECT (view_line);
224 /*---------------------------------------------------------------------------*/
225 /* PRIVATE. label object "changed" callback. */
226 /*---------------------------------------------------------------------------*/
228 update_view_line_cb (glLabelObject *object,
229 glViewLine *view_line)
234 GnomeCanvasPoints *points;
236 gl_debug (DEBUG_VIEW, "START");
238 /* Query properties of object. */
239 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
240 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
241 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
243 /* Adjust appearance of analogous canvas item. */
244 points = gnome_canvas_points_new (2);
245 points->coords[0] = 0.0;
246 points->coords[1] = 0.0;
247 points->coords[2] = w;
248 points->coords[3] = h;
249 gnome_canvas_item_set (view_line->private->item,
251 "width_units", line_width,
252 "fill_color_rgba", line_color,
254 gnome_canvas_points_free (points);
256 gl_debug (DEBUG_VIEW, "END");
259 /*****************************************************************************/
260 /* Create a properties dialog for a line object. */
261 /*****************************************************************************/
263 construct_properties_dialog (glViewLine *view_line)
265 GtkWidget *dialog, *wsection;
266 glLabelObject *object;
269 gdouble x, y, w, h, label_width, label_height;
270 GtkSizeGroup *label_size_group;
273 gl_debug (DEBUG_VIEW, "START");
275 /* retrieve object and query parameters */
276 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
277 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
278 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
279 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
280 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
281 gl_label_get_size (GL_LABEL(object->parent),
282 &label_width, &label_height);
284 /*-----------------------------------------------------------------*/
285 /* Build dialog with notebook. */
286 /*-----------------------------------------------------------------*/
287 window = gtk_widget_get_toplevel (
288 GTK_WIDGET(gl_view_object_get_view(GL_VIEW_OBJECT(view_line))));
289 dialog = gl_hig_dialog_new_with_buttons ( _("Edit line object properties"),
291 GTK_DIALOG_DESTROY_WITH_PARENT,
295 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
296 g_signal_connect (G_OBJECT (dialog), "response",
297 G_CALLBACK (response_cb), view_line);
299 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
301 /*---------------------------*/
303 /*---------------------------*/
304 wsection = gl_hig_category_new (_("Line"));
305 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
306 view_line->private->line = gl_wdgt_line_new ();
307 gl_wdgt_line_set_label_size_group (GL_WDGT_LINE(view_line->private->line),
309 gl_wdgt_line_set_params (GL_WDGT_LINE (view_line->private->line),
312 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
313 view_line->private->line);
314 g_signal_connect (G_OBJECT (view_line->private->line), "changed",
315 G_CALLBACK(line_changed_cb), view_line);
317 /*---------------------------*/
318 /* Position section */
319 /*---------------------------*/
320 wsection = gl_hig_category_new (_("Position"));
321 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
322 view_line->private->position = gl_wdgt_position_new ();
323 gl_wdgt_position_set_label_size_group (GL_WDGT_POSITION(view_line->private->position),
325 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_line->private->position),
327 label_width, label_height);
328 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
329 view_line->private->position);
330 g_signal_connect (G_OBJECT (view_line->private->position),
332 G_CALLBACK(position_changed_cb), view_line);
335 /*---------------------------*/
337 /*---------------------------*/
338 wsection = gl_hig_category_new (_("Size"));
339 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
340 view_line->private->vector = gl_wdgt_vector_new ();
341 gl_wdgt_vector_set_label_size_group (GL_WDGT_VECTOR(view_line->private->vector),
343 gl_wdgt_vector_set_params (GL_WDGT_VECTOR (view_line->private->vector),
345 label_width, label_height);
346 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
347 view_line->private->vector);
348 g_signal_connect (G_OBJECT (view_line->private->vector), "changed",
349 G_CALLBACK(vector_changed_cb), view_line);
352 /*----------------------------*/
353 /* Track object changes. */
354 /*----------------------------*/
355 g_signal_connect (G_OBJECT (object), "changed",
356 G_CALLBACK (update_dialog_cb), view_line);
357 g_signal_connect (G_OBJECT (object), "moved",
358 G_CALLBACK (update_dialog_from_move_cb), view_line);
360 gl_debug (DEBUG_VIEW, "END");
365 /*---------------------------------------------------------------------------*/
366 /* PRIVATE. "Response" callback. */
367 /*---------------------------------------------------------------------------*/
369 response_cb (GtkDialog *dialog,
371 glViewLine *view_line)
373 gl_debug (DEBUG_VIEW, "START");
375 g_return_if_fail(dialog != NULL);
376 g_return_if_fail(GTK_IS_DIALOG(dialog));
379 case GTK_RESPONSE_CLOSE:
380 gtk_widget_hide (GTK_WIDGET(dialog));
382 case GTK_RESPONSE_DELETE_EVENT:
385 g_print ("response = %d", response);
386 g_assert_not_reached();
389 gl_debug (DEBUG_VIEW, "END");
392 /*---------------------------------------------------------------------------*/
393 /* PRIVATE. line properties "changed" callback. */
394 /*---------------------------------------------------------------------------*/
396 line_changed_cb (glWdgtLine *line,
397 glViewLine *view_line)
399 glLabelObject *object;
403 gl_debug (DEBUG_VIEW, "START");
405 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
407 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
411 g_signal_handlers_block_by_func (G_OBJECT(object),
412 update_dialog_cb, view_line);
413 gl_label_line_set_line_width(GL_LABEL_LINE(object), line_width);
414 gl_label_line_set_line_color(GL_LABEL_LINE(object), line_color);
415 g_signal_handlers_unblock_by_func (G_OBJECT(object),
416 update_dialog_cb, view_line);
418 gl_debug (DEBUG_VIEW, "END");
421 /*---------------------------------------------------------------------------*/
422 /* PRIVATE. position "changed" callback. */
423 /*---------------------------------------------------------------------------*/
425 position_changed_cb (glWdgtPosition *position,
426 glViewLine *view_line)
428 glLabelObject *object;
431 gl_debug (DEBUG_VIEW, "START");
433 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
435 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
437 g_signal_handlers_block_by_func (G_OBJECT(object),
438 update_dialog_cb, view_line);
439 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
440 g_signal_handlers_unblock_by_func (G_OBJECT(object),
441 update_dialog_cb, view_line);
443 gl_debug (DEBUG_VIEW, "END");
446 /*---------------------------------------------------------------------------*/
447 /* PRIVATE. vector "changed" callback. */
448 /*---------------------------------------------------------------------------*/
450 vector_changed_cb (glWdgtVector *vector,
451 glViewLine *view_line)
453 glLabelObject *object;
455 gboolean keep_aspect_ratio_flag;
457 gl_debug (DEBUG_VIEW, "START");
459 gl_wdgt_vector_get_params (GL_WDGT_VECTOR (vector), &w, &h);
461 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
463 g_signal_handlers_block_by_func (G_OBJECT(object),
464 update_dialog_cb, view_line);
465 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
466 g_signal_handlers_unblock_by_func (G_OBJECT(object),
467 update_dialog_cb, view_line);
469 gl_debug (DEBUG_VIEW, "END");
472 /*---------------------------------------------------------------------------*/
473 /* PRIVATE. label object "changed" callback. */
474 /*---------------------------------------------------------------------------*/
476 update_dialog_cb (glLabelObject *object,
477 glViewLine *view_line)
481 gdouble x, y, w, h, label_width, label_height;
483 gl_debug (DEBUG_VIEW, "START");
485 /* Query properties of object. */
486 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
487 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
488 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
489 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
490 gl_label_get_size (GL_LABEL(object->parent),
491 &label_width, &label_height);
493 /* Block widget handlers to prevent recursion */
494 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->line),
495 line_changed_cb, view_line);
496 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->position),
497 position_changed_cb, view_line);
498 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->vector),
499 vector_changed_cb, view_line);
501 /* Update widgets in property dialog */
502 gl_wdgt_line_set_params (GL_WDGT_LINE (view_line->private->line),
505 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_line->private->position),
507 gl_wdgt_vector_set_params (GL_WDGT_VECTOR(view_line->private->vector),
508 w, h, label_width, label_height);
510 /* Unblock widget handlers */
511 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->line),
512 line_changed_cb, view_line);
513 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->position),
514 position_changed_cb, view_line);
515 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->vector),
516 vector_changed_cb, view_line);
519 gl_debug (DEBUG_VIEW, "END");
522 /*---------------------------------------------------------------------------*/
523 /* PRIVATE. label object "moved" callback. */
524 /*---------------------------------------------------------------------------*/
526 update_dialog_from_move_cb (glLabelObject *object,
529 glViewLine *view_line)
533 gl_debug (DEBUG_VIEW, "START");
535 /* Query properties of object. */
536 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
538 /* Block widget handlers to prevent recursion */
539 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->position),
540 position_changed_cb, view_line);
542 /* Update widgets in property dialog */
543 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_line->private->position),
546 /* Unblock widget handlers */
547 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->position),
548 position_changed_cb, view_line);
550 gl_debug (DEBUG_VIEW, "END");
553 /*****************************************************************************/
554 /* Return apropos cursor for create object mode. */
555 /*****************************************************************************/
557 gl_view_line_get_create_cursor (void)
559 static GdkCursor *cursor = NULL;
560 GdkPixmap *pixmap_data, *pixmap_mask;
561 GdkColor fg = { 0, 0, 0, 0 };
562 GdkColor bg = { 0, 65535, 65535, 65535 };
564 gl_debug (DEBUG_VIEW, "START");
567 pixmap_data = gdk_bitmap_create_from_data (NULL,
571 pixmap_mask = gdk_bitmap_create_from_data (NULL,
572 cursor_line_mask_bits,
573 cursor_line_mask_width,
574 cursor_line_mask_height);
576 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
577 &bg, cursor_line_x_hot,
581 gl_debug (DEBUG_VIEW, "END");
586 /*****************************************************************************/
587 /* Canvas event handler for creating line objects. */
588 /*****************************************************************************/
590 gl_view_line_create_event_handler (GnomeCanvas *canvas,
594 static gdouble x0, y0;
595 static gboolean dragging = FALSE;
596 static glViewObject *view_line;
597 static GObject *object;
600 gl_debug (DEBUG_VIEW, "");
602 switch (event->type) {
604 case GDK_BUTTON_PRESS:
605 switch (event->button.button) {
608 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
610 GDK_POINTER_MOTION_MASK |
611 GDK_BUTTON_RELEASE_MASK |
612 GDK_BUTTON_PRESS_MASK,
613 NULL, NULL, event->button.time);
614 gnome_canvas_window_to_world (canvas,
616 event->button.y, &x, &y);
617 object = gl_label_line_new (view->label);
618 gl_label_object_set_position (GL_LABEL_OBJECT(object),
620 gl_label_object_set_size (GL_LABEL_OBJECT(object),
622 gl_label_line_set_line_width (GL_LABEL_LINE(object),
623 gl_prefs->default_line_width);
624 gl_label_line_set_line_color (GL_LABEL_LINE(object),
625 gl_color_set_opacity (gl_prefs->default_line_color, 0.5));
626 view_line = gl_view_line_new (GL_LABEL_LINE(object),
636 case GDK_BUTTON_RELEASE:
637 switch (event->button.button) {
640 gdk_pointer_ungrab (event->button.time);
641 gnome_canvas_window_to_world (canvas,
643 event->button.y, &x, &y);
644 if ((x0 == x) && (y0 == y)) {
650 gl_label_object_set_size (GL_LABEL_OBJECT(object),
652 gl_label_line_set_line_color (GL_LABEL_LINE(object),
653 gl_prefs->default_line_color);
654 gl_view_unselect_all (view);
655 gl_view_object_select (GL_VIEW_OBJECT(view_line));
656 gl_view_arrow_mode (view);
663 case GDK_MOTION_NOTIFY:
664 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
665 gnome_canvas_window_to_world (canvas,
667 event->motion.y, &x, &y);
670 gl_label_object_set_size (GL_LABEL_OBJECT(object),