1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* DO NOT USE THIS OBJECT AS A BASIS FOR A NEW OBJECT. */
32 #include "connectionpoint.h"
33 #include "diarenderer.h"
34 #include "attributes.h"
36 #include "properties.h"
38 #include "pixmaps/entity.xpm"
40 #define DEFAULT_WIDTH 2.0
41 #define DEFAULT_HEIGHT 1.0
42 #define TEXT_BORDER_WIDTH_X 0.7
43 #define TEXT_BORDER_WIDTH_Y 0.5
44 #define WEAK_BORDER_WIDTH 0.25
45 #define FONT_HEIGHT 0.8
46 #define DIAMOND_RATIO 0.6
48 typedef struct _Entity Entity
;
50 #define NUM_CONNECTIONS 9
55 ConnectionPoint connections
[NUM_CONNECTIONS
];
72 static real
entity_distance_from(Entity
*entity
, Point
*point
);
73 static void entity_select(Entity
*entity
, Point
*clicked_point
,
74 DiaRenderer
*interactive_renderer
);
75 static ObjectChange
* entity_move_handle(Entity
*entity
, Handle
*handle
,
76 Point
*to
, ConnectionPoint
*cp
,
77 HandleMoveReason reason
,
78 ModifierKeys modifiers
);
79 static ObjectChange
* entity_move(Entity
*entity
, Point
*to
);
80 static void entity_draw(Entity
*entity
, DiaRenderer
*renderer
);
81 static void entity_update_data(Entity
*entity
);
82 static DiaObject
*entity_create(Point
*startpoint
,
86 static void entity_destroy(Entity
*entity
);
87 static DiaObject
*entity_copy(Entity
*entity
);
88 static PropDescription
*
89 entity_describe_props(Entity
*entity
);
90 static void entity_get_props(Entity
*entity
, GPtrArray
*props
);
91 static void entity_set_props(Entity
*entity
, GPtrArray
*props
);
93 static void entity_save(Entity
*entity
, ObjectNode obj_node
,
94 const char *filename
);
95 static DiaObject
*entity_load(ObjectNode obj_node
, int version
,
96 const char *filename
);
98 static ObjectTypeOps entity_type_ops
=
100 (CreateFunc
) entity_create
,
101 (LoadFunc
) entity_load
,
102 (SaveFunc
) entity_save
105 DiaObjectType entity_type
=
107 "ER - Entity", /* name */
109 (char **) entity_xpm
, /* pixmap */
111 &entity_type_ops
/* ops */
114 DiaObjectType
*_entity_type
= (DiaObjectType
*) &entity_type
;
116 static ObjectOps entity_ops
= {
117 (DestroyFunc
) entity_destroy
,
118 (DrawFunc
) entity_draw
,
119 (DistanceFunc
) entity_distance_from
,
120 (SelectFunc
) entity_select
,
121 (CopyFunc
) entity_copy
,
122 (MoveFunc
) entity_move
,
123 (MoveHandleFunc
) entity_move_handle
,
124 (GetPropertiesFunc
) object_create_props_dialog
,
125 (ApplyPropertiesFunc
) object_apply_props_from_dialog
,
126 (ObjectMenuFunc
) NULL
,
127 (DescribePropsFunc
) entity_describe_props
,
128 (GetPropsFunc
) entity_get_props
,
129 (SetPropsFunc
) entity_set_props
,
132 static PropDescription entity_props
[] = {
133 ELEMENT_COMMON_PROPERTIES
,
134 { "name", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
,
135 N_("Name:"), NULL
, NULL
},
136 { "weak", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
,
137 N_("Weak:"), NULL
, NULL
},
138 { "associative", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
,
139 N_("Associative:"), NULL
, NULL
},
141 PROP_STD_LINE_COLOUR
,
142 PROP_STD_FILL_COLOUR
,
144 PROP_STD_TEXT_HEIGHT
,
148 static PropDescription
*
149 entity_describe_props(Entity
*entity
)
151 if (entity_props
[0].quark
== 0)
152 prop_desc_list_calculate_quarks(entity_props
);
156 static PropOffset entity_offsets
[] = {
157 ELEMENT_COMMON_PROPERTIES_OFFSETS
,
158 { "name", PROP_TYPE_STRING
, offsetof(Entity
, name
) },
159 { "weak", PROP_TYPE_BOOL
, offsetof(Entity
, weak
) },
160 { "associative", PROP_TYPE_BOOL
, offsetof(Entity
, associative
) },
161 { "line_width", PROP_TYPE_REAL
, offsetof(Entity
, border_width
) },
162 { "line_colour", PROP_TYPE_COLOUR
, offsetof(Entity
, border_color
) },
163 { "fill_colour", PROP_TYPE_COLOUR
, offsetof(Entity
, inner_color
) },
164 { "text_font", PROP_TYPE_FONT
, offsetof (Entity
, font
) },
165 { "text_height", PROP_TYPE_REAL
, offsetof(Entity
, font_height
) },
171 entity_get_props(Entity
*entity
, GPtrArray
*props
)
173 object_get_props_from_offsets(&entity
->element
.object
,
174 entity_offsets
, props
);
178 entity_set_props(Entity
*entity
, GPtrArray
*props
)
180 object_set_props_from_offsets(&entity
->element
.object
,
181 entity_offsets
, props
);
182 entity_update_data(entity
);
186 entity_distance_from(Entity
*entity
, Point
*point
)
188 Element
*elem
= &entity
->element
;
191 rect
.left
= elem
->corner
.x
- entity
->border_width
/2;
192 rect
.right
= elem
->corner
.x
+ elem
->width
+ entity
->border_width
/2;
193 rect
.top
= elem
->corner
.y
- entity
->border_width
/2;
194 rect
.bottom
= elem
->corner
.y
+ elem
->height
+ entity
->border_width
/2;
195 return distance_rectangle_point(&rect
, point
);
199 entity_select(Entity
*entity
, Point
*clicked_point
,
200 DiaRenderer
*interactive_renderer
)
202 element_update_handles(&entity
->element
);
206 entity_move_handle(Entity
*entity
, Handle
*handle
,
207 Point
*to
, ConnectionPoint
*cp
,
208 HandleMoveReason reason
, ModifierKeys modifiers
)
210 assert(entity
!=NULL
);
211 assert(handle
!=NULL
);
214 element_move_handle(&entity
->element
, handle
->id
, to
, cp
, reason
, modifiers
);
216 entity_update_data(entity
);
222 entity_move(Entity
*entity
, Point
*to
)
224 entity
->element
.corner
= *to
;
226 entity_update_data(entity
);
232 entity_draw(Entity
*entity
, DiaRenderer
*renderer
)
234 DiaRendererClass
*renderer_ops
= DIA_RENDERER_GET_CLASS (renderer
);
235 Point ul_corner
, lr_corner
;
240 assert(entity
!= NULL
);
241 assert(renderer
!= NULL
);
243 elem
= &entity
->element
;
245 ul_corner
.x
= elem
->corner
.x
;
246 ul_corner
.y
= elem
->corner
.y
;
247 lr_corner
.x
= elem
->corner
.x
+ elem
->width
;
248 lr_corner
.y
= elem
->corner
.y
+ elem
->height
;
250 renderer_ops
->set_fillstyle(renderer
, FILLSTYLE_SOLID
);
252 renderer_ops
->fill_rect(renderer
,
255 &entity
->inner_color
);
257 renderer_ops
->set_linewidth(renderer
, entity
->border_width
);
258 renderer_ops
->set_linestyle(renderer
, LINESTYLE_SOLID
);
259 renderer_ops
->set_linejoin(renderer
, LINEJOIN_MITER
);
261 renderer_ops
->draw_rect(renderer
,
264 &entity
->border_color
);
267 diff
= WEAK_BORDER_WIDTH
/*MIN(elem->width / 2.0 * 0.20, elem->height / 2.0 * 0.20)*/;
272 renderer_ops
->draw_rect(renderer
,
273 &ul_corner
, &lr_corner
,
274 &entity
->border_color
);
276 if(entity
->associative
){
278 corners
[0].x
= elem
->corner
.x
;
279 corners
[0].y
= elem
->corner
.y
+ elem
->height
/ 2;
280 corners
[1].x
= elem
->corner
.x
+ elem
->width
/ 2;
281 corners
[1].y
= elem
->corner
.y
;
282 corners
[2].x
= elem
->corner
.x
+ elem
->width
;
283 corners
[2].y
= elem
->corner
.y
+ elem
->height
/ 2;
284 corners
[3].x
= elem
->corner
.x
+ elem
->width
/ 2;
285 corners
[3].y
= elem
->corner
.y
+ elem
->height
;
286 renderer_ops
->set_fillstyle(renderer
, FILLSTYLE_SOLID
);
288 renderer_ops
->fill_polygon(renderer
, corners
, 4,
289 &entity
->inner_color
);
291 renderer_ops
->set_linewidth(renderer
, entity
->border_width
);
292 renderer_ops
->set_linestyle(renderer
, LINESTYLE_SOLID
);
293 renderer_ops
->set_linejoin(renderer
, LINEJOIN_MITER
);
295 renderer_ops
->draw_polygon(renderer
, corners
, 4,
296 &entity
->border_color
);
299 p
.x
= elem
->corner
.x
+ elem
->width
/ 2.0;
300 p
.y
= elem
->corner
.y
+ (elem
->height
- entity
->font_height
)/2.0 +
301 dia_font_ascent(entity
->name
,entity
->font
, entity
->font_height
);
302 renderer_ops
->set_font(renderer
, entity
->font
, entity
->font_height
);
303 renderer_ops
->draw_string(renderer
,
310 entity_update_data(Entity
*entity
)
312 Element
*elem
= &entity
->element
;
313 DiaObject
*obj
= &elem
->object
;
314 ElementBBExtras
*extra
= &elem
->extra_spacing
;
317 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
319 if(entity
->associative
){
320 elem
->width
= entity
->name_width
+ 2*TEXT_BORDER_WIDTH_X
;
321 elem
->height
= elem
->width
* DIAMOND_RATIO
;
324 elem
->width
= entity
->name_width
+ 2*TEXT_BORDER_WIDTH_X
;
325 elem
->height
= entity
->font_height
+ 2*TEXT_BORDER_WIDTH_Y
;
328 /* Update connections: */
329 connpoint_update(&entity
->connections
[0],
333 connpoint_update(&entity
->connections
[1],
334 elem
->corner
.x
+ elem
->width
/ 2.0,
337 connpoint_update(&entity
->connections
[2],
338 elem
->corner
.x
+ elem
->width
,
341 connpoint_update(&entity
->connections
[3],
343 elem
->corner
.y
+ elem
->height
/ 2.0,
345 connpoint_update(&entity
->connections
[4],
346 elem
->corner
.x
+ elem
->width
,
347 elem
->corner
.y
+ elem
->height
/ 2.0,
349 connpoint_update(&entity
->connections
[5],
351 elem
->corner
.y
+ elem
->height
,
353 connpoint_update(&entity
->connections
[6],
354 elem
->corner
.x
+ elem
->width
/ 2.0,
355 elem
->corner
.y
+ elem
->height
,
357 connpoint_update(&entity
->connections
[7],
358 elem
->corner
.x
+ elem
->width
,
359 elem
->corner
.y
+ elem
->height
,
361 connpoint_update(&entity
->connections
[8],
362 elem
->corner
.x
+ elem
->width
/ 2.0,
363 elem
->corner
.y
+ elem
->height
/ 2.0,
366 extra
->border_trans
= entity
->border_width
/2.0;
367 element_update_boundingbox(elem
);
369 obj
->position
= elem
->corner
;
371 element_update_handles(elem
);
375 entity_create(Point
*startpoint
,
385 entity
= g_malloc0(sizeof(Entity
));
386 elem
= &entity
->element
;
389 obj
->type
= &entity_type
;
391 obj
->ops
= &entity_ops
;
393 elem
->corner
= *startpoint
;
394 elem
->width
= DEFAULT_WIDTH
;
395 elem
->height
= DEFAULT_HEIGHT
;
397 entity
->border_width
= attributes_get_default_linewidth();
398 entity
->border_color
= attributes_get_foreground();
399 entity
->inner_color
= attributes_get_background();
401 element_init(elem
, 8, NUM_CONNECTIONS
);
403 for (i
=0;i
<NUM_CONNECTIONS
;i
++) {
404 obj
->connections
[i
] = &entity
->connections
[i
];
405 entity
->connections
[i
].object
= obj
;
406 entity
->connections
[i
].connected
= NULL
;
408 entity
->connections
[8].flags
= CP_FLAGS_MAIN
;
410 entity
->weak
= GPOINTER_TO_INT(user_data
);
411 entity
->font
= dia_font_new_from_style(DIA_FONT_MONOSPACE
,FONT_HEIGHT
);
412 entity
->font_height
= FONT_HEIGHT
;
413 entity
->name
= g_strdup(_("Entity"));
416 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
418 entity_update_data(entity
);
421 obj
->handles
[i
]->type
= HANDLE_NON_MOVABLE
;
425 *handle2
= obj
->handles
[0];
426 return &entity
->element
.object
;
430 entity_destroy(Entity
*entity
)
432 dia_font_unref(entity
->font
);
433 element_destroy(&entity
->element
);
434 g_free(entity
->name
);
438 entity_copy(Entity
*entity
)
442 Element
*elem
, *newelem
;
445 elem
= &entity
->element
;
447 newentity
= g_malloc0(sizeof(Entity
));
448 newelem
= &newentity
->element
;
449 newobj
= &newelem
->object
;
451 element_copy(elem
, newelem
);
453 newentity
->border_width
= entity
->border_width
;
454 newentity
->border_color
= entity
->border_color
;
455 newentity
->inner_color
= entity
->inner_color
;
457 for (i
=0;i
<NUM_CONNECTIONS
;i
++) {
458 newobj
->connections
[i
] = &newentity
->connections
[i
];
459 newentity
->connections
[i
].object
= newobj
;
460 newentity
->connections
[i
].connected
= NULL
;
461 newentity
->connections
[i
].pos
= entity
->connections
[i
].pos
;
462 newentity
->connections
[i
].last_pos
= entity
->connections
[i
].last_pos
;
463 newentity
->connections
[i
].flags
= entity
->connections
[i
].flags
;
466 newentity
->font
= dia_font_ref(entity
->font
);
467 newentity
->font_height
= entity
->font_height
;
468 newentity
->name
= g_strdup(entity
->name
);
469 newentity
->name_width
= entity
->name_width
;
471 newentity
->weak
= entity
->weak
;
473 return &newentity
->element
.object
;
477 entity_save(Entity
*entity
, ObjectNode obj_node
, const char *filename
)
479 element_save(&entity
->element
, obj_node
);
481 data_add_real(new_attribute(obj_node
, "border_width"),
482 entity
->border_width
);
483 data_add_color(new_attribute(obj_node
, "border_color"),
484 &entity
->border_color
);
485 data_add_color(new_attribute(obj_node
, "inner_color"),
486 &entity
->inner_color
);
487 data_add_string(new_attribute(obj_node
, "name"),
489 data_add_boolean(new_attribute(obj_node
, "weak"),
491 data_add_boolean(new_attribute(obj_node
, "associative"),
492 entity
->associative
);
493 data_add_font (new_attribute (obj_node
, "font"),
495 data_add_real(new_attribute(obj_node
, "font_height"),
496 entity
->font_height
);
500 entity_load(ObjectNode obj_node
, int version
, const char *filename
)
508 entity
= g_malloc0(sizeof(Entity
));
509 elem
= &entity
->element
;
512 obj
->type
= &entity_type
;
513 obj
->ops
= &entity_ops
;
515 element_load(elem
, obj_node
);
517 entity
->border_width
= 0.1;
518 attr
= object_find_attribute(obj_node
, "border_width");
520 entity
->border_width
= data_real( attribute_first_data(attr
) );
522 entity
->border_color
= color_black
;
523 attr
= object_find_attribute(obj_node
, "border_color");
525 data_color(attribute_first_data(attr
), &entity
->border_color
);
527 entity
->inner_color
= color_white
;
528 attr
= object_find_attribute(obj_node
, "inner_color");
530 data_color(attribute_first_data(attr
), &entity
->inner_color
);
533 attr
= object_find_attribute(obj_node
, "name");
535 entity
->name
= data_string(attribute_first_data(attr
));
537 attr
= object_find_attribute(obj_node
, "weak");
539 entity
->weak
= data_boolean(attribute_first_data(attr
));
541 attr
= object_find_attribute(obj_node
, "associative");
543 entity
->associative
= data_boolean(attribute_first_data(attr
));
545 if (entity
->font
!= NULL
) {
546 /* This shouldn't happen, but doesn't hurt */
547 dia_font_unref(entity
->font
);
550 attr
= object_find_attribute (obj_node
, "font");
552 entity
->font
= data_font (attribute_first_data (attr
));
554 entity
->font_height
= FONT_HEIGHT
;
555 attr
= object_find_attribute(obj_node
, "font_height");
557 entity
->font_height
= data_real(attribute_first_data(attr
));
559 element_init(elem
, 8, NUM_CONNECTIONS
);
561 for (i
=0;i
<NUM_CONNECTIONS
;i
++) {
562 obj
->connections
[i
] = &entity
->connections
[i
];
563 entity
->connections
[i
].object
= obj
;
564 entity
->connections
[i
].connected
= NULL
;
566 entity
->connections
[8].flags
= CP_FLAGS_MAIN
;
568 if (entity
->font
== NULL
) {
569 entity
->font
= dia_font_new_from_style(DIA_FONT_MONOSPACE
,1.0);
573 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
575 entity_update_data(entity
);
578 obj
->handles
[i
]->type
= HANDLE_NON_MOVABLE
;
581 return &entity
->element
.object
;