2006-12-05 David Lodge <dave@cirt.net>
[dia.git] / objects / UML / branch.c
blobb1557b0c507d60fccc8d86107a8dcfe3db933c6a
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * node type for UML diagrams
5 * Copyright (C) 2000 Stefan Seefeld <stefan@berlin-consortium.org>
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/branch.xpm"
42 typedef struct _Branch Branch;
44 struct _Branch
46 Element element;
47 ConnectionPoint connections[8];
48 Color line_color;
49 Color fill_color;
52 static const double BRANCH_BORDERWIDTH = 0.1;
53 static const double BRANCH_WIDTH = 2.0;
54 static const double BRANCH_HEIGHT = 2.0;
56 static real branch_distance_from(Branch *branch, Point *point);
57 static void branch_select(Branch *branch, Point *clicked_point, DiaRenderer *interactive_renderer);
58 static ObjectChange* branch_move_handle(Branch *branch, Handle *handle,
59 Point *to, ConnectionPoint *cp,
60 HandleMoveReason reason, ModifierKeys modifiers);
61 static ObjectChange* branch_move(Branch *branch, Point *to);
62 static void branch_draw(Branch *branch, DiaRenderer *renderer);
63 static DiaObject *branch_create(Point *startpoint,
64 void *user_data,
65 Handle **handle1,
66 Handle **handle2);
67 static void branch_destroy(Branch *branch);
68 static DiaObject *branch_load(ObjectNode obj_node, int version,
69 const char *filename);
71 static PropDescription *branch_describe_props(Branch *branch);
72 static void branch_get_props(Branch *branch, GPtrArray *props);
73 static void branch_set_props(Branch *branch, GPtrArray *props);
75 static void branch_update_data(Branch *branch);
77 static ObjectTypeOps branch_type_ops =
79 (CreateFunc) branch_create,
80 (LoadFunc) branch_load,/*using_properties*/ /* load */
81 (SaveFunc) object_save_using_properties, /* save */
82 (GetDefaultsFunc) NULL,
83 (ApplyDefaultsFunc) NULL
86 DiaObjectType branch_type =
88 "UML - Branch", /* name */
89 0, /* version */
90 (char **) branch_xpm, /* pixmap */
92 &branch_type_ops /* ops */
95 static ObjectOps branch_ops =
97 (DestroyFunc) branch_destroy,
98 (DrawFunc) branch_draw,
99 (DistanceFunc) branch_distance_from,
100 (SelectFunc) branch_select,
101 (CopyFunc) object_copy_using_properties,
102 (MoveFunc) branch_move,
103 (MoveHandleFunc) branch_move_handle,
104 (GetPropertiesFunc) object_create_props_dialog,
105 (ApplyPropertiesFunc) object_apply_props_from_dialog,
106 (ObjectMenuFunc) NULL,
107 (DescribePropsFunc) branch_describe_props,
108 (GetPropsFunc) branch_get_props,
109 (SetPropsFunc) branch_set_props
112 static PropDescription branch_props[] = {
113 ELEMENT_COMMON_PROPERTIES,
114 PROP_STD_LINE_COLOUR_OPTIONAL,
115 PROP_STD_FILL_COLOUR_OPTIONAL,
117 PROP_DESC_END
120 static PropDescription *
121 branch_describe_props(Branch *branch)
123 if (branch_props[0].quark == 0) {
124 prop_desc_list_calculate_quarks(branch_props);
126 return branch_props;
129 static PropOffset branch_offsets[] = {
130 ELEMENT_COMMON_PROPERTIES_OFFSETS,
131 {"line_colour",PROP_TYPE_COLOUR,offsetof(Branch,line_color)},
132 {"fill_colour",PROP_TYPE_COLOUR,offsetof(Branch,fill_color)},
133 { NULL, 0, 0 },
136 static void
137 branch_get_props(Branch * branch, GPtrArray *props)
139 object_get_props_from_offsets(&branch->element.object,
140 branch_offsets, props);
143 static void
144 branch_set_props(Branch *branch, GPtrArray *props)
146 object_set_props_from_offsets(&branch->element.object,
147 branch_offsets, props);
148 branch_update_data(branch);
151 static real
152 branch_distance_from(Branch *branch, Point *point)
154 DiaObject *obj = &branch->element.object;
155 return distance_rectangle_point(&obj->bounding_box, point);
158 static void
159 branch_select(Branch *branch, Point *clicked_point, DiaRenderer *interactive_renderer)
161 element_update_handles(&branch->element);
164 static ObjectChange*
165 branch_move_handle(Branch *branch, Handle *handle,
166 Point *to, ConnectionPoint *cp,
167 HandleMoveReason reason, ModifierKeys modifiers)
169 assert(branch!=NULL);
170 assert(handle!=NULL);
171 assert(to!=NULL);
173 assert(handle->id < 8);
175 /* It smashes size info in update_data anyway. And none of its siblings
176 * resizable, so until that changes, this should be properly unresizable
180 element_move_handle(&branch->element, handle->id, to, cp, reason, modifiers);
181 branch_update_data(branch);
184 return NULL;
187 static ObjectChange*
188 branch_move(Branch *branch, Point *to)
190 branch->element.corner = *to;
191 branch_update_data(branch);
193 return NULL;
196 static void branch_draw(Branch *branch, DiaRenderer *renderer)
198 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
199 Element *elem;
200 real w, h;
201 Point points[4];
203 assert(branch != NULL);
204 assert(renderer != NULL);
206 elem = &branch->element;
207 w = elem->width/2;
208 h = elem->height/2;
209 points[0].x = elem->corner.x, points[0].y = elem->corner.y + h;
210 points[1].x = elem->corner.x + w, points[1].y = elem->corner.y;
211 points[2].x = elem->corner.x + 2*w, points[2].y = elem->corner.y + h;
212 points[3].x = elem->corner.x + w, points[3].y = elem->corner.y + 2*h;
214 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
215 renderer_ops->set_linewidth(renderer, BRANCH_BORDERWIDTH);
216 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
218 renderer_ops->fill_polygon(renderer, points, 4, &branch->fill_color);
219 renderer_ops->draw_polygon(renderer, points, 4, &branch->line_color);
222 static void branch_update_data(Branch *branch)
224 Element *elem = &branch->element;
225 DiaObject *obj = &elem->object;
227 elem->width = BRANCH_WIDTH;
228 elem->height = BRANCH_HEIGHT;
230 /* Update connections: */
231 branch->connections[0].pos.x = elem->corner.x;
232 branch->connections[0].pos.y = elem->corner.y + elem->height / 2.;
233 branch->connections[0].directions = DIR_WEST;
234 branch->connections[1].pos.x = elem->corner.x + elem->width / 2.;
235 branch->connections[1].pos.y = elem->corner.y;
236 branch->connections[1].directions = DIR_NORTH;
237 branch->connections[2].pos.x = elem->corner.x + elem->width;
238 branch->connections[2].pos.y = elem->corner.y + elem->height / 2.;
239 branch->connections[2].directions = DIR_EAST;
240 branch->connections[3].pos.x = elem->corner.x + elem->width / 2.;;
241 branch->connections[3].pos.y = elem->corner.y + elem->height;
242 branch->connections[3].directions = DIR_SOUTH;
244 element_update_boundingbox(elem);
245 obj->position = elem->corner;
247 element_update_handles(elem);
250 static DiaObject *branch_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2)
252 Branch *branch;
253 Element *elem;
254 DiaObject *obj;
255 int i;
257 branch = g_malloc0(sizeof(Branch));
258 elem = &branch->element;
259 obj = &elem->object;
261 obj->type = &branch_type;
263 obj->ops = &branch_ops;
265 elem->corner = *startpoint;
266 element_init(elem, 8, 8);
268 branch->line_color = attributes_get_foreground();
269 branch->fill_color = attributes_get_background();
271 for (i=0;i<8;i++)
273 obj->connections[i] = &branch->connections[i];
274 branch->connections[i].object = obj;
275 branch->connections[i].connected = NULL;
277 elem->extra_spacing.border_trans = BRANCH_BORDERWIDTH / 2.0;
278 branch_update_data(branch);
280 for (i=0;i<8;i++) {
281 obj->handles[i]->type = HANDLE_NON_MOVABLE;
284 *handle1 = NULL;
285 *handle2 = NULL;
286 return &branch->element.object;
289 static void branch_destroy(Branch *branch)
291 element_destroy(&branch->element);
294 static DiaObject *branch_load(ObjectNode obj_node, int version, const char *filename)
296 return object_load_using_properties(&branch_type,
297 obj_node,version,filename);