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. */
33 #include "connectionpoint.h"
35 #include "attributes.h"
37 #include "properties.h"
39 #include "pixmaps/entity.xpm"
41 #define DEFAULT_WIDTH 2.0
42 #define DEFAULT_HEIGHT 1.0
43 #define TEXT_BORDER_WIDTH_X 0.7
44 #define TEXT_BORDER_WIDTH_Y 0.5
45 #define WEAK_BORDER_WIDTH 0.25
46 #define FONT_HEIGHT 0.8
48 typedef struct _Entity Entity
;
53 ConnectionPoint connections
[8];
68 static real
entity_distance_from(Entity
*entity
, Point
*point
);
69 static void entity_select(Entity
*entity
, Point
*clicked_point
,
70 Renderer
*interactive_renderer
);
71 static void entity_move_handle(Entity
*entity
, Handle
*handle
,
72 Point
*to
, HandleMoveReason reason
, ModifierKeys modifiers
);
73 static void entity_move(Entity
*entity
, Point
*to
);
74 static void entity_draw(Entity
*entity
, Renderer
*renderer
);
75 static void entity_update_data(Entity
*entity
);
76 static Object
*entity_create(Point
*startpoint
,
80 static void entity_destroy(Entity
*entity
);
81 static Object
*entity_copy(Entity
*entity
);
82 static PropDescription
*
83 entity_describe_props(Entity
*entity
);
84 static void entity_get_props(Entity
*entity
, GPtrArray
*props
);
85 static void entity_set_props(Entity
*entity
, GPtrArray
*props
);
87 static void entity_save(Entity
*entity
, ObjectNode obj_node
,
88 const char *filename
);
89 static Object
*entity_load(ObjectNode obj_node
, int version
,
90 const char *filename
);
92 static ObjectTypeOps entity_type_ops
=
94 (CreateFunc
) entity_create
,
95 (LoadFunc
) entity_load
,
96 (SaveFunc
) entity_save
99 ObjectType entity_type
=
101 "ER - Entity", /* name */
103 (char **) entity_xpm
, /* pixmap */
105 &entity_type_ops
/* ops */
108 ObjectType
*_entity_type
= (ObjectType
*) &entity_type
;
110 static ObjectOps entity_ops
= {
111 (DestroyFunc
) entity_destroy
,
112 (DrawFunc
) entity_draw
,
113 (DistanceFunc
) entity_distance_from
,
114 (SelectFunc
) entity_select
,
115 (CopyFunc
) entity_copy
,
116 (MoveFunc
) entity_move
,
117 (MoveHandleFunc
) entity_move_handle
,
118 (GetPropertiesFunc
) object_create_props_dialog
,
119 (ApplyPropertiesFunc
) object_apply_props_from_dialog
,
120 (ObjectMenuFunc
) NULL
,
121 (DescribePropsFunc
) entity_describe_props
,
122 (GetPropsFunc
) entity_get_props
,
123 (SetPropsFunc
) entity_set_props
,
126 static PropDescription entity_props
[] = {
127 ELEMENT_COMMON_PROPERTIES
,
128 { "name", PROP_TYPE_STRING
, PROP_FLAG_VISIBLE
,
129 N_("Name:"), NULL
, NULL
},
130 { "weak", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
,
131 N_("Weak:"), NULL
, NULL
},
133 PROP_STD_LINE_COLOUR
,
134 PROP_STD_FILL_COLOUR
,
136 PROP_STD_TEXT_HEIGHT
,
140 static PropDescription
*
141 entity_describe_props(Entity
*entity
)
143 if (entity_props
[0].quark
== 0)
144 prop_desc_list_calculate_quarks(entity_props
);
148 static PropOffset entity_offsets
[] = {
149 ELEMENT_COMMON_PROPERTIES_OFFSETS
,
150 { "name", PROP_TYPE_STRING
, offsetof(Entity
, name
) },
151 { "weak", PROP_TYPE_BOOL
, offsetof(Entity
, weak
) },
152 { "line_width", PROP_TYPE_REAL
, offsetof(Entity
, border_width
) },
153 { "line_colour", PROP_TYPE_COLOUR
, offsetof(Entity
, border_color
) },
154 { "fill_colour", PROP_TYPE_COLOUR
, offsetof(Entity
, inner_color
) },
155 { "text_font", PROP_TYPE_FONT
, offsetof (Entity
, font
) },
156 { "text_height", PROP_TYPE_REAL
, offsetof(Entity
, font_height
) },
162 entity_get_props(Entity
*entity
, GPtrArray
*props
)
164 object_get_props_from_offsets(&entity
->element
.object
,
165 entity_offsets
, props
);
169 entity_set_props(Entity
*entity
, GPtrArray
*props
)
171 object_set_props_from_offsets(&entity
->element
.object
,
172 entity_offsets
, props
);
173 entity_update_data(entity
);
177 entity_distance_from(Entity
*entity
, Point
*point
)
179 Element
*elem
= &entity
->element
;
182 rect
.left
= elem
->corner
.x
- entity
->border_width
/2;
183 rect
.right
= elem
->corner
.x
+ elem
->width
+ entity
->border_width
/2;
184 rect
.top
= elem
->corner
.y
- entity
->border_width
/2;
185 rect
.bottom
= elem
->corner
.y
+ elem
->height
+ entity
->border_width
/2;
186 return distance_rectangle_point(&rect
, point
);
190 entity_select(Entity
*entity
, Point
*clicked_point
,
191 Renderer
*interactive_renderer
)
193 element_update_handles(&entity
->element
);
197 entity_move_handle(Entity
*entity
, Handle
*handle
,
198 Point
*to
, HandleMoveReason reason
, ModifierKeys modifiers
)
200 assert(entity
!=NULL
);
201 assert(handle
!=NULL
);
204 element_move_handle(&entity
->element
, handle
->id
, to
, reason
);
206 entity_update_data(entity
);
210 entity_move(Entity
*entity
, Point
*to
)
212 entity
->element
.corner
= *to
;
214 entity_update_data(entity
);
218 entity_draw(Entity
*entity
, Renderer
*renderer
)
220 Point ul_corner
, lr_corner
;
225 assert(entity
!= NULL
);
226 assert(renderer
!= NULL
);
228 elem
= &entity
->element
;
230 ul_corner
.x
= elem
->corner
.x
;
231 ul_corner
.y
= elem
->corner
.y
;
232 lr_corner
.x
= elem
->corner
.x
+ elem
->width
;
233 lr_corner
.y
= elem
->corner
.y
+ elem
->height
;
235 renderer
->ops
->set_fillstyle(renderer
, FILLSTYLE_SOLID
);
237 renderer
->ops
->fill_rect(renderer
,
240 &entity
->inner_color
);
242 renderer
->ops
->set_linewidth(renderer
, entity
->border_width
);
243 renderer
->ops
->set_linestyle(renderer
, LINESTYLE_SOLID
);
244 renderer
->ops
->set_linejoin(renderer
, LINEJOIN_MITER
);
246 renderer
->ops
->draw_rect(renderer
,
249 &entity
->border_color
);
252 diff
= WEAK_BORDER_WIDTH
/*MIN(elem->width / 2.0 * 0.20, elem->height / 2.0 * 0.20)*/;
257 renderer
->ops
->draw_rect(renderer
,
258 &ul_corner
, &lr_corner
,
259 &entity
->border_color
);
262 p
.x
= elem
->corner
.x
+ elem
->width
/ 2.0;
263 p
.y
= elem
->corner
.y
+ (elem
->height
- entity
->font_height
)/2.0 +
264 dia_font_ascent(entity
->name
,entity
->font
, entity
->font_height
);
265 renderer
->ops
->set_font(renderer
, entity
->font
, entity
->font_height
);
266 renderer
->ops
->draw_string(renderer
,
273 entity_update_data(Entity
*entity
)
275 Element
*elem
= &entity
->element
;
276 Object
*obj
= &elem
->object
;
277 ElementBBExtras
*extra
= &elem
->extra_spacing
;
280 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
282 elem
->width
= entity
->name_width
+ 2*TEXT_BORDER_WIDTH_X
;
283 elem
->height
= entity
->font_height
+ 2*TEXT_BORDER_WIDTH_Y
;
285 /* Update connections: */
286 entity
->connections
[0].pos
= elem
->corner
;
287 entity
->connections
[1].pos
.x
= elem
->corner
.x
+ elem
->width
/ 2.0;
288 entity
->connections
[1].pos
.y
= elem
->corner
.y
;
289 entity
->connections
[2].pos
.x
= elem
->corner
.x
+ elem
->width
;
290 entity
->connections
[2].pos
.y
= elem
->corner
.y
;
291 entity
->connections
[3].pos
.x
= elem
->corner
.x
;
292 entity
->connections
[3].pos
.y
= elem
->corner
.y
+ elem
->height
/ 2.0;
293 entity
->connections
[4].pos
.x
= elem
->corner
.x
+ elem
->width
;
294 entity
->connections
[4].pos
.y
= elem
->corner
.y
+ elem
->height
/ 2.0;
295 entity
->connections
[5].pos
.x
= elem
->corner
.x
;
296 entity
->connections
[5].pos
.y
= elem
->corner
.y
+ elem
->height
;
297 entity
->connections
[6].pos
.x
= elem
->corner
.x
+ elem
->width
/ 2.0;
298 entity
->connections
[6].pos
.y
= elem
->corner
.y
+ elem
->height
;
299 entity
->connections
[7].pos
.x
= elem
->corner
.x
+ elem
->width
;
300 entity
->connections
[7].pos
.y
= elem
->corner
.y
+ elem
->height
;
302 extra
->border_trans
= entity
->border_width
/2.0;
303 element_update_boundingbox(elem
);
305 obj
->position
= elem
->corner
;
307 element_update_handles(elem
);
311 entity_create(Point
*startpoint
,
321 entity
= g_malloc0(sizeof(Entity
));
322 elem
= &entity
->element
;
325 obj
->type
= &entity_type
;
327 obj
->ops
= &entity_ops
;
329 elem
->corner
= *startpoint
;
330 elem
->width
= DEFAULT_WIDTH
;
331 elem
->height
= DEFAULT_WIDTH
;
333 entity
->border_width
= attributes_get_default_linewidth();
334 entity
->border_color
= attributes_get_foreground();
335 entity
->inner_color
= attributes_get_background();
337 element_init(elem
, 8, 8);
340 obj
->connections
[i
] = &entity
->connections
[i
];
341 entity
->connections
[i
].object
= obj
;
342 entity
->connections
[i
].connected
= NULL
;
345 entity
->weak
= GPOINTER_TO_INT(user_data
);
346 entity
->font
= dia_font_new(BASIC_MONOSPACE_FONT
,STYLE_NORMAL
,FONT_HEIGHT
);
347 entity
->font_height
= FONT_HEIGHT
;
348 entity
->name
= g_strdup(_("Entity"));
351 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
353 entity_update_data(entity
);
356 obj
->handles
[i
]->type
= HANDLE_NON_MOVABLE
;
360 *handle2
= obj
->handles
[0];
361 return &entity
->element
.object
;
365 entity_destroy(Entity
*entity
)
367 dia_font_unref(entity
->font
);
368 element_destroy(&entity
->element
);
369 g_free(entity
->name
);
373 entity_copy(Entity
*entity
)
377 Element
*elem
, *newelem
;
380 elem
= &entity
->element
;
382 newentity
= g_malloc0(sizeof(Entity
));
383 newelem
= &newentity
->element
;
384 newobj
= &newelem
->object
;
386 element_copy(elem
, newelem
);
388 newentity
->border_width
= entity
->border_width
;
389 newentity
->border_color
= entity
->border_color
;
390 newentity
->inner_color
= entity
->inner_color
;
393 newobj
->connections
[i
] = &newentity
->connections
[i
];
394 newentity
->connections
[i
].object
= newobj
;
395 newentity
->connections
[i
].connected
= NULL
;
396 newentity
->connections
[i
].pos
= entity
->connections
[i
].pos
;
397 newentity
->connections
[i
].last_pos
= entity
->connections
[i
].last_pos
;
400 newentity
->font
= dia_font_ref(entity
->font
);
401 newentity
->font_height
= entity
->font_height
;
402 newentity
->name
= strdup(entity
->name
);
403 newentity
->name_width
= entity
->name_width
;
405 newentity
->weak
= entity
->weak
;
407 return &newentity
->element
.object
;
411 entity_save(Entity
*entity
, ObjectNode obj_node
, const char *filename
)
413 element_save(&entity
->element
, obj_node
);
415 data_add_real(new_attribute(obj_node
, "border_width"),
416 entity
->border_width
);
417 data_add_color(new_attribute(obj_node
, "border_color"),
418 &entity
->border_color
);
419 data_add_color(new_attribute(obj_node
, "inner_color"),
420 &entity
->inner_color
);
421 data_add_string(new_attribute(obj_node
, "name"),
423 data_add_boolean(new_attribute(obj_node
, "weak"),
425 data_add_font (new_attribute (obj_node
, "font"),
427 data_add_real(new_attribute(obj_node
, "font_height"),
428 entity
->font_height
);
432 entity_load(ObjectNode obj_node
, int version
, const char *filename
)
440 entity
= g_malloc0(sizeof(Entity
));
441 elem
= &entity
->element
;
444 obj
->type
= &entity_type
;
445 obj
->ops
= &entity_ops
;
447 element_load(elem
, obj_node
);
449 entity
->border_width
= 0.1;
450 attr
= object_find_attribute(obj_node
, "border_width");
452 entity
->border_width
= data_real( attribute_first_data(attr
) );
454 entity
->border_color
= color_black
;
455 attr
= object_find_attribute(obj_node
, "border_color");
457 data_color(attribute_first_data(attr
), &entity
->border_color
);
459 entity
->inner_color
= color_white
;
460 attr
= object_find_attribute(obj_node
, "inner_color");
462 data_color(attribute_first_data(attr
), &entity
->inner_color
);
465 attr
= object_find_attribute(obj_node
, "name");
467 entity
->name
= data_string(attribute_first_data(attr
));
469 attr
= object_find_attribute(obj_node
, "weak");
471 entity
->weak
= data_boolean(attribute_first_data(attr
));
473 dia_font_unref(entity
->font
);
475 attr
= object_find_attribute (obj_node
, "font");
477 entity
->font
= data_font (attribute_first_data (attr
));
479 entity
->font_height
= FONT_HEIGHT
;
480 attr
= object_find_attribute(obj_node
, "font_height");
482 entity
->font_height
= data_real(attribute_first_data(attr
));
484 element_init(elem
, 8, 8);
487 obj
->connections
[i
] = &entity
->connections
[i
];
488 entity
->connections
[i
].object
= obj
;
489 entity
->connections
[i
].connected
= NULL
;
492 if (entity
->font
== NULL
) {
493 entity
->font
= dia_font_new("Monospace",STYLE_NORMAL
,1.0);
497 dia_font_string_width(entity
->name
, entity
->font
, entity
->font_height
);
499 entity_update_data(entity
);
502 obj
->handles
[i
]->type
= HANDLE_NON_MOVABLE
;
505 return &entity
->element
.object
;