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 gl_debug (DEBUG_VIEW, "END");
260 /*****************************************************************************/
261 /* Create a properties dialog for a box object. */
262 /*****************************************************************************/
264 construct_properties_dialog (glViewBox *view_box)
266 GtkWidget *dialog, *wsection;
267 glLabelObject *object;
269 guint line_color, fill_color;
270 gdouble x, y, w, h, label_width, label_height;
271 GtkSizeGroup *label_size_group;
274 gl_debug (DEBUG_VIEW, "START");
276 /* retrieve object and query parameters */
277 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
278 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
279 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
280 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
281 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
282 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
283 gl_label_get_size (GL_LABEL(object->parent),
284 &label_width, &label_height);
286 /*-----------------------------------------------------------------*/
287 /* Build dialog with notebook. */
288 /*-----------------------------------------------------------------*/
289 window = gtk_widget_get_toplevel (
290 GTK_WIDGET(gl_view_object_get_view(GL_VIEW_OBJECT(view_box))));
291 dialog = gl_hig_dialog_new_with_buttons ( _("Edit box object properties"),
293 GTK_DIALOG_DESTROY_WITH_PARENT,
297 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
298 g_signal_connect (G_OBJECT (dialog), "response",
299 G_CALLBACK (response_cb), view_box);
301 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
304 /*---------------------------*/
305 /* Outline section */
306 /*---------------------------*/
307 wsection = gl_hig_category_new (_("Outline"));
308 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
309 view_box->private->line = gl_wdgt_line_new ();
310 gl_wdgt_line_set_label_size_group (GL_WDGT_LINE(view_box->private->line),
312 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
315 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
316 view_box->private->line);
317 g_signal_connect (G_OBJECT (view_box->private->line), "changed",
318 G_CALLBACK(line_changed_cb), view_box);
320 /*---------------------------*/
322 /*---------------------------*/
323 wsection = gl_hig_category_new (_("Fill"));
324 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
325 view_box->private->fill = gl_wdgt_fill_new ();
326 gl_wdgt_fill_set_label_size_group (GL_WDGT_FILL(view_box->private->fill),
328 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
330 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
331 view_box->private->fill);
332 g_signal_connect (G_OBJECT (view_box->private->fill), "changed",
333 G_CALLBACK(fill_changed_cb), view_box);
336 /*---------------------------*/
337 /* Position section */
338 /*---------------------------*/
339 wsection = gl_hig_category_new (_("Position"));
340 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
341 view_box->private->position = gl_wdgt_position_new ();
342 gl_wdgt_position_set_label_size_group (GL_WDGT_POSITION(view_box->private->position),
344 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_box->private->position),
345 x, y, label_width, label_height);
346 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
347 view_box->private->position);
348 g_signal_connect (G_OBJECT (view_box->private->position), "changed",
349 G_CALLBACK(position_changed_cb), view_box);
351 /*---------------------------*/
353 /*---------------------------*/
354 wsection = gl_hig_category_new (_("Size"));
355 gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), wsection);
356 view_box->private->size = gl_wdgt_size_new ();
357 gl_wdgt_size_set_label_size_group (GL_WDGT_SIZE(view_box->private->size),
359 gl_wdgt_size_set_params (GL_WDGT_SIZE (view_box->private->size),
360 w, h, TRUE, label_width, label_height);
361 gl_hig_category_add_widget (GL_HIG_CATEGORY(wsection),
362 view_box->private->size);
363 g_signal_connect (G_OBJECT (view_box->private->size), "changed",
364 G_CALLBACK(size_changed_cb), view_box);
367 /*----------------------------*/
368 /* Track object changes. */
369 /*----------------------------*/
370 g_signal_connect (G_OBJECT (object), "changed",
371 G_CALLBACK (update_dialog_cb), view_box);
372 g_signal_connect (G_OBJECT (object), "moved",
373 G_CALLBACK (update_dialog_from_move_cb), view_box);
375 gl_debug (DEBUG_VIEW, "END");
380 /*---------------------------------------------------------------------------*/
381 /* PRIVATE. "Response" callback. */
382 /*---------------------------------------------------------------------------*/
384 response_cb (GtkDialog *dialog,
388 gl_debug (DEBUG_VIEW, "START");
390 g_return_if_fail(dialog != NULL);
391 g_return_if_fail(GTK_IS_DIALOG(dialog));
394 case GTK_RESPONSE_CLOSE:
395 gtk_widget_hide (GTK_WIDGET(dialog));
397 case GTK_RESPONSE_DELETE_EVENT:
400 g_print ("response = %d", response);
401 g_assert_not_reached ();
404 gl_debug (DEBUG_VIEW, "END");
407 /*---------------------------------------------------------------------------*/
408 /* PRIVATE. line properties "changed" callback. */
409 /*---------------------------------------------------------------------------*/
411 line_changed_cb (glWdgtLine *line,
414 glLabelObject *object;
418 gl_debug (DEBUG_VIEW, "START");
420 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
422 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
426 g_signal_handlers_block_by_func (G_OBJECT(object),
427 update_dialog_cb, view_box);
428 gl_label_box_set_line_width(GL_LABEL_BOX(object), line_width);
429 gl_label_box_set_line_color(GL_LABEL_BOX(object), line_color);
430 g_signal_handlers_unblock_by_func (G_OBJECT(object),
431 update_dialog_cb, view_box);
433 gl_debug (DEBUG_VIEW, "END");
436 /*---------------------------------------------------------------------------*/
437 /* PRIVATE. fill properties "changed" callback. */
438 /*---------------------------------------------------------------------------*/
440 fill_changed_cb (glWdgtFill *fill,
443 glLabelObject *object;
446 gl_debug (DEBUG_VIEW, "START");
448 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
450 gl_wdgt_fill_get_params (GL_WDGT_FILL (fill),
453 g_signal_handlers_block_by_func (G_OBJECT(object),
454 update_dialog_cb, view_box);
455 gl_label_box_set_fill_color(GL_LABEL_BOX(object), fill_color);
456 g_signal_handlers_unblock_by_func (G_OBJECT(object),
457 update_dialog_cb, view_box);
459 gl_debug (DEBUG_VIEW, "END");
462 /*---------------------------------------------------------------------------*/
463 /* PRIVATE. position "changed" callback. */
464 /*---------------------------------------------------------------------------*/
466 position_changed_cb (glWdgtPosition *position,
469 glLabelObject *object;
472 gl_debug (DEBUG_VIEW, "START");
474 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
476 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
478 g_signal_handlers_block_by_func (G_OBJECT(object),
479 update_dialog_cb, view_box);
480 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
481 g_signal_handlers_unblock_by_func (G_OBJECT(object),
482 update_dialog_cb, view_box);
484 gl_debug (DEBUG_VIEW, "END");
487 /*---------------------------------------------------------------------------*/
488 /* PRIVATE. size "changed" callback. */
489 /*---------------------------------------------------------------------------*/
491 size_changed_cb (glWdgtSize *size,
494 glLabelObject *object;
496 gboolean keep_aspect_ratio_flag;
498 gl_debug (DEBUG_VIEW, "START");
500 gl_wdgt_size_get_size (GL_WDGT_SIZE (size),
501 &w, &h, &keep_aspect_ratio_flag);
503 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_box));
505 g_signal_handlers_block_by_func (G_OBJECT(object),
506 update_dialog_cb, view_box);
507 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
508 g_signal_handlers_unblock_by_func (G_OBJECT(object),
509 update_dialog_cb, view_box);
511 gl_debug (DEBUG_VIEW, "END");
514 /*---------------------------------------------------------------------------*/
515 /* PRIVATE. label object "changed" callback. */
516 /*---------------------------------------------------------------------------*/
518 update_dialog_cb (glLabelObject *object,
522 guint line_color, fill_color;
525 gl_debug (DEBUG_VIEW, "START");
527 /* Query properties of object. */
528 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
529 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
530 line_width = gl_label_box_get_line_width(GL_LABEL_BOX(object));
531 line_color = gl_label_box_get_line_color(GL_LABEL_BOX(object));
532 fill_color = gl_label_box_get_fill_color(GL_LABEL_BOX(object));
534 /* Block widget handlers to prevent recursion */
535 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->line),
536 line_changed_cb, view_box);
537 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->fill),
538 fill_changed_cb, view_box);
539 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->position),
540 position_changed_cb, view_box);
541 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->size),
542 size_changed_cb, view_box);
544 /* Update widgets in property dialog */
545 gl_wdgt_line_set_params (GL_WDGT_LINE (view_box->private->line),
548 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_box->private->fill),
550 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_box->private->position),
552 gl_wdgt_size_set_size (GL_WDGT_SIZE(view_box->private->size), w, h);
554 /* Unblock widget handlers */
555 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->line),
556 line_changed_cb, view_box);
557 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->fill),
558 fill_changed_cb, view_box);
559 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->position),
560 position_changed_cb, view_box);
561 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->size),
562 size_changed_cb, view_box);
565 gl_debug (DEBUG_VIEW, "END");
568 /*---------------------------------------------------------------------------*/
569 /* PRIVATE. label object "moved" callback. */
570 /*---------------------------------------------------------------------------*/
572 update_dialog_from_move_cb (glLabelObject *object,
579 gl_debug (DEBUG_VIEW, "START");
581 /* Query properties of object. */
582 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
584 /* Block widget handlers to prevent recursion */
585 g_signal_handlers_block_by_func (G_OBJECT(view_box->private->position),
586 position_changed_cb, view_box);
588 /* Update widgets in property dialog */
589 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_box->private->position),
592 /* Unblock widget handlers */
593 g_signal_handlers_unblock_by_func (G_OBJECT(view_box->private->position),
594 position_changed_cb, view_box);
596 gl_debug (DEBUG_VIEW, "END");
599 /*****************************************************************************/
600 /* Return apropos cursor for create object mode. */
601 /*****************************************************************************/
603 gl_view_box_get_create_cursor (void)
605 static GdkCursor *cursor = NULL;
606 GdkPixmap *pixmap_data, *pixmap_mask;
607 GdkColor fg = { 0, 0, 0, 0 };
608 GdkColor bg = { 0, 65535, 65535, 65535 };
610 gl_debug (DEBUG_VIEW, "START");
613 pixmap_data = gdk_bitmap_create_from_data (NULL,
617 pixmap_mask = gdk_bitmap_create_from_data (NULL,
618 cursor_box_mask_bits,
619 cursor_box_mask_width,
620 cursor_box_mask_height);
622 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
623 &bg, cursor_box_x_hot,
627 gl_debug (DEBUG_VIEW, "END");
632 /*****************************************************************************/
633 /* Canvas event handler for creating box objects. */
634 /*****************************************************************************/
636 gl_view_box_create_event_handler (GnomeCanvas *canvas,
640 static gdouble x0, y0;
641 static gboolean dragging = FALSE;
642 static glViewObject *view_box;
643 static GObject *object;
644 guint line_color, fill_color;
647 gl_debug (DEBUG_VIEW, "");
649 switch (event->type) {
651 case GDK_BUTTON_PRESS:
652 switch (event->button.button) {
655 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
657 GDK_POINTER_MOTION_MASK |
658 GDK_BUTTON_RELEASE_MASK |
659 GDK_BUTTON_PRESS_MASK,
660 NULL, NULL, event->button.time);
661 gnome_canvas_window_to_world (canvas,
663 event->button.y, &x, &y);
664 object = gl_label_box_new (view->label);
665 gl_label_object_set_position (GL_LABEL_OBJECT(object),
667 gl_label_object_set_size (GL_LABEL_OBJECT(object),
669 line_color = gl_color_set_opacity (gl_prefs->default_line_color, 0.5);
670 fill_color = gl_color_set_opacity (gl_prefs->default_fill_color, 0.5);
671 gl_label_box_set_line_width (GL_LABEL_BOX(object),
672 gl_prefs->default_line_width);
673 gl_label_box_set_line_color (GL_LABEL_BOX(object),
675 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
677 view_box = gl_view_box_new (GL_LABEL_BOX(object),
687 case GDK_BUTTON_RELEASE:
688 switch (event->button.button) {
691 gdk_pointer_ungrab (event->button.time);
692 gnome_canvas_window_to_world (canvas,
694 event->button.y, &x, &y);
695 if ((x0 == x) && (y0 == y)) {
699 gl_label_object_set_position (GL_LABEL_OBJECT(object),
700 MIN (x, x0), MIN (y, y0));
701 w = MAX (x, x0) - MIN (x, x0);
702 h = MAX (y, y0) - MIN (y, y0);
703 gl_label_object_set_size (GL_LABEL_OBJECT(object),
705 gl_label_box_set_line_color (GL_LABEL_BOX(object),
706 gl_prefs->default_line_color);
707 gl_label_box_set_fill_color (GL_LABEL_BOX(object),
708 gl_prefs->default_fill_color);
709 gl_view_unselect_all (view);
710 gl_view_object_select (GL_VIEW_OBJECT(view_box));
711 gl_view_arrow_mode (view);
718 case GDK_MOTION_NOTIFY:
719 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
720 gnome_canvas_window_to_world (canvas,
722 event->motion.y, &x, &y);
723 gl_label_object_set_position (GL_LABEL_OBJECT(object),
724 MIN (x, x0), MIN (y, y0));
725 w = MAX (x, x0) - MIN (x, x0);
726 h = MAX (y, y0) - MIN (y, y0);
727 gl_label_object_set_size (GL_LABEL_OBJECT(object),