]> git.sur5r.net Git - glabels/blob - glabels1/src/item_box.c
2009-09-22 Jim Evins <evins@snaught.com>
[glabels] / glabels1 / src / item_box.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  item_box.c:  GLabels Box Object (canvas item) module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26
27 #include "display.h"
28 #include "item_box.h"
29
30 #include "highlight.h"
31
32 #include "mdi.h"
33 #include "propertybox.h"
34 #include "prop_line.h"
35 #include "prop_fill.h"
36 #include "prop_size.h"
37 #include "prop_position.h"
38
39 #include "pixmaps/cursor_box.xbm"
40 #include "pixmaps/cursor_box_mask.xbm"
41
42 #include "debug.h"
43
44 /*===========================================*/
45 /* Private data types                        */
46 /*===========================================*/
47
48 typedef struct {
49         GnomeCanvasItem *item;
50         gboolean keep_aspect_ratio_flag;
51
52         /* Page 0 widgets */
53         GtkWidget *line;
54         GtkWidget *fill;
55
56         /* Page 1 widgets */
57         GtkWidget *position;
58         GtkWidget *size;
59 } PropertyDialogPassback;
60
61 /*===========================================*/
62 /* Private globals                           */
63 /*===========================================*/
64 \f
65 /*===========================================*/
66 /* Local function prototypes                 */
67 /*===========================================*/
68
69 static void item_box_update (GnomeCanvasItem * item);
70
71 static void changed_cb (glPropertyBox * propertybox);
72 static void apply_cb (glPropertyBox * propertybox,
73                       gint page, PropertyDialogPassback * data);
74 \f
75 /*****************************************************************************/
76 /* Create a box object                                                       */
77 /*****************************************************************************/
78 GnomeCanvasItem *
79 gl_item_box_new (glLabelObject * object,
80                  glDisplay * display)
81 {
82         GnomeCanvasGroup *group;
83         GnomeCanvasItem *item;
84
85         group = gnome_canvas_root (GNOME_CANVAS (display->canvas));
86         item = gnome_canvas_item_new (group, gnome_canvas_rect_get_type (),
87                                       "x1", object->x,
88                                       "y1", object->y,
89                                       "x2", object->x + object->arg.box.w,
90                                       "y2", object->y + object->arg.box.h,
91                                       "width_units", object->arg.box.line_width,
92                                       "outline_color_rgba",
93                                       object->arg.box.line_color,
94                                       "fill_color_rgba",
95                                       object->arg.box.fill_color, NULL);
96
97         /* Squirrel away pointers to object and display in the canvas item. */
98         gtk_object_set_data (GTK_OBJECT (item), "label_object", object);
99         gtk_object_set_data (GTK_OBJECT (item), "display", display);
100         gtk_object_set_data (GTK_OBJECT (item), "highlight", NULL);
101
102         gtk_signal_connect (GTK_OBJECT (item), "event",
103                             GTK_SIGNAL_FUNC (gl_display_item_event_handler),
104                             display);
105
106         gl_display_new_item_menu (item);
107
108         gl_display_set_modified (display);
109
110         return item;
111 }
112
113 /*---------------------------------------------------------------------------*/
114 /* PRIVATE. Update a box object                                              */
115 /*---------------------------------------------------------------------------*/
116 static void
117 item_box_update (GnomeCanvasItem * item)
118 {
119         glLabelObject *object;
120         glDisplay *display;
121         gdouble affine[6];
122
123         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
124
125         art_affine_identity (affine);
126         gnome_canvas_item_affine_absolute (item, affine);
127         gnome_canvas_item_set (item,
128                                "x1", object->x,
129                                "y1", object->y,
130                                "x2", object->x + object->arg.box.w,
131                                "y2", object->y + object->arg.box.h,
132                                "width_units", object->arg.box.line_width,
133                                "outline_color_rgba", object->arg.box.line_color,
134                                "fill_color_rgba", object->arg.box.fill_color,
135                                NULL);
136
137         display = gtk_object_get_data (GTK_OBJECT (item), "display");
138         gl_display_set_modified (display);
139 }
140
141 /*****************************************************************************/
142 /* Return a selection canvas item/group for given item                       */
143 /*****************************************************************************/
144 void
145 gl_item_box_highlight (GnomeCanvasItem * item)
146 {
147         gl_highlight (item, GL_HIGHLIGHT_BOX_RESIZABLE);
148 }
149
150 /*****************************************************************************/
151 /* Get position and size of object.                                          */
152 /*****************************************************************************/
153 void
154 gl_item_box_get_position_size (GnomeCanvasItem * item,
155                                gdouble * x,
156                                gdouble * y,
157                                gdouble * w,
158                                gdouble * h)
159 {
160         glLabelObject *object;
161
162         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
163
164         *x = object->x;
165         *y = object->y;
166
167         *w = object->arg.box.w;
168         *h = object->arg.box.h;
169 }
170
171 /*****************************************************************************/
172 /* Get position and size of object.                                          */
173 /*****************************************************************************/
174 void
175 gl_item_box_set_position_size (GnomeCanvasItem * item,
176                                gdouble x,
177                                gdouble y,
178                                gdouble w,
179                                gdouble h)
180 {
181         glLabelObject *object;
182
183         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
184
185         object->x = x;
186         object->y = y;
187
188         object->arg.box.w = w;
189         object->arg.box.h = h;
190
191         item_box_update (item);
192 }
193
194 /*****************************************************************************/
195 /* Get box item bounds.                                                      */
196 /*****************************************************************************/
197 void
198 gl_item_box_get_bounds (GnomeCanvasItem * item,
199                         gdouble * x1,
200                         gdouble * y1,
201                         gdouble * x2,
202                         gdouble * y2)
203 {
204         gnome_canvas_item_get_bounds (item, x1, y1, x2, y2);
205 }
206
207 /*****************************************************************************/
208 /* Create and run an edit dialog on a box object.                            */
209 /*****************************************************************************/
210 void
211 gl_item_box_edit_dialog (GnomeCanvasItem * item)
212 {
213         GtkWidget *dialog;
214         static PropertyDialogPassback *data = NULL;
215         glLabelObject *object;
216         glDisplay *display;
217         GtkWidget *wvbox;
218
219         object = gtk_object_get_data (GTK_OBJECT (item), "label_object");
220         display = gtk_object_get_data (GTK_OBJECT (item), "display");
221
222         /*-----------------------------------------------------------------*/
223         /* Build dialog with notebook.                                     */
224         /*-----------------------------------------------------------------*/
225         if (data == NULL) {
226                 data = g_new0 (PropertyDialogPassback, 1);
227         }
228         data->item = item;
229
230         dialog = gl_property_box_new ();
231         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
232         gtk_window_set_transient_for (GTK_WINDOW (dialog),
233                                       GTK_WINDOW (gl_mdi_get_active_window ()));
234         gtk_window_set_title (GTK_WINDOW (dialog),
235                               _("Edit box object properties"));
236         gtk_signal_connect (GTK_OBJECT (dialog), "apply",
237                             GTK_SIGNAL_FUNC (apply_cb), data);
238
239         /*---------------------------*/
240         /* Appearance Notebook Tab   */
241         /*---------------------------*/
242         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
243         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
244         gl_property_box_append_page (GL_PROPERTY_BOX (dialog), wvbox,
245                                      gtk_label_new (_("Appearance")));
246
247         /* ------ Line box ------ */
248         data->line = gl_prop_line_new (_("Outline"));
249         gl_prop_line_set_params (GL_PROP_LINE (data->line),
250                                  object->arg.box.line_width,
251                                  object->arg.box.line_color);
252         gtk_box_pack_start (GTK_BOX (wvbox), data->line, FALSE, FALSE, 0);
253         gtk_signal_connect_object (GTK_OBJECT (data->line), "changed",
254                                    GTK_SIGNAL_FUNC (changed_cb),
255                                    GTK_OBJECT (dialog));
256
257         /* ------ Fill box ------ */
258         data->fill = gl_prop_fill_new (_("Fill"));
259         gl_prop_fill_set_params (GL_PROP_FILL (data->fill),
260                                  object->arg.box.fill_color);
261         gtk_box_pack_start (GTK_BOX (wvbox), data->fill, FALSE, FALSE, 0);
262         gtk_signal_connect_object (GTK_OBJECT (data->fill), "changed",
263                                    GTK_SIGNAL_FUNC (changed_cb),
264                                    GTK_OBJECT (dialog));
265
266         /*----------------------------*/
267         /* Position/Size Notebook Tab */
268         /*----------------------------*/
269         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
270         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
271         gl_property_box_append_page (GL_PROPERTY_BOX (dialog), wvbox,
272                                      gtk_label_new (_("Position/Size")));
273
274         /* ------ Position Frame ------ */
275         data->position = gl_prop_position_new (_("Position"));
276         gl_prop_position_set_params (GL_PROP_POSITION (data->position),
277                                      object->x, object->y,
278                                      display->label->width,
279                                      display->label->height);
280         gtk_box_pack_start (GTK_BOX (wvbox), data->position, FALSE, FALSE, 0);
281         gtk_signal_connect_object (GTK_OBJECT (data->position), "changed",
282                                    GTK_SIGNAL_FUNC (changed_cb),
283                                    GTK_OBJECT (dialog));
284
285         /* ------ Size Frame ------ */
286         data->size = gl_prop_size_new (_("Size"));
287         gl_prop_size_set_params (GL_PROP_SIZE (data->size),
288                                  object->arg.box.w, object->arg.box.h,
289                                  data->keep_aspect_ratio_flag,
290                                  display->label->width, display->label->height);
291         gtk_box_pack_start (GTK_BOX (wvbox), data->size, FALSE, FALSE, 0);
292         gtk_signal_connect_object (GTK_OBJECT (data->size), "changed",
293                                    GTK_SIGNAL_FUNC (changed_cb),
294                                    GTK_OBJECT (dialog));
295
296         /*-----------------------------------------------------------------*/
297         /* Run dialog, and update state of object if "Applied."            */
298         /*-----------------------------------------------------------------*/
299         gtk_widget_show_all (GTK_WIDGET (dialog));
300 }
301
302 /*---------------------------------------------------------------------------*/
303 /* PRIVATE.  Callback for when any control in the dialog has changed.        */
304 /*---------------------------------------------------------------------------*/
305 static void
306 changed_cb (glPropertyBox * propertybox)
307 {
308         gl_property_box_changed (propertybox);
309 }
310
311 /*---------------------------------------------------------------------------*/
312 /* PRIVATE.  "Apply" callback.                                               */
313 /*---------------------------------------------------------------------------*/
314 static void
315 apply_cb (glPropertyBox * propertybox,
316           gint page,
317           PropertyDialogPassback * data)
318 {
319         glLabelObject *object;
320         glDisplay *display;
321
322         object = gtk_object_get_data (GTK_OBJECT (data->item), "label_object");
323         display = gtk_object_get_data (GTK_OBJECT (data->item), "display");
324
325         switch (page) {
326
327         case 0:
328                 /* ------- Get updated line width & color ------ */
329                 gl_prop_line_get_params (GL_PROP_LINE (data->line),
330                                          &object->arg.box.line_width,
331                                          &object->arg.box.line_color);
332                 /* ------- Get updated fill color ------ */
333                 gl_prop_fill_get_params (GL_PROP_FILL (data->fill),
334                                          &object->arg.box.fill_color);
335                 break;
336
337         case 1:
338                 /* ------ get updated position ------ */
339                 gl_prop_position_get_position (GL_PROP_POSITION
340                                                (data->position), &object->x,
341                                                &object->y);
342
343                 /* ------ get updated size ------ */
344                 gl_prop_size_get_size (GL_PROP_SIZE (data->size),
345                                        &object->arg.box.w, &object->arg.box.h,
346                                        &data->keep_aspect_ratio_flag);
347                 break;
348
349         default:
350                 return;
351         }
352
353         /* ------ Udate state of object ------ */
354         item_box_update (data->item);
355         gl_display_select_item (display, data->item);
356
357 }
358
359 /*****************************************************************************/
360 /* Return apropos cursor for create object mode.                             */
361 /*****************************************************************************/
362 GdkCursor *
363 gl_item_box_get_create_cursor (void)
364 {
365         static GdkCursor *cursor = NULL;
366         GdkPixmap *pixmap_data, *pixmap_mask;
367         GdkColor fg = { 0, 0, 0, 0 };
368         GdkColor bg = { 0, 65535, 65535, 65535 };
369
370         if (!cursor) {
371                 pixmap_data = gdk_bitmap_create_from_data (NULL,
372                                                            cursor_box_bits,
373                                                            cursor_box_width,
374                                                            cursor_box_height);
375                 pixmap_mask = gdk_bitmap_create_from_data (NULL,
376                                                            cursor_box_mask_bits,
377                                                            cursor_box_mask_width,
378                                                            cursor_box_mask_height);
379                 cursor =
380                     gdk_cursor_new_from_pixmap (pixmap_data, pixmap_mask, &fg,
381                                                 &bg, cursor_box_x_hot,
382                                                 cursor_box_y_hot);
383         }
384
385         return cursor;
386 }
387
388 /*****************************************************************************/
389 /* Canvas event handler (box mode)                                           */
390 /*****************************************************************************/
391 int
392 gl_item_box_create_event_handler (GnomeCanvas * canvas,
393                                   GdkEvent * event,
394                                   gpointer data)
395 {
396         static gdouble x0, y0;
397         static gboolean dragging = FALSE;
398         static GnomeCanvasItem *item;
399         static glLabelObject *object;
400         glDisplay *display = GL_DISPLAY (data);
401         gdouble x, y;
402
403         switch (event->type) {
404
405         case GDK_BUTTON_PRESS:
406                 switch (event->button.button) {
407                 case 1:
408                         dragging = TRUE;
409                         gdk_pointer_grab (GTK_WIDGET (display->canvas)->window,
410                                           FALSE,
411                                           GDK_POINTER_MOTION_MASK |
412                                           GDK_BUTTON_RELEASE_MASK |
413                                           GDK_BUTTON_PRESS_MASK,
414                                           NULL, NULL, event->button.time);
415                         gnome_canvas_window_to_world (canvas,
416                                                       event->button.x,
417                                                       event->button.y, &x, &y);
418                         object =
419                             gl_label_object_new (display->label,
420                                                  GL_LABEL_OBJECT_BOX);
421                         object->x = x;
422                         object->y = y;
423                         object->arg.box.w = 0.0;
424                         object->arg.box.h = 0.0;
425                         object->arg.box.line_width = 1.0;
426                         object->arg.box.line_color =
427                             GNOME_CANVAS_COLOR_A (0, 0, 255, 128);
428                         object->arg.box.fill_color =
429                             GNOME_CANVAS_COLOR_A (128, 128, 128, 128);
430                         item = gl_item_box_new (object, display);
431                         x0 = x;
432                         y0 = y;
433                         return TRUE;
434
435                 default:
436                         return FALSE;
437                 }
438
439         case GDK_BUTTON_RELEASE:
440                 switch (event->button.button) {
441                 case 1:
442                         dragging = FALSE;
443                         gdk_pointer_ungrab (event->button.time);
444                         gnome_canvas_window_to_world (canvas,
445                                                       event->button.x,
446                                                       event->button.y, &x, &y);
447                         if ((x0 == x) && (y0 == y)) {
448                                 x = x0 + 36.0;
449                                 y = y0 + 36.0;
450                         }
451                         object->x = MIN (x, x0);
452                         object->y = MIN (y, y0);
453                         object->arg.box.w = MAX (x, x0) - MIN (x, x0);
454                         object->arg.box.h = MAX (y, y0) - MIN (y, y0);
455                         object->arg.box.line_color =
456                             GNOME_CANVAS_COLOR_A (0, 0, 0, 255);
457                         object->arg.box.fill_color =
458                             GNOME_CANVAS_COLOR_A (0, 255, 0, 255);
459                         item_box_update (item);
460                         gl_display_add_item (display, item);
461                         gl_display_unselect_all (display);
462                         gl_display_select_item (display, item);
463                         gl_display_arrow_mode (display);
464                         return TRUE;
465
466                 default:
467                         return FALSE;
468                 }
469
470         case GDK_MOTION_NOTIFY:
471                 if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
472                         gnome_canvas_window_to_world (canvas,
473                                                       event->motion.x,
474                                                       event->motion.y, &x, &y);
475                         object->x = MIN (x, x0);
476                         object->y = MIN (y, y0);
477                         object->arg.box.w = MAX (x, x0) - MIN (x, x0);
478                         object->arg.box.h = MAX (y, y0) - MIN (y, y0);
479                         item_box_update (item);
480                         return TRUE;
481                 } else {
482                         return FALSE;
483                 }
484
485         default:
486                 return FALSE;
487         }
488
489 }