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"
30 #include "wdgt-line.h"
31 #include "wdgt-vector.h"
32 #include "wdgt-position.h"
34 #include "pixmaps/cursor_line.xbm"
35 #include "pixmaps/cursor_line_mask.xbm"
39 /*========================================================*/
40 /* Private macros and constants. */
41 /*========================================================*/
42 #define CREATE_LINE_COLOR GNOME_CANVAS_COLOR_A (0, 0, 0, 192)
44 #define DEFAULT_LINE_COLOR GNOME_CANVAS_COLOR_A (0, 0, 0, 255)
46 /*========================================================*/
48 /*========================================================*/
50 struct _glViewLinePrivate {
51 GnomeCanvasItem *item;
53 /* Property dialog Page 0 widgets */
56 /* Property dialog Page 1 widgets */
61 /*========================================================*/
62 /* Private globals. */
63 /*========================================================*/
65 static glViewObjectClass *parent_class = NULL;
68 /*========================================================*/
69 /* Private function prototypes. */
70 /*========================================================*/
72 static void gl_view_line_class_init (glViewLineClass *klass);
73 static void gl_view_line_instance_init (glViewLine *view_line);
74 static void gl_view_line_finalize (GObject *object);
76 static void update_view_line_cb (glLabelObject *object,
77 glViewLine *view_line);
79 static GtkWidget *construct_properties_dialog (glViewLine *view_line);
81 static void response_cb (GtkDialog *dialog,
83 glViewLine *view_line);
85 static void line_changed_cb (glWdgtLine *line,
86 glViewLine *view_line);
88 static void position_changed_cb (glWdgtPosition *position,
89 glViewLine *view_line);
91 static void vector_changed_cb (glWdgtVector *vector,
92 glViewLine *view_line);
94 static void update_dialog_cb (glLabelObject *object,
95 glViewLine *view_line);
98 /*****************************************************************************/
99 /* Boilerplate object stuff. */
100 /*****************************************************************************/
102 gl_view_line_get_type (void)
104 static GType type = 0;
108 sizeof (glViewLineClass),
111 (GClassInitFunc) gl_view_line_class_init,
116 (GInstanceInitFunc) gl_view_line_instance_init,
119 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
120 "glViewLine", &info, 0);
127 gl_view_line_class_init (glViewLineClass *klass)
129 GObjectClass *object_class = (GObjectClass *) klass;
131 gl_debug (DEBUG_VIEW, "START");
133 parent_class = g_type_class_peek_parent (klass);
135 object_class->finalize = gl_view_line_finalize;
137 gl_debug (DEBUG_VIEW, "END");
141 gl_view_line_instance_init (glViewLine *view_line)
143 gl_debug (DEBUG_VIEW, "START");
145 view_line->private = g_new0 (glViewLinePrivate, 1);
147 gl_debug (DEBUG_VIEW, "END");
151 gl_view_line_finalize (GObject *object)
155 gl_debug (DEBUG_VIEW, "START");
157 g_return_if_fail (object && GL_IS_VIEW_LINE (object));
159 G_OBJECT_CLASS (parent_class)->finalize (object);
161 gl_debug (DEBUG_VIEW, "END");
164 /*****************************************************************************/
165 /* NEW line object view. */
166 /*****************************************************************************/
168 gl_view_line_new (glLabelLine *object,
171 glViewLine *view_line;
172 GnomeCanvasItem *group;
178 GnomeCanvasPoints *points;
180 gl_debug (DEBUG_VIEW, "START");
181 g_return_if_fail (object && GL_IS_LABEL_LINE (object));
182 g_return_if_fail (view && GL_IS_VIEW (view));
184 view_line = g_object_new (gl_view_line_get_type(), NULL);
186 gl_view_object_set_view (GL_VIEW_OBJECT(view_line), view);
187 gl_view_object_set_object (GL_VIEW_OBJECT(view_line),
188 GL_LABEL_OBJECT(object),
189 GL_VIEW_HIGHLIGHT_LINE_RESIZABLE);
191 /* Query properties of object. */
192 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
193 line_width = gl_label_line_get_line_width(object);
194 line_color = gl_label_line_get_line_color(object);
196 /* Create analogous canvas item. */
197 group = gl_view_object_get_group (GL_VIEW_OBJECT(view_line));
199 points = gnome_canvas_points_new (2);
200 points->coords[0] = 0.0;
201 points->coords[1] = 0.0;
202 points->coords[2] = w;
203 points->coords[3] = h;
204 view_line->private->item =
205 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
206 gnome_canvas_line_get_type (),
208 "width_units", line_width,
209 "fill_color_rgba", line_color,
211 gnome_canvas_points_free (points);
213 g_signal_connect (G_OBJECT (object), "changed",
214 G_CALLBACK (update_view_line_cb), view_line);
216 /* Create a dialog for controlling/viewing object properties. */
217 dialog = construct_properties_dialog (view_line);
218 gl_view_object_set_dialog (GL_VIEW_OBJECT(view_line), dialog);
220 gl_debug (DEBUG_VIEW, "END");
222 return GL_VIEW_OBJECT (view_line);
225 /*---------------------------------------------------------------------------*/
226 /* PRIVATE. label object "changed" callback. */
227 /*---------------------------------------------------------------------------*/
229 update_view_line_cb (glLabelObject *object,
230 glViewLine *view_line)
235 GnomeCanvasPoints *points;
237 gl_debug (DEBUG_VIEW, "START");
239 /* Query properties of object. */
240 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
241 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
242 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
244 /* Adjust appearance of analogous canvas item. */
245 points = gnome_canvas_points_new (2);
246 points->coords[0] = 0.0;
247 points->coords[1] = 0.0;
248 points->coords[2] = w;
249 points->coords[3] = h;
250 gnome_canvas_item_set (view_line->private->item,
252 "width_units", line_width,
253 "fill_color_rgba", line_color,
255 gnome_canvas_points_free (points);
257 /* Adjust highlight */
258 gl_view_object_update_highlight (GL_VIEW_OBJECT(view_line));
260 gl_debug (DEBUG_VIEW, "END");
263 /*****************************************************************************/
264 /* Create a properties dialog for a line object. */
265 /*****************************************************************************/
267 construct_properties_dialog (glViewLine *view_line)
269 GtkWidget *dialog, *notebook, *wvbox;
270 BonoboWindow *win = glabels_get_active_window ();
271 glLabelObject *object;
274 gdouble x, y, w, h, label_width, label_height;
276 gl_debug (DEBUG_VIEW, "START");
278 /* retrieve object and query parameters */
279 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
280 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
281 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
282 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
283 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
284 gl_label_get_size (GL_LABEL(object->parent),
285 &label_width, &label_height);
287 /*-----------------------------------------------------------------*/
288 /* Build dialog with notebook. */
289 /*-----------------------------------------------------------------*/
290 dialog = gtk_dialog_new_with_buttons ( _("Edit line object properties"),
292 GTK_DIALOG_DESTROY_WITH_PARENT,
296 g_signal_connect (G_OBJECT (dialog), "response",
297 G_CALLBACK (response_cb), view_line);
299 notebook = gtk_notebook_new ();
300 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
301 notebook, TRUE, TRUE, 0);
303 /*---------------------------*/
304 /* Appearance Notebook Tab */
305 /*---------------------------*/
306 wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
307 gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
308 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), wvbox,
309 gtk_label_new (_("Appearance")));
311 /* ------ Line line ------ */
312 view_line->private->line = gl_wdgt_line_new (_("Outline"));
313 gl_wdgt_line_set_params (GL_WDGT_LINE (view_line->private->line),
316 gtk_box_pack_start (GTK_BOX (wvbox), view_line->private->line,
318 g_signal_connect (G_OBJECT (view_line->private->line), "changed",
319 G_CALLBACK(line_changed_cb), view_line);
322 /*----------------------------*/
323 /* Position/Size Notebook Tab */
324 /*----------------------------*/
325 wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
326 gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
327 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), wvbox,
328 gtk_label_new (_("Position/Size")));
330 /* ------ Position Frame ------ */
331 view_line->private->position = gl_wdgt_position_new (_("Position"));
332 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_line->private->position),
334 label_width, label_height);
335 gtk_box_pack_start (GTK_BOX (wvbox),
336 view_line->private->position,
338 g_signal_connect (G_OBJECT (view_line->private->position),
340 G_CALLBACK(position_changed_cb), view_line);
343 /* ------ Size Frame ------ */
344 view_line->private->vector = gl_wdgt_vector_new (_("Size"));
345 gl_wdgt_vector_set_params (GL_WDGT_VECTOR (view_line->private->vector),
347 label_width, label_height);
348 gtk_box_pack_start (GTK_BOX (wvbox), view_line->private->vector,
350 g_signal_connect (G_OBJECT (view_line->private->vector), "changed",
351 G_CALLBACK(vector_changed_cb), view_line);
354 /*----------------------------*/
355 /* Track object changes. */
356 /*----------------------------*/
357 g_signal_connect (G_OBJECT (object), "changed",
358 G_CALLBACK (update_dialog_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));
383 g_assert_not_reached();
386 gl_debug (DEBUG_VIEW, "END");
389 /*---------------------------------------------------------------------------*/
390 /* PRIVATE. line properties "changed" callback. */
391 /*---------------------------------------------------------------------------*/
393 line_changed_cb (glWdgtLine *line,
394 glViewLine *view_line)
396 glLabelObject *object;
400 gl_debug (DEBUG_VIEW, "START");
402 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
404 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
408 g_signal_handlers_block_by_func (G_OBJECT(object),
409 update_dialog_cb, view_line);
410 gl_label_line_set_line_width(GL_LABEL_LINE(object), line_width);
411 gl_label_line_set_line_color(GL_LABEL_LINE(object), line_color);
412 g_signal_handlers_unblock_by_func (G_OBJECT(object),
413 update_dialog_cb, view_line);
415 gl_debug (DEBUG_VIEW, "END");
418 /*---------------------------------------------------------------------------*/
419 /* PRIVATE. position "changed" callback. */
420 /*---------------------------------------------------------------------------*/
422 position_changed_cb (glWdgtPosition *position,
423 glViewLine *view_line)
425 glLabelObject *object;
428 gl_debug (DEBUG_VIEW, "START");
430 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
432 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
434 g_signal_handlers_block_by_func (G_OBJECT(object),
435 update_dialog_cb, view_line);
436 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
437 g_signal_handlers_unblock_by_func (G_OBJECT(object),
438 update_dialog_cb, view_line);
440 gl_debug (DEBUG_VIEW, "END");
443 /*---------------------------------------------------------------------------*/
444 /* PRIVATE. vector "changed" callback. */
445 /*---------------------------------------------------------------------------*/
447 vector_changed_cb (glWdgtVector *vector,
448 glViewLine *view_line)
450 glLabelObject *object;
452 gboolean keep_aspect_ratio_flag;
454 gl_debug (DEBUG_VIEW, "START");
456 gl_wdgt_vector_get_params (GL_WDGT_VECTOR (vector), &w, &h);
458 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_line));
460 g_signal_handlers_block_by_func (G_OBJECT(object),
461 update_dialog_cb, view_line);
462 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
463 g_signal_handlers_unblock_by_func (G_OBJECT(object),
464 update_dialog_cb, view_line);
466 gl_debug (DEBUG_VIEW, "END");
469 /*---------------------------------------------------------------------------*/
470 /* PRIVATE. label object "changed" callback. */
471 /*---------------------------------------------------------------------------*/
473 update_dialog_cb (glLabelObject *object,
474 glViewLine *view_line)
478 gdouble x, y, w, h, label_width, label_height;
480 gl_debug (DEBUG_VIEW, "START");
482 /* Query properties of object. */
483 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
484 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
485 line_width = gl_label_line_get_line_width(GL_LABEL_LINE(object));
486 line_color = gl_label_line_get_line_color(GL_LABEL_LINE(object));
487 gl_label_get_size (GL_LABEL(object->parent),
488 &label_width, &label_height);
490 /* Block widget handlers to prevent recursion */
491 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->line),
492 line_changed_cb, view_line);
493 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->position),
494 position_changed_cb, view_line);
495 g_signal_handlers_block_by_func (G_OBJECT(view_line->private->vector),
496 vector_changed_cb, view_line);
498 /* Update widgets in property dialog */
499 gl_wdgt_line_set_params (GL_WDGT_LINE (view_line->private->line),
502 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_line->private->position),
504 gl_wdgt_vector_set_params (GL_WDGT_VECTOR(view_line->private->vector),
505 w, h, label_width, label_height);
507 /* Unblock widget handlers */
508 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->line),
509 line_changed_cb, view_line);
510 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->position),
511 position_changed_cb, view_line);
512 g_signal_handlers_unblock_by_func (G_OBJECT(view_line->private->vector),
513 vector_changed_cb, view_line);
516 gl_debug (DEBUG_VIEW, "END");
519 /*****************************************************************************/
520 /* Return apropos cursor for create object mode. */
521 /*****************************************************************************/
523 gl_view_line_get_create_cursor (void)
525 static GdkCursor *cursor = NULL;
526 GdkPixmap *pixmap_data, *pixmap_mask;
527 GdkColor fg = { 0, 0, 0, 0 };
528 GdkColor bg = { 0, 65535, 65535, 65535 };
530 gl_debug (DEBUG_VIEW, "START");
533 pixmap_data = gdk_bitmap_create_from_data (NULL,
537 pixmap_mask = gdk_bitmap_create_from_data (NULL,
538 cursor_line_mask_bits,
539 cursor_line_mask_width,
540 cursor_line_mask_height);
542 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
543 &bg, cursor_line_x_hot,
547 gl_debug (DEBUG_VIEW, "END");
552 /*****************************************************************************/
553 /* Canvas event handler for creating line objects. */
554 /*****************************************************************************/
556 gl_view_line_create_event_handler (GnomeCanvas *canvas,
560 static gdouble x0, y0;
561 static gboolean dragging = FALSE;
562 static glViewObject *view_line;
563 static GObject *object;
568 gl_debug (DEBUG_VIEW, "");
570 switch (event->type) {
572 case GDK_BUTTON_PRESS:
573 switch (event->button.button) {
576 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
578 GDK_POINTER_MOTION_MASK |
579 GDK_BUTTON_RELEASE_MASK |
580 GDK_BUTTON_PRESS_MASK,
581 NULL, NULL, event->button.time);
582 gnome_canvas_window_to_world (canvas,
584 event->button.y, &x, &y);
585 object = gl_label_line_new (view->label);
586 gl_label_object_set_position (GL_LABEL_OBJECT(object),
588 gl_label_object_set_size (GL_LABEL_OBJECT(object),
591 line_color = CREATE_LINE_COLOR;
592 gl_label_line_set_line_width (GL_LABEL_LINE(object),
594 gl_label_line_set_line_color (GL_LABEL_LINE(object),
596 view_line = gl_view_line_new (GL_LABEL_LINE(object),
606 case GDK_BUTTON_RELEASE:
607 switch (event->button.button) {
610 gdk_pointer_ungrab (event->button.time);
611 gnome_canvas_window_to_world (canvas,
613 event->button.y, &x, &y);
614 if ((x0 == x) && (y0 == y)) {
620 gl_label_object_set_size (GL_LABEL_OBJECT(object),
622 line_color = DEFAULT_LINE_COLOR;
623 gl_label_line_set_line_color (GL_LABEL_LINE(object),
625 gl_view_unselect_all (view);
626 gl_view_object_select (GL_VIEW_OBJECT(view_line));
627 gl_view_arrow_mode (view);
634 case GDK_MOTION_NOTIFY:
635 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
636 gnome_canvas_window_to_world (canvas,
638 event->button.y, &x, &y);
641 gl_label_object_set_size (GL_LABEL_OBJECT(object),