Template rendering improvements.
[dia.git] / objects / UML / fork.c
blob952094eeda77a84e70b5fff20f2778760ba87847
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * Fork type for UML diagrams
5 * Copyright (C) 2002 Alejandro Sierra <asierra@servidor.unam.mx>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <assert.h>
27 #include <math.h>
28 #include <string.h>
30 #include "intl.h"
31 #include "object.h"
32 #include "element.h"
33 #include "diarenderer.h"
34 #include "attributes.h"
35 #include "text.h"
36 #include "properties.h"
38 #include "uml.h"
40 #include "pixmaps/fork.xpm"
42 typedef struct _Fork Fork;
44 struct _Fork
46 Element element;
47 ConnectionPoint connections[8];
50 static const double FORK_BORDERWIDTH = 0.0;
51 static const double FORK_WIDTH = 4.0;
52 static const double FORK_HEIGHT = 0.4;
53 static const double FORK_MARGIN = 0.125;
55 static real fork_distance_from(Fork *branch, Point *point);
56 static void fork_select(Fork *branch, Point *clicked_point, DiaRenderer *interactive_renderer);
57 static ObjectChange* fork_move_handle(Fork *branch, Handle *handle,
58 Point *to, ConnectionPoint *cp,
59 HandleMoveReason reason, ModifierKeys modifiers);
60 static ObjectChange* fork_move(Fork *branch, Point *to);
61 static void fork_draw(Fork *branch, DiaRenderer *renderer);
62 static DiaObject *fork_create(Point *startpoint,
63 void *user_data,
64 Handle **handle1,
65 Handle **handle2);
66 static void fork_destroy(Fork *branch);
67 static DiaObject *fork_load(ObjectNode obj_node, int version,
68 const char *filename);
70 static PropDescription *fork_describe_props(Fork *branch);
71 static void fork_get_props(Fork *branch, GPtrArray *props);
72 static void fork_set_props(Fork *branch, GPtrArray *props);
74 static void fork_update_data(Fork *branch);
76 static ObjectTypeOps fork_type_ops =
78 (CreateFunc) fork_create,
79 (LoadFunc) fork_load,/*using_properties*/ /* load */
80 (SaveFunc) object_save_using_properties, /* save */
81 (GetDefaultsFunc) NULL,
82 (ApplyDefaultsFunc) NULL
85 DiaObjectType fork_type =
87 "UML - Fork", /* name */
88 0, /* version */
89 (char **) fork_xpm, /* pixmap */
91 &fork_type_ops /* ops */
94 static ObjectOps fork_ops =
96 (DestroyFunc) fork_destroy,
97 (DrawFunc) fork_draw,
98 (DistanceFunc) fork_distance_from,
99 (SelectFunc) fork_select,
100 (CopyFunc) object_copy_using_properties,
101 (MoveFunc) fork_move,
102 (MoveHandleFunc) fork_move_handle,
103 (GetPropertiesFunc) object_return_null,
104 (ApplyPropertiesFunc) object_return_void,
105 (ObjectMenuFunc) NULL,
106 (DescribePropsFunc) fork_describe_props,
107 (GetPropsFunc) fork_get_props,
108 (SetPropsFunc) fork_set_props
111 static PropDescription fork_props[] = {
112 ELEMENT_COMMON_PROPERTIES,
114 PROP_DESC_END
117 static PropDescription *
118 fork_describe_props(Fork *branch)
120 if (fork_props[0].quark == 0) {
121 prop_desc_list_calculate_quarks(fork_props);
123 return fork_props;
126 static PropOffset fork_offsets[] = {
127 ELEMENT_COMMON_PROPERTIES_OFFSETS,
128 { NULL, 0, 0 },
131 static void
132 fork_get_props(Fork * branch, GPtrArray *props)
134 object_get_props_from_offsets(&branch->element.object,
135 fork_offsets, props);
138 static void
139 fork_set_props(Fork *branch, GPtrArray *props)
141 object_set_props_from_offsets(&branch->element.object,
142 fork_offsets, props);
143 fork_update_data(branch);
146 static real
147 fork_distance_from(Fork *branch, Point *point)
149 DiaObject *obj = &branch->element.object;
150 return distance_rectangle_point(&obj->bounding_box, point);
153 static void
154 fork_select(Fork *branch, Point *clicked_point, DiaRenderer *interactive_renderer)
156 element_update_handles(&branch->element);
159 static ObjectChange*
160 fork_move_handle(Fork *branch, Handle *handle,
161 Point *to, ConnectionPoint *cp,
162 HandleMoveReason reason, ModifierKeys modifiers)
164 coord dx;
165 Point c;
167 assert(branch!=NULL);
168 assert(handle!=NULL);
169 assert(to!=NULL);
171 assert(handle->id < 8);
173 /* Only orizontal E/W movement are allowed */
174 if (handle->id==3 || handle->id==4) {
175 c.y = to->y;
176 c.x = branch->element.corner.x + branch->element.width / 2.;
177 dx = fabs(to->x - c.x);
178 to->x = c.x - dx;
179 element_move_handle(&branch->element, 3, to, cp, reason, modifiers);
180 to->x = c.x + dx;
181 element_move_handle(&branch->element, 4, to, cp, reason, modifiers);
182 fork_update_data(branch);
185 return NULL;
188 static ObjectChange*
189 fork_move(Fork *branch, Point *to)
191 branch->element.corner = *to;
192 fork_update_data(branch);
194 return NULL;
197 static void fork_draw(Fork *branch, DiaRenderer *renderer)
199 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
200 Element *elem;
201 real w, h;
202 Point p1, p2;
204 assert(branch != NULL);
205 assert(renderer != NULL);
207 elem = &branch->element;
208 w = elem->width;
209 h = elem->height;
211 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
212 renderer_ops->set_linewidth(renderer, FORK_BORDERWIDTH);
213 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
215 p1.x = elem->corner.x;
216 p1.y = elem->corner.y;
217 p2.x = elem->corner.x + w;
218 p2.y = elem->corner.y + h;
220 renderer_ops->fill_rect(renderer,
221 &p1, &p2,
222 &color_black);
225 static void fork_update_data(Fork *branch)
227 Element *elem = &branch->element;
228 DiaObject *obj = &elem->object;
230 /* Update connections: */
231 branch->connections[0].pos.x = elem->corner.x + FORK_MARGIN*elem->width;
232 branch->connections[0].pos.y = elem->corner.y;
233 branch->connections[1].pos.x = elem->corner.x + elem->width / 2.;
234 branch->connections[1].pos.y = elem->corner.y;
235 branch->connections[2].pos.x = elem->corner.x + elem->width - FORK_MARGIN*elem->width;
236 branch->connections[2].pos.y = elem->corner.y;
237 branch->connections[3].pos.x = elem->corner.x + FORK_MARGIN*elem->width;
238 branch->connections[3].pos.y = elem->corner.y + elem->height;
239 branch->connections[4].pos.x = elem->corner.x + elem->width / 2.;
240 branch->connections[4].pos.y = elem->corner.y + elem->height;
241 branch->connections[5].pos.x = elem->corner.x + elem->width - FORK_MARGIN*elem->width;
242 branch->connections[5].pos.y = elem->corner.y + elem->height;
244 element_update_boundingbox(elem);
245 obj->position = elem->corner;
247 element_update_handles(elem);
250 static DiaObject *fork_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2)
252 Fork *branch;
253 Element *elem;
254 DiaObject *obj;
255 int i;
257 branch = g_malloc0(sizeof(Fork));
258 elem = &branch->element;
259 obj = &elem->object;
261 obj->type = &fork_type;
263 obj->ops = &fork_ops;
265 elem->corner = *startpoint;
266 elem->width = FORK_WIDTH;
267 elem->height = FORK_HEIGHT;
268 element_init(elem, 8, 8);
270 for (i=0;i<8;i++)
272 obj->connections[i] = &branch->connections[i];
273 branch->connections[i].object = obj;
274 branch->connections[i].connected = NULL;
276 elem->extra_spacing.border_trans = FORK_BORDERWIDTH / 2.0;
277 fork_update_data(branch);
279 for (i=0;i<8;i++) {
280 if (i!=3 && i!=4)
281 obj->handles[i]->type = HANDLE_NON_MOVABLE;
284 *handle1 = NULL;
285 *handle2 = obj->handles[0];
286 return &branch->element.object;
289 static void fork_destroy(Fork *branch)
291 element_destroy(&branch->element);
294 static DiaObject *fork_load(ObjectNode obj_node, int version, const char *filename)
296 return object_load_using_properties(&fork_type,
297 obj_node,version,filename);