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"
29 #include "wdgt-line.h"
30 #include "wdgt-fill.h"
31 #include "wdgt-size.h"
32 #include "wdgt-position.h"
36 #include "pixmaps/cursor_box.xbm"
37 #include "pixmaps/cursor_box_mask.xbm"
41 /*========================================================*/
42 /* Private macros and constants. */
43 /*========================================================*/
47 /*========================================================*/
49 /*========================================================*/
51 struct _glViewBoxPrivate {
52 GnomeCanvasItem *item;
54 /* Property dialog Page 0 widgets */
58 /* Property dialog Page 1 widgets */
63 /*========================================================*/
64 /* Private globals. */
65 /*========================================================*/
67 static glViewObjectClass *parent_class = NULL;
70 /*========================================================*/
71 /* Private function prototypes. */
72 /*========================================================*/
74 static void gl_view_box_class_init (glViewBoxClass *klass);
75 static void gl_view_box_instance_init (glViewBox *view_box);
76 static void gl_view_box_finalize (GObject *object);
78 static void update_view_box_cb (glLabelObject *object,
81 static GtkWidget *construct_properties_dialog (glViewBox *view_box);
83 static void response_cb (GtkDialog *dialog,
87 static void line_changed_cb (glWdgtLine *line,
90 static void fill_changed_cb (glWdgtFill *fill,
93 static void position_changed_cb (glWdgtPosition *position,
96 static void size_changed_cb (glWdgtSize *size,
99 static void update_dialog_cb (glLabelObject *object,
100 glViewBox *view_box);
102 static void update_dialog_from_move_cb (glLabelObject *object,
105 glViewBox *view_box);
108 /*****************************************************************************/
109 /* Boilerplate object stuff. */
110 /*****************************************************************************/
112 gl_view_box_get_type (void)
114 static GType type = 0;
118 sizeof (glViewBoxClass),
121 (GClassInitFunc) gl_view_box_class_init,
126 (GInstanceInitFunc) gl_view_box_instance_init,
129 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
130 "glViewBox", &info, 0);
137 gl_view_box_class_init (glViewBoxClass *klass)
139 GObjectClass *object_class = (GObjectClass *) klass;
141 gl_debug (DEBUG_VIEW, "START");
143 parent_class = g_type_class_peek_parent (klass);
145 object_class->finalize = gl_view_box_finalize;
147 gl_debug (DEBUG_VIEW, "END");
151 gl_view_box_instance_init (glViewBox *view_box)
153 gl_debug (DEBUG_VIEW, "START");
155 view_box->private = g_new0 (glViewBoxPrivate, 1);
157 gl_debug (DEBUG_VIEW, "END");
161 gl_view_box_finalize (GObject *object)
165 gl_debug (DEBUG_VIEW, "START");
167 g_return_if_fail (object && GL_IS_VIEW_BOX (object));
169 G_OBJECT_CLASS (parent_class)->finalize (object);
171 gl_debug (DEBUG_VIEW, "END");
174 /*****************************************************************************/
175 /* NEW box object view. */
176 /*****************************************************************************/
178 gl_view_box_new (glLabelBox *object,
183 guint line_color, fill_color;
187 gl_debug (DEBUG_VIEW, "START");
188 g_return_if_fail (object && GL_IS_LABEL_BOX (object));
189 g_return_if_fail (view && GL_IS_VIEW (view));
191 view_box = g_object_new (gl_view_box_get_type(), NULL);
193 gl_view_object_set_view (GL_VIEW_OBJECT(view_box), view);
194 gl_view_object_set_object (GL_VIEW_OBJECT(view_box),
195 GL_LABEL_OBJECT(object),
196 GL_VIEW_HIGHLIGHT_BOX_RESIZABLE);
198 /* Query properties of object. */
199 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
200 line_width = gl_label_box_get_line_width(object);
201 line_color = gl_label_box_get_line_color(object);
202 fill_color = gl_label_box_get_fill_color(object);
204 /* Create analogous canvas item. */
205 view_box->private->item =
206 gl_view_object_item_new (GL_VIEW_OBJECT(view_box),
207 gnome_canvas_rect_get_type (),
212 "width_units", line_width,
213 "outline_color_rgba", line_color,
214 "fill_color_rgba", fill_color,
217 g_signal_connect (G_OBJECT (object), "changed",
218 G_CALLBACK (update_view_box_cb), view_box);
220 /* Create a dialog for controlling/viewing object properties. */
221 gl_view_object_set_dlg_constructor (GL_VIEW_OBJECT(view_box),
222 GL_VIEW_OBJECT_DLG_CONSTRUCTOR(construct_properties_dialog));
224 gl_debug (DEBUG_VIEW, "END");
226 return GL_VIEW_OBJECT (view_box);
229 /*---------------------------------------------------------------------------*/
230 /* PRIVATE. label object "changed" callback. */
231 /*---------------------------------------------------------------------------*/
233 update_view_box_cb (glLabelObject *object,
237 guint line_color, fill_color;
240 gl_debug (DEBUG_VIEW, "START");
242 /* Query properties of object. */
243 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
244 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
245 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
246 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
248 /* Adjust appearance of analogous canvas item. */
249 gnome_canvas_item_set (view_box->private->item,
252 "width_units", line_width,
253 "outline_color_rgba", line_color,
254 "fill_color_rgba", fill_color,
257 /* Adjust highlight */
258 gl_view_object_update_highlight (GL_VIEW_OBJECT(view_box));
260 gl_debug (DEBUG_VIEW, "END");
263 /*****************************************************************************/
264 /* Create a properties dialog for a box object. */
265 /*****************************************************************************/
267 construct_properties_dialog (glViewBox *view_box)
269 GtkWidget *dialog, *wsection;
270 glLabelObject *object;
272 guint line_color, fill_color;
273 gdouble x, y, w, h, label_width, label_height;
274 GtkSizeGroup *label_size_group;
277 gl_debug (DEBUG_VIEW, "START");
279 /* retrieve object and query parameters */
280 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
281 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
282 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
283 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
284 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
285 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
286 gl_label_get_size (GL_LABEL(object->parent),
287 &label_width, &label_height);
289 /*-----------------------------------------------------------------*/
290 /* Build dialog with notebook. */
291 /*-----------------------------------------------------------------*/
292 window = gtk_widget_get_toplevel (
293 GTK_WIDGET(gl_view_object_get_view(GL_VIEW_OBJECT(view_box))));
294 dialog = gl_hig_dialog_new_with_buttons ( _("Edit box object properties"),
296 GTK_DIALOG_DESTROY_WITH_PARENT,
300 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
301 g_signal_connect (G_OBJECT (dialog), "response",
302 G_CALLBACK (response_cb), view_box);
304 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
307 /*---------------------------*/
308 /* Outline section */
309 /*---------------------------*/
310 wsection = gl_hig_category_new (_("Outline"));
311 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
312 view_box->private->line = gl_wdgt_line_new ();
313 gl_wdgt_line_set_label_size_group (GL_WDGT_LINE(view_box->private->line),
315 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
318 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
319 view_box->private->line);
320 g_signal_connect (G_OBJECT (view_box->private->line), "changed",
321 G_CALLBACK(line_changed_cb), view_box);
323 /*---------------------------*/
325 /*---------------------------*/
326 wsection = gl_hig_category_new (_("Fill"));
327 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
328 view_box->private->fill = gl_wdgt_fill_new ();
329 gl_wdgt_fill_set_label_size_group (GL_WDGT_FILL(view_box->private->fill),
331 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
333 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
334 view_box->private->fill);
335 g_signal_connect (G_OBJECT (view_box->private->fill), "changed",
336 G_CALLBACK(fill_changed_cb), view_box);
339 /*---------------------------*/
340 /* Position section */
341 /*---------------------------*/
342 wsection = gl_hig_category_new (_("Position"));
343 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
344 view_box->private->position = gl_wdgt_position_new ();
345 gl_wdgt_position_set_label_size_group (GL_WDGT_POSITION(view_box->private->position),
347 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_box->private->position),
348 x, y, label_width, label_height);
349 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
350 view_box->private->position);
351 g_signal_connect (G_OBJECT (view_box->private->position), "changed",
352 G_CALLBACK(position_changed_cb), view_box);
354 /*---------------------------*/
356 /*---------------------------*/
357 wsection = gl_hig_category_new (_("Size"));
358 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
359 view_box->private->size = gl_wdgt_size_new ();
360 gl_wdgt_size_set_label_size_group (GL_WDGT_SIZE(view_box->private->size),
362 gl_wdgt_size_set_params (GL_WDGT_SIZE (view_box->private->size),
363 w, h, TRUE, label_width, label_height);
364 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
365 view_box->private->size);
366 g_signal_connect (G_OBJECT (view_box->private->size), "changed",
367 G_CALLBACK(size_changed_cb), view_box);
370 /*----------------------------*/
371 /* Track object changes. */
372 /*----------------------------*/
373 g_signal_connect (G_OBJECT (object), "changed",
374 G_CALLBACK (update_dialog_cb), view_box);
375 g_signal_connect (G_OBJECT (object), "moved",
376 G_CALLBACK (update_dialog_from_move_cb), view_box);
378 gl_debug (DEBUG_VIEW, "END");
383 /*---------------------------------------------------------------------------*/
384 /* PRIVATE. "Response" callback. */
385 /*---------------------------------------------------------------------------*/
387 response_cb (GtkDialog *dialog,
391 gl_debug (DEBUG_VIEW, "START");
393 g_return_if_fail(dialog != NULL);
394 g_return_if_fail(GTK_IS_DIALOG(dialog));
397 case GTK_RESPONSE_CLOSE:
398 gtk_widget_hide (GTK_WIDGET(dialog));
400 case GTK_RESPONSE_DELETE_EVENT:
403 g_print ("response = %d", response);
404 g_assert_not_reached ();
407 gl_debug (DEBUG_VIEW, "END");
410 /*---------------------------------------------------------------------------*/
411 /* PRIVATE. line properties "changed" callback. */
412 /*---------------------------------------------------------------------------*/
414 line_changed_cb (glWdgtLine *line,
417 glLabelObject *object;
421 gl_debug (DEBUG_VIEW, "START");
423 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
425 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
429 g_signal_handlers_block_by_func (G_OBJECT(object),
430 update_dialog_cb, view_box);
431 gl_label_box_set_line_width(GL_LABEL_BOX(object), line_width);
432 gl_label_box_set_line_color(GL_LABEL_BOX(object), line_color);
433 g_signal_handlers_unblock_by_func (G_OBJECT(object),
434 update_dialog_cb, view_box);
436 gl_debug (DEBUG_VIEW, "END");
439 /*---------------------------------------------------------------------------*/
440 /* PRIVATE. fill properties "changed" callback. */
441 /*---------------------------------------------------------------------------*/
443 fill_changed_cb (glWdgtFill *fill,
446 glLabelObject *object;
449 gl_debug (DEBUG_VIEW, "START");
451 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
453 gl_wdgt_fill_get_params (GL_WDGT_FILL (fill),
456 g_signal_handlers_block_by_func (G_OBJECT(object),
457 update_dialog_cb, view_box);
458 gl_label_box_set_fill_color(GL_LABEL_BOX(object), fill_color);
459 g_signal_handlers_unblock_by_func (G_OBJECT(object),
460 update_dialog_cb, view_box);
462 gl_debug (DEBUG_VIEW, "END");
465 /*---------------------------------------------------------------------------*/
466 /* PRIVATE. position "changed" callback. */
467 /*---------------------------------------------------------------------------*/
469 position_changed_cb (glWdgtPosition *position,
472 glLabelObject *object;
475 gl_debug (DEBUG_VIEW, "START");
477 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
479 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
481 g_signal_handlers_block_by_func (G_OBJECT(object),
482 update_dialog_cb, view_box);
483 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
484 g_signal_handlers_unblock_by_func (G_OBJECT(object),
485 update_dialog_cb, view_box);
487 gl_debug (DEBUG_VIEW, "END");
490 /*---------------------------------------------------------------------------*/
491 /* PRIVATE. size "changed" callback. */
492 /*---------------------------------------------------------------------------*/
494 size_changed_cb (glWdgtSize *size,
497 glLabelObject *object;
499 gboolean keep_aspect_ratio_flag;
501 gl_debug (DEBUG_VIEW, "START");
503 gl_wdgt_size_get_size (GL_WDGT_SIZE (size),
504 &w, &h, &keep_aspect_ratio_flag);
506 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
508 g_signal_handlers_block_by_func (G_OBJECT(object),
509 update_dialog_cb, view_box);
510 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
511 g_signal_handlers_unblock_by_func (G_OBJECT(object),
512 update_dialog_cb, view_box);
514 gl_debug (DEBUG_VIEW, "END");
517 /*---------------------------------------------------------------------------*/
518 /* PRIVATE. label object "changed" callback. */
519 /*---------------------------------------------------------------------------*/
521 update_dialog_cb (glLabelObject *object,
525 guint line_color, fill_color;
528 gl_debug (DEBUG_VIEW, "START");
530 /* Query properties of object. */
531 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
532 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
533 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
534 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
535 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
537 /* Block widget handlers to prevent recursion */
538 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->line),
539 line_changed_cb, view_box);
540 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->fill),
541 fill_changed_cb, view_box);
542 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->position),
543 position_changed_cb, view_box);
544 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->size),
545 size_changed_cb, view_box);
547 /* Update widgets in property dialog */
548 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
551 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
553 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_box->private->position),
555 gl_wdgt_size_set_size (GL_WDGT_SIZE(view_box->private->size), w, h);
557 /* Unblock widget handlers */
558 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->line),
559 line_changed_cb, view_box);
560 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->fill),
561 fill_changed_cb, view_box);
562 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->position),
563 position_changed_cb, view_box);
564 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->size),
565 size_changed_cb, view_box);
568 gl_debug (DEBUG_VIEW, "END");
571 /*---------------------------------------------------------------------------*/
572 /* PRIVATE. label object "moved" callback. */
573 /*---------------------------------------------------------------------------*/
575 update_dialog_from_move_cb (glLabelObject *object,
582 gl_debug (DEBUG_VIEW, "START");
584 /* Query properties of object. */
585 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
587 /* Block widget handlers to prevent recursion */
588 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->position),
589 position_changed_cb, view_box);
591 /* Update widgets in property dialog */
592 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_box->private->position),
595 /* Unblock widget handlers */
596 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->position),
597 position_changed_cb, view_box);
599 gl_debug (DEBUG_VIEW, "END");
602 /*****************************************************************************/
603 /* Return apropos cursor for create object mode. */
604 /*****************************************************************************/
606 gl_view_box_get_create_cursor (void)
608 static GdkCursor *cursor = NULL;
609 GdkPixmap *pixmap_data, *pixmap_mask;
610 GdkColor fg = { 0, 0, 0, 0 };
611 GdkColor bg = { 0, 65535, 65535, 65535 };
613 gl_debug (DEBUG_VIEW, "START");
616 pixmap_data = gdk_bitmap_create_from_data (NULL,
620 pixmap_mask = gdk_bitmap_create_from_data (NULL,
621 cursor_box_mask_bits,
622 cursor_box_mask_width,
623 cursor_box_mask_height);
625 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
626 &bg, cursor_box_x_hot,
630 gl_debug (DEBUG_VIEW, "END");
635 /*****************************************************************************/
636 /* Canvas event handler for creating box objects. */
637 /*****************************************************************************/
639 gl_view_box_create_event_handler (GnomeCanvas *canvas,
643 static gdouble x0, y0;
644 static gboolean dragging = FALSE;
645 static glViewObject *view_box;
646 static GObject *object;
647 guint line_color, fill_color;
650 gl_debug (DEBUG_VIEW, "");
652 switch (event->type) {
654 case GDK_BUTTON_PRESS:
655 switch (event->button.button) {
658 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
660 GDK_POINTER_MOTION_MASK |
661 GDK_BUTTON_RELEASE_MASK |
662 GDK_BUTTON_PRESS_MASK,
663 NULL, NULL, event->button.time);
664 gnome_canvas_window_to_world (canvas,
666 event->button.y, &x, &y);
667 object = gl_label_box_new (view->label);
668 gl_label_object_set_position (GL_LABEL_OBJECT(object),
670 gl_label_object_set_size (GL_LABEL_OBJECT(object),
672 line_color = gl_color_set_opacity (gl_prefs->default_line_color, 0.5);
673 fill_color = gl_color_set_opacity (gl_prefs->default_fill_color, 0.5);
674 gl_label_box_set_line_width (GL_LABEL_BOX(object),
675 gl_prefs->default_line_width);
676 gl_label_box_set_line_color (GL_LABEL_BOX(object),
678 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
680 view_box = gl_view_box_new (GL_LABEL_BOX(object),
690 case GDK_BUTTON_RELEASE:
691 switch (event->button.button) {
694 gdk_pointer_ungrab (event->button.time);
695 gnome_canvas_window_to_world (canvas,
697 event->button.y, &x, &y);
698 if ((x0 == x) && (y0 == y)) {
702 gl_label_object_set_position (GL_LABEL_OBJECT(object),
703 MIN (x, x0), MIN (y, y0));
704 w = MAX (x, x0) - MIN (x, x0);
705 h = MAX (y, y0) - MIN (y, y0);
706 gl_label_object_set_size (GL_LABEL_OBJECT(object),
708 gl_label_box_set_line_color (GL_LABEL_BOX(object),
709 gl_prefs->default_line_color);
710 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
711 gl_prefs->default_fill_color);
712 gl_view_unselect_all (view);
713 gl_view_object_select (GL_VIEW_OBJECT(view_box));
714 gl_view_arrow_mode (view);
721 case GDK_MOTION_NOTIFY:
722 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
723 gnome_canvas_window_to_world (canvas,
725 event->motion.y, &x, &y);
726 gl_label_object_set_position (GL_LABEL_OBJECT(object),
727 MIN (x, x0), MIN (y, y0));
728 w = MAX (x, x0) - MIN (x, x0);
729 h = MAX (y, y0) - MIN (y, y0);
730 gl_label_object_set_size (GL_LABEL_OBJECT(object),