2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * view_ellipse.c: GLabels label ellipse 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-ellipse.h"
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_ellipse.xbm"
36 #include "pixmaps/cursor_ellipse_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 _glViewEllipsePrivate {
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_ellipse_class_init (glViewEllipseClass *klass);
79 static void gl_view_ellipse_instance_init (glViewEllipse *view_ellipse);
80 static void gl_view_ellipse_finalize (GObject *object);
82 static void update_view_ellipse_cb (glLabelObject *object,
83 glViewEllipse *view_ellipse);
85 static GtkWidget *construct_properties_dialog (glViewEllipse *view_ellipse);
87 static void response_cb (GtkDialog *dialog,
89 glViewEllipse *view_ellipse);
91 static void line_changed_cb (glWdgtLine *line,
92 glViewEllipse *view_ellipse);
94 static void fill_changed_cb (glWdgtFill *fill,
95 glViewEllipse *view_ellipse);
97 static void position_changed_cb (glWdgtPosition *position,
98 glViewEllipse *view_ellipse);
100 static void size_changed_cb (glWdgtSize *size,
101 glViewEllipse *view_ellipse);
103 static void update_dialog_cb (glLabelObject *object,
104 glViewEllipse *view_ellipse);
107 /*****************************************************************************/
108 /* Boilerplate object stuff. */
109 /*****************************************************************************/
111 gl_view_ellipse_get_type (void)
113 static GType type = 0;
117 sizeof (glViewEllipseClass),
120 (GClassInitFunc) gl_view_ellipse_class_init,
123 sizeof (glViewEllipse),
125 (GInstanceInitFunc) gl_view_ellipse_instance_init,
128 type = g_type_register_static (GL_TYPE_VIEW_OBJECT,
129 "glViewEllipse", &info, 0);
136 gl_view_ellipse_class_init (glViewEllipseClass *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_ellipse_finalize;
146 gl_debug (DEBUG_VIEW, "END");
150 gl_view_ellipse_instance_init (glViewEllipse *view_ellipse)
152 gl_debug (DEBUG_VIEW, "START");
154 view_ellipse->private = g_new0 (glViewEllipsePrivate, 1);
156 gl_debug (DEBUG_VIEW, "END");
160 gl_view_ellipse_finalize (GObject *object)
164 gl_debug (DEBUG_VIEW, "START");
166 g_return_if_fail (object && GL_IS_VIEW_ELLIPSE (object));
168 G_OBJECT_CLASS (parent_class)->finalize (object);
170 gl_debug (DEBUG_VIEW, "END");
173 /*****************************************************************************/
174 /* NEW ellipse object view. */
175 /*****************************************************************************/
177 gl_view_ellipse_new (glLabelEllipse *object,
180 glViewEllipse *view_ellipse;
181 GnomeCanvasItem *group;
183 guint line_color, fill_color;
188 gl_debug (DEBUG_VIEW, "START");
189 g_return_if_fail (object && GL_IS_LABEL_ELLIPSE (object));
190 g_return_if_fail (view && GL_IS_VIEW (view));
192 view_ellipse = g_object_new (gl_view_ellipse_get_type(), NULL);
194 gl_view_object_set_view (GL_VIEW_OBJECT(view_ellipse), view);
195 gl_view_object_set_object (GL_VIEW_OBJECT(view_ellipse),
196 GL_LABEL_OBJECT(object),
197 GL_VIEW_HIGHLIGHT_ELLIPSE_RESIZABLE);
199 /* Query properties of object. */
200 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
201 line_width = gl_label_ellipse_get_line_width(object);
202 line_color = gl_label_ellipse_get_line_color(object);
203 fill_color = gl_label_ellipse_get_fill_color(object);
205 /* Create analogous canvas item. */
206 group = gl_view_object_get_group (GL_VIEW_OBJECT(view_ellipse));
207 view_ellipse->private->item =
208 gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
209 gnome_canvas_ellipse_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_ellipse_cb), view_ellipse);
222 /* Create a dialog for controlling/viewing object properties. */
223 dialog = construct_properties_dialog (view_ellipse);
224 gl_view_object_set_dialog (GL_VIEW_OBJECT(view_ellipse), dialog);
226 gl_debug (DEBUG_VIEW, "END");
228 return GL_VIEW_OBJECT (view_ellipse);
231 /*---------------------------------------------------------------------------*/
232 /* PRIVATE. label object "changed" callback. */
233 /*---------------------------------------------------------------------------*/
235 update_view_ellipse_cb (glLabelObject *object,
236 glViewEllipse *view_ellipse)
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_ellipse_get_line_width(GL_LABEL_ELLIPSE(object));
247 line_color = gl_label_ellipse_get_line_color(GL_LABEL_ELLIPSE(object));
248 fill_color = gl_label_ellipse_get_fill_color(GL_LABEL_ELLIPSE(object));
250 /* Adjust appearance of analogous canvas item. */
251 gnome_canvas_item_set (view_ellipse->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_ellipse));
262 gl_debug (DEBUG_VIEW, "END");
265 /*****************************************************************************/
266 /* Create a properties dialog for a ellipse object. */
267 /*****************************************************************************/
269 construct_properties_dialog (glViewEllipse *view_ellipse)
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_ellipse));
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_ellipse_get_line_width(GL_LABEL_ELLIPSE(object));
285 line_color = gl_label_ellipse_get_line_color(GL_LABEL_ELLIPSE(object));
286 fill_color = gl_label_ellipse_get_fill_color(GL_LABEL_ELLIPSE(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 ellipse object properties"),
295 GTK_DIALOG_DESTROY_WITH_PARENT,
299 g_signal_connect (G_OBJECT (dialog), "response",
300 G_CALLBACK (response_cb), view_ellipse);
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 ellipse ------ */
315 view_ellipse->private->line = gl_wdgt_line_new (_("Outline"));
316 gl_wdgt_line_set_params (GL_WDGT_LINE (view_ellipse->private->line),
319 gtk_box_pack_start (GTK_BOX (wvbox), view_ellipse->private->line,
321 g_signal_connect (G_OBJECT (view_ellipse->private->line), "changed",
322 G_CALLBACK(line_changed_cb), view_ellipse);
324 /* ------ Fill ellipse ------ */
325 view_ellipse->private->fill = gl_wdgt_fill_new (_("Fill"));
326 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_ellipse->private->fill),
328 gtk_box_pack_start (GTK_BOX (wvbox), view_ellipse->private->fill,
330 g_signal_connect (G_OBJECT (view_ellipse->private->fill), "changed",
331 G_CALLBACK(fill_changed_cb), view_ellipse);
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_ellipse->private->position = gl_wdgt_position_new (_("Position"));
344 gl_wdgt_position_set_params (GL_WDGT_POSITION (view_ellipse->private->position),
346 label_width, label_height);
347 gtk_box_pack_start (GTK_BOX (wvbox),
348 view_ellipse->private->position,
350 g_signal_connect (G_OBJECT (view_ellipse->private->position),
352 G_CALLBACK(position_changed_cb), view_ellipse);
355 /* ------ Size Frame ------ */
356 view_ellipse->private->size = gl_wdgt_size_new (_("Size"));
357 gl_wdgt_size_set_params (GL_WDGT_SIZE (view_ellipse->private->size),
360 label_width, label_height);
361 gtk_box_pack_start (GTK_BOX (wvbox), view_ellipse->private->size,
363 g_signal_connect (G_OBJECT (view_ellipse->private->size), "changed",
364 G_CALLBACK(size_changed_cb), view_ellipse);
367 /*----------------------------*/
368 /* Track object changes. */
369 /*----------------------------*/
370 g_signal_connect (G_OBJECT (object), "changed",
371 G_CALLBACK (update_dialog_cb), view_ellipse);
373 gl_debug (DEBUG_VIEW, "END");
378 /*---------------------------------------------------------------------------*/
379 /* PRIVATE. "Response" callback. */
380 /*---------------------------------------------------------------------------*/
382 response_cb (GtkDialog *dialog,
384 glViewEllipse *view_ellipse)
386 gl_debug (DEBUG_VIEW, "START");
388 g_return_if_fail(dialog != NULL);
389 g_return_if_fail(GTK_IS_DIALOG(dialog));
392 case GTK_RESPONSE_CLOSE:
393 gtk_widget_hide (GTK_WIDGET(dialog));
396 g_assert_not_reached();
399 gl_debug (DEBUG_VIEW, "END");
402 /*---------------------------------------------------------------------------*/
403 /* PRIVATE. line properties "changed" callback. */
404 /*---------------------------------------------------------------------------*/
406 line_changed_cb (glWdgtLine *line,
407 glViewEllipse *view_ellipse)
409 glLabelObject *object;
413 gl_debug (DEBUG_VIEW, "START");
415 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_ellipse));
417 gl_wdgt_line_get_params (GL_WDGT_LINE (line),
421 g_signal_handlers_block_by_func (G_OBJECT(object),
422 update_dialog_cb, view_ellipse);
423 gl_label_ellipse_set_line_width(GL_LABEL_ELLIPSE(object), line_width);
424 gl_label_ellipse_set_line_color(GL_LABEL_ELLIPSE(object), line_color);
425 g_signal_handlers_unblock_by_func (G_OBJECT(object),
426 update_dialog_cb, view_ellipse);
428 gl_debug (DEBUG_VIEW, "END");
431 /*---------------------------------------------------------------------------*/
432 /* PRIVATE. fill properties "changed" callback. */
433 /*---------------------------------------------------------------------------*/
435 fill_changed_cb (glWdgtFill *fill,
436 glViewEllipse *view_ellipse)
438 glLabelObject *object;
441 gl_debug (DEBUG_VIEW, "START");
443 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_ellipse));
445 gl_wdgt_fill_get_params (GL_WDGT_FILL (fill),
448 g_signal_handlers_block_by_func (G_OBJECT(object),
449 update_dialog_cb, view_ellipse);
450 gl_label_ellipse_set_fill_color(GL_LABEL_ELLIPSE(object), fill_color);
451 g_signal_handlers_unblock_by_func (G_OBJECT(object),
452 update_dialog_cb, view_ellipse);
454 gl_debug (DEBUG_VIEW, "END");
457 /*---------------------------------------------------------------------------*/
458 /* PRIVATE. position "changed" callback. */
459 /*---------------------------------------------------------------------------*/
461 position_changed_cb (glWdgtPosition *position,
462 glViewEllipse *view_ellipse)
464 glLabelObject *object;
467 gl_debug (DEBUG_VIEW, "START");
469 gl_wdgt_position_get_position (GL_WDGT_POSITION (position), &x, &y);
471 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_ellipse));
473 g_signal_handlers_block_by_func (G_OBJECT(object),
474 update_dialog_cb, view_ellipse);
475 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
476 g_signal_handlers_unblock_by_func (G_OBJECT(object),
477 update_dialog_cb, view_ellipse);
479 gl_debug (DEBUG_VIEW, "END");
482 /*---------------------------------------------------------------------------*/
483 /* PRIVATE. size "changed" callback. */
484 /*---------------------------------------------------------------------------*/
486 size_changed_cb (glWdgtSize *size,
487 glViewEllipse *view_ellipse)
489 glLabelObject *object;
491 gboolean keep_aspect_ratio_flag;
493 gl_debug (DEBUG_VIEW, "START");
495 gl_wdgt_size_get_size (GL_WDGT_SIZE (size),
496 &w, &h, &keep_aspect_ratio_flag);
498 object = gl_view_object_get_object (GL_VIEW_OBJECT(view_ellipse));
500 g_signal_handlers_block_by_func (G_OBJECT(object),
501 update_dialog_cb, view_ellipse);
502 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
503 g_signal_handlers_unblock_by_func (G_OBJECT(object),
504 update_dialog_cb, view_ellipse);
506 gl_debug (DEBUG_VIEW, "END");
509 /*---------------------------------------------------------------------------*/
510 /* PRIVATE. label object "changed" callback. */
511 /*---------------------------------------------------------------------------*/
513 update_dialog_cb (glLabelObject *object,
514 glViewEllipse *view_ellipse)
517 guint line_color, fill_color;
520 gl_debug (DEBUG_VIEW, "START");
522 /* Query properties of object. */
523 gl_label_object_get_position (GL_LABEL_OBJECT(object), &x, &y);
524 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
525 line_width = gl_label_ellipse_get_line_width(GL_LABEL_ELLIPSE(object));
526 line_color = gl_label_ellipse_get_line_color(GL_LABEL_ELLIPSE(object));
527 fill_color = gl_label_ellipse_get_fill_color(GL_LABEL_ELLIPSE(object));
529 /* Block widget handlers to prevent recursion */
530 g_signal_handlers_block_by_func (G_OBJECT(view_ellipse->private->line),
531 line_changed_cb, view_ellipse);
532 g_signal_handlers_block_by_func (G_OBJECT(view_ellipse->private->fill),
533 fill_changed_cb, view_ellipse);
534 g_signal_handlers_block_by_func (G_OBJECT(view_ellipse->private->position),
535 position_changed_cb, view_ellipse);
536 g_signal_handlers_block_by_func (G_OBJECT(view_ellipse->private->size),
537 size_changed_cb, view_ellipse);
539 /* Update widgets in property dialog */
540 gl_wdgt_line_set_params (GL_WDGT_LINE (view_ellipse->private->line),
543 gl_wdgt_fill_set_params (GL_WDGT_FILL (view_ellipse->private->fill),
545 gl_wdgt_position_set_position (GL_WDGT_POSITION(view_ellipse->private->position),
547 gl_wdgt_size_set_size (GL_WDGT_SIZE(view_ellipse->private->size), w, h);
549 /* Unblock widget handlers */
550 g_signal_handlers_unblock_by_func (G_OBJECT(view_ellipse->private->line),
551 line_changed_cb, view_ellipse);
552 g_signal_handlers_unblock_by_func (G_OBJECT(view_ellipse->private->fill),
553 fill_changed_cb, view_ellipse);
554 g_signal_handlers_unblock_by_func (G_OBJECT(view_ellipse->private->position),
555 position_changed_cb, view_ellipse);
556 g_signal_handlers_unblock_by_func (G_OBJECT(view_ellipse->private->size),
557 size_changed_cb, view_ellipse);
560 gl_debug (DEBUG_VIEW, "END");
563 /*****************************************************************************/
564 /* Return apropos cursor for create object mode. */
565 /*****************************************************************************/
567 gl_view_ellipse_get_create_cursor (void)
569 static GdkCursor *cursor = NULL;
570 GdkPixmap *pixmap_data, *pixmap_mask;
571 GdkColor fg = { 0, 0, 0, 0 };
572 GdkColor bg = { 0, 65535, 65535, 65535 };
574 gl_debug (DEBUG_VIEW, "START");
577 pixmap_data = gdk_bitmap_create_from_data (NULL,
579 cursor_ellipse_width,
580 cursor_ellipse_height);
581 pixmap_mask = gdk_bitmap_create_from_data (NULL,
582 cursor_ellipse_mask_bits,
583 cursor_ellipse_mask_width,
584 cursor_ellipse_mask_height);
586 gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
587 &bg, cursor_ellipse_x_hot,
588 cursor_ellipse_y_hot);
591 gl_debug (DEBUG_VIEW, "END");
596 /*****************************************************************************/
597 /* Canvas event handler for creating ellipse objects. */
598 /*****************************************************************************/
600 gl_view_ellipse_create_event_handler (GnomeCanvas *canvas,
604 static gdouble x0, y0;
605 static gboolean dragging = FALSE;
606 static glViewObject *view_ellipse;
607 static GObject *object;
609 guint line_color, fill_color;
612 gl_debug (DEBUG_VIEW, "");
614 switch (event->type) {
616 case GDK_BUTTON_PRESS:
617 switch (event->button.button) {
620 gdk_pointer_grab (GTK_WIDGET (view->canvas)->window,
622 GDK_POINTER_MOTION_MASK |
623 GDK_BUTTON_RELEASE_MASK |
624 GDK_BUTTON_PRESS_MASK,
625 NULL, NULL, event->button.time);
626 gnome_canvas_window_to_world (canvas,
628 event->button.y, &x, &y);
629 object = gl_label_ellipse_new (view->label);
630 gl_label_object_set_position (GL_LABEL_OBJECT(object),
632 gl_label_object_set_size (GL_LABEL_OBJECT(object),
635 line_color = CREATE_LINE_COLOR;
636 fill_color = CREATE_FILL_COLOR;
637 gl_label_ellipse_set_line_width (GL_LABEL_ELLIPSE(object),
639 gl_label_ellipse_set_line_color (GL_LABEL_ELLIPSE(object),
641 gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object),
643 view_ellipse = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
653 case GDK_BUTTON_RELEASE:
654 switch (event->button.button) {
657 gdk_pointer_ungrab (event->button.time);
658 gnome_canvas_window_to_world (canvas,
660 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_ellipse_set_line_color (GL_LABEL_ELLIPSE(object),
675 gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object),
677 gl_view_unselect_all (view);
678 gl_view_object_select (GL_VIEW_OBJECT(view_ellipse));
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 w = MAX (x, x0) - MIN (x, x0);
694 h = MAX (y, y0) - MIN (y, y0);
695 gl_label_object_set_size (GL_LABEL_OBJECT(object),