3
* Copyright (C) 2002 - 2004 Vivien Malerba
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
#include "mg-canvas.h"
22
#include "mg-canvas-entity.h"
23
#include "mg-canvas-field.h"
24
#include <libmergeant/mg-field.h>
25
#include <libmergeant/mg-db-table.h>
26
#include <libmergeant/mg-query.h>
27
#include <libmergeant/mg-entity.h>
29
static void mg_canvas_entity_class_init (MgCanvasEntityClass * class);
30
static void mg_canvas_entity_init (MgCanvasEntity * drag);
31
static void mg_canvas_entity_dispose (GObject * object);
32
static void mg_canvas_entity_finalize (GObject * object);
34
static void mg_canvas_entity_set_property (GObject *object,
38
static void mg_canvas_entity_get_property (GObject *object,
50
struct _MgCanvasEntityPrivate
54
/* UI building information */
55
GSList *field_items; /* list of GnomeCanvasItem for the fields */
57
GnomeCanvasItem *title;
58
gdouble *field_ypos; /* array for each field's Y position in this canvas group */
60
/* presentation parameters */
65
/* get a pointer to the parents to be able to call their destructor */
66
static GObjectClass *entity_parent_class = NULL;
69
mg_canvas_entity_get_type (void)
71
static GType type = 0;
74
static const GTypeInfo info = {
75
sizeof (MgCanvasEntityClass),
77
(GBaseFinalizeFunc) NULL,
78
(GClassInitFunc) mg_canvas_entity_class_init,
81
sizeof (MgCanvasEntity),
83
(GInstanceInitFunc) mg_canvas_entity_init
86
type = g_type_register_static (MG_CANVAS_ITEM_TYPE, "MgCanvasEntity", &info, 0);
95
mg_canvas_entity_class_init (MgCanvasEntityClass * class)
97
GObjectClass *object_class = G_OBJECT_CLASS (class);
99
entity_parent_class = g_type_class_peek_parent (class);
101
object_class->dispose = mg_canvas_entity_dispose;
102
object_class->finalize = mg_canvas_entity_finalize;
105
object_class->set_property = mg_canvas_entity_set_property;
106
object_class->get_property = mg_canvas_entity_get_property;
108
g_object_class_install_property
109
(object_class, PROP_ENTITY,
110
g_param_spec_pointer ("entity", NULL, NULL, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
111
g_object_class_install_property
112
(object_class, PROP_SCALE,
113
g_param_spec_double ("scale", NULL, NULL, 0., G_MAXDOUBLE, 0., G_PARAM_WRITABLE));
117
mg_canvas_entity_init (MgCanvasEntity * entity)
119
entity->priv = g_new0 (MgCanvasEntityPrivate, 1);
120
entity->priv->entity = NULL;
121
entity->priv->field_ypos = NULL;
123
entity->priv->x_text_space = 3.;
124
entity->priv->y_text_space = 3.;
127
static void clean_items (MgCanvasEntity *ce);
128
static void create_items (MgCanvasEntity *ce);
129
static void entity_nullified_cb (MgEntity *ent, MgCanvasEntity *ce);
130
static void entity_changed_cb (MgEntity *ent, MgCanvasEntity *ce);
133
mg_canvas_entity_dispose (GObject * object)
136
g_return_if_fail (object != NULL);
137
g_return_if_fail (IS_MG_CANVAS_ENTITY (object));
139
ce = MG_CANVAS_ENTITY (object);
141
if (ce->priv->entity) {
142
g_signal_handlers_disconnect_by_func (G_OBJECT (ce->priv->entity),
143
G_CALLBACK (entity_nullified_cb), ce);
144
g_signal_handlers_disconnect_by_func (G_OBJECT (ce->priv->entity),
145
G_CALLBACK (entity_changed_cb), ce);
146
ce->priv->entity = NULL;
149
/* for the parent class */
150
entity_parent_class->dispose (object);
155
mg_canvas_entity_finalize (GObject * object)
158
g_return_if_fail (object != NULL);
159
g_return_if_fail (IS_MG_CANVAS_ENTITY (object));
161
ce = MG_CANVAS_ENTITY (object);
163
if (ce->priv->field_items)
164
g_slist_free (ce->priv->field_items);
165
if (ce->priv->field_ypos)
166
g_free (ce->priv->field_ypos);
172
/* for the parent class */
173
entity_parent_class->finalize (object);
177
mg_canvas_entity_set_property (GObject *object,
186
PangoFontDescription *font_desc, *font_copy;
188
ce = MG_CANVAS_ENTITY (object);
192
ptr = g_value_get_pointer (value);
193
if (ptr == ce->priv->entity)
196
if (ce->priv->entity) {
197
g_signal_handlers_disconnect_by_func (G_OBJECT (ce->priv->entity),
198
G_CALLBACK (entity_nullified_cb), ce);
199
g_signal_handlers_disconnect_by_func (G_OBJECT (ce->priv->entity),
200
G_CALLBACK (entity_changed_cb), ce);
201
ce->priv->entity = NULL;
205
g_return_if_fail (IS_MG_ENTITY (ptr));
206
ce->priv->entity = ptr;
207
g_signal_connect (G_OBJECT (ce->priv->entity), "nullified",
208
G_CALLBACK (entity_nullified_cb), ce);
209
/* Signals to keep the display up to date */
210
g_signal_connect (G_OBJECT (ce->priv->entity), "changed",
211
G_CALLBACK (entity_changed_cb), ce);
217
scale = g_value_get_double (value);
218
list = ce->priv->field_items;
220
g_object_set (G_OBJECT (list->data), "scale", scale, NULL);
221
list = g_slist_next (list);
223
g_object_get (G_OBJECT (ce->priv->title), "font-desc", &font_desc, NULL);
224
font_copy = pango_font_description_copy (font_desc);
225
pango_font_description_set_size (font_copy, scale * ce->priv->init_font_size);
226
g_object_set (G_OBJECT (ce->priv->title), "font-desc", font_copy, NULL);
227
pango_font_description_free (font_copy);
232
mg_canvas_entity_get_property (GObject *object,
241
entity_nullified_cb (MgEntity *ent, MgCanvasEntity *ce)
243
gtk_object_destroy (GTK_OBJECT (ce));
247
entity_changed_cb (MgEntity *ent, MgCanvasEntity *ce)
253
* destroy any existing GnomeCanvasItem obejcts
256
clean_items (MgCanvasEntity *ce)
258
/* destroy all the items in the group */
259
while (GNOME_CANVAS_GROUP (ce)->item_list)
260
gtk_object_destroy (GTK_OBJECT (GNOME_CANVAS_GROUP (ce)->item_list->data));
262
ce->priv->title = NULL;
264
/* free the fields positions */
265
if (ce->priv->field_ypos) {
266
g_free (ce->priv->field_ypos);
267
ce->priv->field_ypos = NULL;
271
static int button_item_event (GnomeCanvasItem *ci, GdkEvent *event, MgCanvasEntity *ce);
272
static void field_item_destroy_cb (MgCanvasField *field, MgCanvasEntity *ce);
275
* create new GnomeCanvasItem objects
278
create_items (MgCanvasEntity *ce)
280
GnomeCanvasItem *item;
282
double x1, y1, x2, y2;
283
GSList *list, *tmplist;
284
gdouble x, sqsize, radius;
285
gdouble title_text_height, title_text_width, total_width;
288
/* WARNING: the text items (GNOME_TYPE_CANVAS_TEXT) are first drawn without taking care of the real zoom factor =>
289
* we must take that into account when using the text sizes */
290
gdouble scale = GNOME_CANVAS_ITEM (ce)->canvas->pixels_per_unit;
294
/* Title of the Table or query */
295
ce->priv->init_font_size = pango_font_description_get_size
296
(GTK_WIDGET (GNOME_CANVAS_ITEM (ce)->canvas)->style->font_desc);
297
cstr = mg_base_get_name (MG_BASE (ce->priv->entity));
298
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
299
GNOME_TYPE_CANVAS_TEXT,
300
"font-desc", GTK_WIDGET (GNOME_CANVAS_ITEM (ce)->canvas)->style->font_desc,
301
"weight", PANGO_WEIGHT_BOLD,
303
"x", ce->priv->x_text_space,
304
"y", ce->priv->y_text_space,
305
"fill_color", "black",
306
"justification", GTK_JUSTIFY_RIGHT,
307
"anchor", GTK_ANCHOR_NORTH_WEST,
309
gnome_canvas_item_get_bounds (item, &x1, &y1, &x2, &y2);
310
ce->priv->title = item;
312
/* Getting text metrics */
313
title_text_height = (y2 - y1) * scale;
314
title_text_width = (x2 - x1) * scale;
315
total_width = title_text_width + 2 * ce->priv->x_text_space;
318
sqsize = title_text_height * 0.6;
319
list = mg_entity_get_visible_fields (ce->priv->entity);
321
ce->priv->field_ypos = g_new0 (gdouble, g_slist_length (list) + 1);
322
ce->priv->field_ypos [0] = title_text_height + 3* ce->priv->y_text_space;
327
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
328
MG_CANVAS_FIELD_TYPE,
330
"y", ce->priv->field_ypos[fieldn],
331
"field", tmplist->data,
333
ce->priv->field_items = g_slist_append (ce->priv->field_items, item);
335
g_signal_connect (G_OBJECT (item), "destroy",
336
G_CALLBACK (field_item_destroy_cb), ce);
338
gnome_canvas_item_get_bounds (item, &x1, &y1, &x2, &y2);
339
ce->priv->field_ypos[fieldn+1] = y2;
341
if (x2 - x1 > total_width)
342
total_width = x2 - x1;
344
tmplist = g_slist_next (tmplist);
349
/* "button" to close the MgCanvasEntity */
350
sqsize = title_text_height * 0.8;
351
x = total_width + ce->priv->x_text_space;
352
if (x - sqsize - 2*ce->priv->x_text_space < title_text_width)
353
x = title_text_width + sqsize + 2*ce->priv->x_text_space;
355
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
356
GNOME_TYPE_CANVAS_RECT,
358
"y1", ce->priv->y_text_space,
360
"y2", ce->priv->y_text_space + sqsize,
361
"fill_color", "white",
362
"outline_color", "black",
365
gnome_canvas_item_raise_to_top (item);
366
g_signal_connect (G_OBJECT (item),"event",
367
G_CALLBACK (button_item_event), ce);
369
if (x - ce->priv->x_text_space > total_width)
370
total_width = x - ce->priv->x_text_space;
372
cstr = MG_CANVAS_ENTITY_COLOR;
373
if (IS_MG_DB_TABLE (ce->priv->entity))
374
cstr = MG_CANVAS_DB_TABLE_COLOR;
375
if (IS_MG_QUERY (ce->priv->entity))
376
cstr = MG_CANVAS_QUERY_COLOR;
378
radius = sqsize * .2;
379
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
380
GNOME_TYPE_CANVAS_ELLIPSE,
381
"x1", x - sqsize/2. - radius,
382
"y1", ce->priv->y_text_space + sqsize/2. - radius,
383
"x2", x - sqsize/2. + radius,
384
"y2", ce->priv->y_text_space + sqsize/2. + radius,
386
"outline_color", "black",
389
gnome_canvas_item_raise_to_top (item);
390
g_signal_connect (G_OBJECT (item),"event",
391
G_CALLBACK (button_item_event), ce);
393
/* Top little frame */
394
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
395
GNOME_TYPE_CANVAS_RECT,
398
"x2", total_width + 2. * ce->priv->x_text_space,
399
"y2", title_text_height + 2 * ce->priv->y_text_space,
400
"outline_color", "black",
404
gnome_canvas_item_lower_to_bottom (item);
407
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (ce),
408
GNOME_TYPE_CANVAS_RECT,
411
"x2", total_width + 2. * ce->priv->x_text_space,
412
"y2", ce->priv->field_ypos[fieldn] + 1,
413
"outline_color", "black",
414
"fill_color", "white",
415
"width_units", 1.0, NULL);
416
gnome_canvas_item_lower_to_bottom (item);
418
total_width += 2. * ce->priv->x_text_space;
420
/* setting the fields' background width to be the same for all */
421
tmplist = ce->priv->field_items;
423
g_object_set (G_OBJECT (tmplist->data), "width", total_width, NULL);
424
tmplist = g_slist_next (tmplist);
427
/* make sure the scale is correctly applied to text items */
428
g_object_set (G_OBJECT (ce), "scale", scale, NULL);
432
field_item_destroy_cb (MgCanvasField *field, MgCanvasEntity *ce)
434
g_assert (g_slist_find (ce->priv->field_items, field));
435
ce->priv->field_items = g_slist_remove (ce->priv->field_items, field);
438
static void popup_delete_cb (GtkMenuItem *mitem, MgCanvasEntity *ce);
440
button_item_event (GnomeCanvasItem *ci, GdkEvent *event, MgCanvasEntity *ce)
442
gboolean done = TRUE;
443
GtkWidget *menu, *entry;
445
switch (event->type) {
446
case GDK_BUTTON_PRESS:
447
menu = gtk_menu_new ();
448
entry = gtk_menu_item_new_with_label (_("Remove"));
449
g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (popup_delete_cb), ce);
450
gtk_menu_append (GTK_MENU (menu), entry);
451
gtk_widget_show (entry);
452
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
453
NULL, NULL, ((GdkEventButton *)event)->button,
454
((GdkEventButton *)event)->time);
466
popup_delete_cb (GtkMenuItem *mitem, MgCanvasEntity *ce)
470
gitem = mg_canvas_item_get_graph_item (MG_CANVAS_ITEM (ce));
471
mg_base_nullify (MG_BASE (gitem));
475
* mg_canvas_entity_get_field_item
476
* @ce: a #MgCanvasEntity object
477
* @field: a #MgField object
479
* Get the #MgCanvasField object representing @field
482
* Returns: the corresponding #MgCanvasField
485
mg_canvas_entity_get_field_item (MgCanvasEntity *ce, MgField *field)
490
g_return_val_if_fail (ce && IS_MG_CANVAS_ENTITY (ce), NULL);
491
g_return_val_if_fail (ce->priv, NULL);
492
g_return_val_if_fail (ce->priv->entity, NULL);
494
fields = mg_entity_get_visible_fields (ce->priv->entity);
495
pos = g_slist_index (fields, field);
496
g_return_val_if_fail (pos >= 0, NULL);
498
return g_slist_nth_data (ce->priv->field_items, pos);
503
* mg_canvas_entity_get_field_ypos
504
* @ce: a #MgCanvasEntity object
505
* @field: a #MgField object
507
* Get the Y position of the #MgCanvasField object representing @field
508
* in @ce, in @ce's coordinates.
510
* Returns: the Y coordinate.
513
mg_canvas_entity_get_field_ypos (MgCanvasEntity *ce, MgField *field)
517
g_return_val_if_fail (ce && IS_MG_CANVAS_ENTITY (ce), 0.);
518
g_return_val_if_fail (ce->priv, 0.);
519
g_return_val_if_fail (ce->priv->entity, 0.);
520
g_return_val_if_fail (ce->priv->field_ypos, 0.);
522
pos = mg_entity_get_field_index (ce->priv->entity, field);
523
g_return_val_if_fail (pos >= 0, 0.);
524
return (ce->priv->field_ypos[pos+1] + ce->priv->field_ypos[pos]) / 2.;