2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * view_box.c: GLabels label box 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
27 #include "view-highlight.h"
30 #include "wdgt-line.h"
31 #include "wdgt-fill.h"
32 #include "wdgt-size.h"
33 #include "wdgt-position.h"
35 #include "pixmaps/cursor_box.xbm"
36 #include "pixmaps/cursor_box_mask.xbm"
40 /*========================================================*/
41 /* Private macros and constants. */
42 /*========================================================*/
43 #define CREATE_LINE_COLOR GNOME_CANVAS_COLOR_A (0, 0, 0, 192)
44 #define CREATE_FILL_COLOR GNOME_CANVAS_COLOR_A (0, 255, 0, 192)
46 #define DEFAULT_LINE_COLOR GNOME_CANVAS_COLOR_A (0, 0, 0, 255)
47 #define DEFAULT_FILL_COLOR GNOME_CANVAS_COLOR_A (0, 255, 0, 255)
51 /*========================================================*/
53 /*========================================================*/
55 struct _glViewBoxPrivate {
56 GnomeCanvasItem *item;
58 /* Property dialog Page 0 widgets */
62 /* Property dialog Page 1 widgets */
67 /*========================================================*/
68 /* Private globals. */
69 /*========================================================*/
71 static glViewObjectClass *parent_class = NULL;
74 /*========================================================*/
75 /* Private function prototypes. */
76 /*========================================================*/
78 static void gl_view_box_class_init (glViewBoxClass *klass);
79 static void gl_view_box_instance_init (glViewBox *view_box);
80 static void gl_view_box_finalize (GObject *object);
82 static void update_view_box_cb (glLabelObject *object,
85 static GtkWidget *construct_properties_dialog (glViewBox *view_box);
87 static void response_cb (GtkDialog *dialog,
91 static void line_changed_cb (glWdgtLine *line,
94 static void fill_changed_cb (glWdgtFill *fill,
97 static void position_changed_cb (glWdgtPosition *position,
100 static void size_changed_cb (glWdgtSize *size,
101 glViewBox *view_box);
103 static void update_dialog_cb (glLabelObject *object,
104 glViewBox *view_box);
107 /*****************************************************************************/
108 /* Boilerplate object stuff. */
109 /*****************************************************************************/
111 gl_view_box_get_type (void)
113 static GType type = 0;
117 sizeof (glViewBoxClass),
120 (GClassInitFunc) gl_view_box_class_init,
125 (GInstanceInitFunc) gl_view_box_instance_init,
128 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
129 "glViewBox", &info, 0);
136 gl_view_box_class_init (glViewBoxClass *klass)
138 GObjectClass *object_class = (GObjectClass *) klass;
140 gl_debug (DEBUG_VIEW, "START");
142 parent_class = g_type_class_peek_parent (klass);
144 object_class->finalize = gl_view_box_finalize;
146 gl_debug (DEBUG_VIEW, "END");
150 gl_view_box_instance_init (glViewBox *view_box)
152 gl_debug (DEBUG_VIEW, "START");
154 view_box->private = g_new0 (glViewBoxPrivate, 1);
156 gl_debug (DEBUG_VIEW, "END");
160 gl_view_box_finalize (GObject *object)
164 gl_debug (DEBUG_VIEW, "START");
166 g_return_if_fail (object && GL_IS_VIEW_BOX (object));
168 G_OBJECT_CLASS (parent_class)->finalize (object);
170 gl_debug (DEBUG_VIEW, "END");
173 /*****************************************************************************/
174 /* NEW box object view. */
175 /*****************************************************************************/
177 gl_view_box_new (glLabelBox *object,
181 GnomeCanvasItem *group;
183 guint line_color, fill_color;
188 gl_debug (DEBUG_VIEW, "START");
189 g_return_if_fail (object && GL_IS_LABEL_BOX (object));
190 g_return_if_fail (view && GL_IS_VIEW (view));
192 view_box = g_object_new (gl_view_box_get_type(), NULL);
194 gl_view_object_set_view (GL_VIEW_OBJECT(view_box), view);
195 gl_view_object_set_object (GL_VIEW_OBJECT(view_box),
196 GL_LABEL_OBJECT(object),
197 GL_VIEW_HIGHLIGHT_BOX_RESIZABLE);
199 /* Query properties of object. */
200 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
201 line_width = gl_label_box_get_line_width(object);
202 line_color = gl_label_box_get_line_color(object);
203 fill_color = gl_label_box_get_fill_color(object);
205 /* Create analogous canvas item. */
206 group = gl_view_object_get_group (GL_VIEW_OBJECT(view_box));
207 view_box->private->item =
208 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
209 gnome_canvas_rect_get_type (),
214 "width_units", line_width,
215 "outline_color_rgba", line_color,
216 "fill_color_rgba", fill_color,
219 g_signal_connect (G_OBJECT (object), "changed",
220 G_CALLBACK (update_view_box_cb), view_box);
222 /* Create a dialog for controlling/viewing object properties. */
223 dialog = construct_properties_dialog (view_box);
224 gl_view_object_set_dialog (GL_VIEW_OBJECT(view_box), dialog);
226 gl_debug (DEBUG_VIEW, "END");
228 return GL_VIEW_OBJECT (view_box);
231 /*---------------------------------------------------------------------------*/
232 /* PRIVATE. label object "changed" callback. */
233 /*---------------------------------------------------------------------------*/
235 update_view_box_cb (glLabelObject *object,
239 guint line_color, fill_color;
242 gl_debug (DEBUG_VIEW, "START");
244 /* Query properties of object. */
245 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
246 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
247 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
248 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
250 /* Adjust appearance of analogous canvas item. */
251 gnome_canvas_item_set (view_box->private->item,
254 "width_units", line_width,
255 "outline_color_rgba", line_color,
256 "fill_color_rgba", fill_color,
259 /* Adjust highlight */
260 gl_view_object_update_highlight (GL_VIEW_OBJECT(view_box));
262 gl_debug (DEBUG_VIEW, "END");
265 /*****************************************************************************/
266 /* Create a properties dialog for a box object. */
267 /*****************************************************************************/
269 construct_properties_dialog (glViewBox *view_box)
271 GtkWidget *dialog, *notebook, *wvbox;
272 BonoboWindow *win = glabels_get_active_window ();
273 glLabelObject *object;
275 guint line_color, fill_color;
276 gdouble x, y, w, h, label_width, label_height;
278 gl_debug (DEBUG_VIEW, "START");
280 /* retrieve object and query parameters */
281 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
282 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
283 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
284 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
285 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
286 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
287 gl_label_get_size (GL_LABEL(object->parent),
288 &label_width, &label_height);
290 /*-----------------------------------------------------------------*/
291 /* Build dialog with notebook. */
292 /*-----------------------------------------------------------------*/
293 dialog = gtk_dialog_new_with_buttons ( _("Edit box object properties"),
295 GTK_DIALOG_DESTROY_WITH_PARENT,
299 g_signal_connect (G_OBJECT (dialog), "response",
300 G_CALLBACK (response_cb), view_box);
302 notebook = gtk_notebook_new ();
303 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
304 notebook, TRUE, TRUE, 0);
306 /*---------------------------*/
307 /* Appearance Notebook Tab */
308 /*---------------------------*/
309 wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
310 gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
311 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), wvbox,
312 gtk_label_new (_("Appearance")));
314 /* ------ Line box ------ */
315 view_box->private->line = gl_wdgt_line_new (_("Outline"));
316 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
319 gtk_box_pack_start (GTK_BOX (wvbox), view_box->private->line,
321 g_signal_connect (G_OBJECT (view_box->private->line), "changed",
322 G_CALLBACK(line_changed_cb), view_box);
324 /* ------ Fill box ------ */
325 view_box->private->fill = gl_wdgt_fill_new (_("Fill"));
326 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
328 gtk_box_pack_start (GTK_BOX (wvbox), view_box->private->fill,
330 g_signal_connect (G_OBJECT (view_box->private->fill), "changed",
331 G_CALLBACK(fill_changed_cb), view_box);
334 /*----------------------------*/
335 /* Position/Size Notebook Tab */
336 /*----------------------------*/
337 wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
338 gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
339 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), wvbox,
340 gtk_label_new (_("Position/Size")));
342 /* ------ Position Frame ------ */
343 view_box->private->position = gl_wdgt_position_new (_("Position"));
344 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_box->private->position),
346 label_width, label_height);
347 gtk_box_pack_start (GTK_BOX (wvbox), view_box->private->position,
349 g_signal_connect (G_OBJECT (view_box->private->position), "changed",
350 G_CALLBACK(position_changed_cb), view_box);
353 /* ------ Size Frame ------ */
354 view_box->private->size = gl_wdgt_size_new (_("Size"));
355 gl_wdgt_size_set_params (GL_WDGT_SIZE (view_box->private->size),
358 label_width, label_height);
359 gtk_box_pack_start (GTK_BOX (wvbox), view_box->private->size,
361 g_signal_connect (G_OBJECT (view_box->private->size), "changed",
362 G_CALLBACK(size_changed_cb), view_box);
365 /*----------------------------*/
366 /* Track object changes. */
367 /*----------------------------*/
368 g_signal_connect (G_OBJECT (object), "changed",
369 G_CALLBACK (update_dialog_cb), view_box);
371 gl_debug (DEBUG_VIEW, "END");
376 /*---------------------------------------------------------------------------*/
377 /* PRIVATE. "Response" callback. */
378 /*---------------------------------------------------------------------------*/
380 response_cb (GtkDialog *dialog,
384 gl_debug (DEBUG_VIEW, "START");
386 g_return_if_fail(dialog != NULL);
387 g_return_if_fail(GTK_IS_DIALOG(dialog));
390 case GTK_RESPONSE_CLOSE:
391 gtk_widget_hide (GTK_WIDGET(dialog));
394 g_assert_not_reached();
397 gl_debug (DEBUG_VIEW, "END");
400 /*---------------------------------------------------------------------------*/
401 /* PRIVATE. line properties "changed" callback. */
402 /*---------------------------------------------------------------------------*/
404 line_changed_cb (glWdgtLine *line,
407 glLabelObject *object;
411 gl_debug (DEBUG_VIEW, "START");
413 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
415 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
419 g_signal_handlers_block_by_func (G_OBJECT(object),
420 update_dialog_cb, view_box);
421 gl_label_box_set_line_width(GL_LABEL_BOX(object), line_width);
422 gl_label_box_set_line_color(GL_LABEL_BOX(object), line_color);
423 g_signal_handlers_unblock_by_func (G_OBJECT(object),
424 update_dialog_cb, view_box);
426 gl_debug (DEBUG_VIEW, "END");
429 /*---------------------------------------------------------------------------*/
430 /* PRIVATE. fill properties "changed" callback. */
431 /*---------------------------------------------------------------------------*/
433 fill_changed_cb (glWdgtFill *fill,
436 glLabelObject *object;
439 gl_debug (DEBUG_VIEW, "START");
441 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
443 gl_wdgt_fill_get_params (GL_WDGT_FILL (fill),
446 g_signal_handlers_block_by_func (G_OBJECT(object),
447 update_dialog_cb, view_box);
448 gl_label_box_set_fill_color(GL_LABEL_BOX(object), fill_color);
449 g_signal_handlers_unblock_by_func (G_OBJECT(object),
450 update_dialog_cb, view_box);
452 gl_debug (DEBUG_VIEW, "END");
455 /*---------------------------------------------------------------------------*/
456 /* PRIVATE. position "changed" callback. */
457 /*---------------------------------------------------------------------------*/
459 position_changed_cb (glWdgtPosition *position,
462 glLabelObject *object;
465 gl_debug (DEBUG_VIEW, "START");
467 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
469 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
471 g_signal_handlers_block_by_func (G_OBJECT(object),
472 update_dialog_cb, view_box);
473 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
474 g_signal_handlers_unblock_by_func (G_OBJECT(object),
475 update_dialog_cb, view_box);
477 gl_debug (DEBUG_VIEW, "END");
480 /*---------------------------------------------------------------------------*/
481 /* PRIVATE. size "changed" callback. */
482 /*---------------------------------------------------------------------------*/
484 size_changed_cb (glWdgtSize *size,
487 glLabelObject *object;
489 gboolean keep_aspect_ratio_flag;
491 gl_debug (DEBUG_VIEW, "START");
493 gl_wdgt_size_get_size (GL_WDGT_SIZE (size),
494 &w, &h, &keep_aspect_ratio_flag);
496 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
498 g_signal_handlers_block_by_func (G_OBJECT(object),
499 update_dialog_cb, view_box);
500 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
501 g_signal_handlers_unblock_by_func (G_OBJECT(object),
502 update_dialog_cb, view_box);
504 gl_debug (DEBUG_VIEW, "END");
507 /*---------------------------------------------------------------------------*/
508 /* PRIVATE. label object "changed" callback. */
509 /*---------------------------------------------------------------------------*/
511 update_dialog_cb (glLabelObject *object,
515 guint line_color, fill_color;
518 gl_debug (DEBUG_VIEW, "START");
520 /* Query properties of object. */
521 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
522 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
523 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
524 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
525 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
527 /* Block widget handlers to prevent recursion */
528 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->line),
529 line_changed_cb, view_box);
530 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->fill),
531 fill_changed_cb, view_box);
532 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->position),
533 position_changed_cb, view_box);
534 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->size),
535 size_changed_cb, view_box);
537 /* Update widgets in property dialog */
538 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
541 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
543 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_box->private->position),
545 gl_wdgt_size_set_size (GL_WDGT_SIZE(view_box->private->size), w, h);
547 /* Unblock widget handlers */
548 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->line),
549 line_changed_cb, view_box);
550 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->fill),
551 fill_changed_cb, view_box);
552 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->position),
553 position_changed_cb, view_box);
554 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->size),
555 size_changed_cb, view_box);
558 gl_debug (DEBUG_VIEW, "END");
561 /*****************************************************************************/
562 /* Return apropos cursor for create object mode. */
563 /*****************************************************************************/
565 gl_view_box_get_create_cursor (void)
567 static GdkCursor *cursor = NULL;
568 GdkPixmap *pixmap_data, *pixmap_mask;
569 GdkColor fg = { 0, 0, 0, 0 };
570 GdkColor bg = { 0, 65535, 65535, 65535 };
572 gl_debug (DEBUG_VIEW, "START");
575 pixmap_data = gdk_bitmap_create_from_data (NULL,
579 pixmap_mask = gdk_bitmap_create_from_data (NULL,
580 cursor_box_mask_bits,
581 cursor_box_mask_width,
582 cursor_box_mask_height);
584 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
585 &bg, cursor_box_x_hot,
589 gl_debug (DEBUG_VIEW, "END");
594 /*****************************************************************************/
595 /* Canvas event handler for creating box objects. */
596 /*****************************************************************************/
598 gl_view_box_create_event_handler (GnomeCanvas *canvas,
602 static gdouble x0, y0;
603 static gboolean dragging = FALSE;
604 static glViewObject *view_box;
605 static GObject *object;
607 guint line_color, fill_color;
610 gl_debug (DEBUG_VIEW, "");
612 switch (event->type) {
614 case GDK_BUTTON_PRESS:
615 switch (event->button.button) {
618 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
620 GDK_POINTER_MOTION_MASK |
621 GDK_BUTTON_RELEASE_MASK |
622 GDK_BUTTON_PRESS_MASK,
623 NULL, NULL, event->button.time);
624 gnome_canvas_window_to_world (canvas,
626 event->button.y, &x, &y);
627 gl_debug (DEBUG_VIEW, "BUTTON_PRESS (%f, %f) -> (%f, %f)", event->button.x, event->button.y, x, y);
628 object = gl_label_box_new (view->label);
629 gl_label_object_set_position (GL_LABEL_OBJECT(object),
631 gl_label_object_set_size (GL_LABEL_OBJECT(object),
634 line_color = CREATE_LINE_COLOR;
635 fill_color = CREATE_FILL_COLOR;
636 gl_label_box_set_line_width (GL_LABEL_BOX(object),
638 gl_label_box_set_line_color (GL_LABEL_BOX(object),
640 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
642 view_box = gl_view_box_new (GL_LABEL_BOX(object),
652 case GDK_BUTTON_RELEASE:
653 switch (event->button.button) {
656 gdk_pointer_ungrab (event->button.time);
657 gnome_canvas_window_to_world (canvas,
659 event->button.y, &x, &y);
660 gl_debug (DEBUG_VIEW, "BUTTON_RELEASE (%f, %f) -> (%f, %f)", event->button.x, event->button.y, x, y);
661 if ((x0 == x) && (y0 == y)) {
665 gl_label_object_set_position (GL_LABEL_OBJECT(object),
666 MIN (x, x0), MIN (y, y0));
667 w = MAX (x, x0) - MIN (x, x0);
668 h = MAX (y, y0) - MIN (y, y0);
669 gl_label_object_set_size (GL_LABEL_OBJECT(object),
671 line_color = DEFAULT_LINE_COLOR;
672 fill_color = DEFAULT_FILL_COLOR;
673 gl_label_box_set_line_color (GL_LABEL_BOX(object),
675 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
677 gl_view_unselect_all (view);
678 gl_view_object_select (GL_VIEW_OBJECT(view_box));
679 gl_view_arrow_mode (view);
686 case GDK_MOTION_NOTIFY:
687 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
688 gnome_canvas_window_to_world (canvas,
690 event->button.y, &x, &y);
691 gl_label_object_set_position (GL_LABEL_OBJECT(object),
692 MIN (x, x0), MIN (y, y0));
693 gl_debug (DEBUG_VIEW, "BUTTON_MOTION (%f, %f) -> (%f, %f)", event->button.x, event->button.y, x, y);
694 w = MAX (x, x0) - MIN (x, x0);
695 h = MAX (y, y0) - MIN (y, y0);
696 gl_label_object_set_size (GL_LABEL_OBJECT(object),