2006-12-03 Dimitris Glezos <dimitris@glezos.com>
[dia.git] / objects / UML / activity.c
blob6f5690c3d25e661df391feee4b208f9607fe9795
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * Activity type for UML diagrams
5 * Copyright (C) 2002 Alejandro Sierra <asierra@servidor.unam.mx>
6 *
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 /** \file objects/UML/activity.c Implementation of the 'UML - Activity' type */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <assert.h>
28 #include <math.h>
29 #include <string.h>
31 #include "intl.h"
32 #include "object.h"
33 #include "element.h"
34 #include "diarenderer.h"
35 #include "attributes.h"
36 #include "text.h"
37 #include "properties.h"
39 #include "pixmaps/activity.xpm"
41 typedef struct _State State;
43 struct _State {
44 Element element;
46 ConnectionPoint connections[8];
48 Text *text;
50 TextAttributes attrs;
51 Color line_color;
52 Color fill_color;
56 #define STATE_WIDTH 4
57 #define STATE_HEIGHT 3
58 #define STATE_LINEWIDTH 0.1
59 #define STATE_MARGIN_X 0.5
60 #define STATE_MARGIN_Y 0.5
62 static real state_distance_from(State *state, Point *point);
63 static void state_select(State *state, Point *clicked_point,
64 DiaRenderer *interactive_renderer);
65 static ObjectChange* state_move_handle(State *state, Handle *handle,
66 Point *to, ConnectionPoint *cp,
67 HandleMoveReason reason, ModifierKeys modifiers);
68 static ObjectChange* state_move(State *state, Point *to);
69 static void state_draw(State *state, DiaRenderer *renderer);
70 static DiaObject *state_create_activity(Point *startpoint,
71 void *user_data,
72 Handle **handle1,
73 Handle **handle2);
74 static void state_destroy(State *state);
75 static DiaObject *state_load(ObjectNode obj_node, int version,
76 const char *filename);
77 static PropDescription *state_describe_props(State *state);
78 static void state_get_props(State *state, GPtrArray *props);
79 static void state_set_props(State *state, GPtrArray *props);
80 static void state_update_data(State *state);
83 static ObjectTypeOps activity_type_ops =
85 (CreateFunc) state_create_activity,
86 (LoadFunc) state_load,/*using_properties*/ /* load */
87 (SaveFunc) object_save_using_properties, /* save */
88 (GetDefaultsFunc) NULL,
89 (ApplyDefaultsFunc) NULL
92 DiaObjectType activity_type =
94 "UML - Activity", /* name */
95 0, /* version */
96 (char **) activity_xpm, /* pixmap */
98 &activity_type_ops /* ops */
102 static ObjectOps state_ops = {
103 (DestroyFunc) state_destroy,
104 (DrawFunc) state_draw,
105 (DistanceFunc) state_distance_from,
106 (SelectFunc) state_select,
107 (CopyFunc) object_copy_using_properties,
108 (MoveFunc) state_move,
109 (MoveHandleFunc) state_move_handle,
110 (GetPropertiesFunc) object_create_props_dialog,
111 (ApplyPropertiesFunc) object_apply_props_from_dialog,
112 (ObjectMenuFunc) NULL,
113 (DescribePropsFunc) state_describe_props,
114 (GetPropsFunc) state_get_props,
115 (SetPropsFunc) state_set_props
119 static PropDescription activity_props[] = {
120 ELEMENT_COMMON_PROPERTIES,
122 PROP_STD_LINE_COLOUR_OPTIONAL,
123 PROP_STD_FILL_COLOUR_OPTIONAL,
124 PROP_STD_TEXT_FONT,
125 PROP_STD_TEXT_HEIGHT,
126 PROP_STD_TEXT_COLOUR_OPTIONAL,
127 { "text", PROP_TYPE_TEXT, 0, N_("Text"), NULL, NULL },
129 PROP_DESC_END
132 static PropDescription *
133 state_describe_props(State *state)
135 if (activity_props[0].quark == 0) {
136 prop_desc_list_calculate_quarks(activity_props);
138 return activity_props;
141 static PropOffset state_offsets[] = {
142 ELEMENT_COMMON_PROPERTIES_OFFSETS,
143 {"line_colour",PROP_TYPE_COLOUR,offsetof(State,line_color)},
144 {"fill_colour",PROP_TYPE_COLOUR,offsetof(State,fill_color)},
145 {"text",PROP_TYPE_TEXT,offsetof(State,text)},
146 {"text_font",PROP_TYPE_FONT,offsetof(State,attrs.font)},
147 {"text_height",PROP_TYPE_REAL,offsetof(State,attrs.height)},
148 {"text_colour",PROP_TYPE_COLOUR,offsetof(State,attrs.color)},
149 { NULL, 0, 0 },
152 static void
153 state_get_props(State * state, GPtrArray *props)
155 text_get_attributes(state->text,&state->attrs);
156 object_get_props_from_offsets(&state->element.object,
157 state_offsets,props);
160 static void
161 state_set_props(State *state, GPtrArray *props)
163 object_set_props_from_offsets(&state->element.object,
164 state_offsets,props);
165 apply_textattr_properties(props,state->text,"text",&state->attrs);
166 state_update_data(state);
169 static real
170 state_distance_from(State *state, Point *point)
172 DiaObject *obj = &state->element.object;
173 return distance_rectangle_point(&obj->bounding_box, point);
176 static void
177 state_select(State *state, Point *clicked_point,
178 DiaRenderer *interactive_renderer)
180 text_set_cursor(state->text, clicked_point, interactive_renderer);
181 text_grab_focus(state->text, &state->element.object);
182 element_update_handles(&state->element);
185 static ObjectChange*
186 state_move_handle(State *state, Handle *handle,
187 Point *to, ConnectionPoint *cp,
188 HandleMoveReason reason, ModifierKeys modifiers)
190 assert(state!=NULL);
191 assert(handle!=NULL);
192 assert(to!=NULL);
194 assert(handle->id < 8);
196 return NULL;
199 static ObjectChange*
200 state_move(State *state, Point *to)
202 state->element.corner = *to;
203 state_update_data(state);
205 return NULL;
208 static void
209 state_draw(State *state, DiaRenderer *renderer)
211 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
212 Element *elem;
213 real x, y, w, h;
214 Point p1, p2;
216 assert(state != NULL);
217 assert(renderer != NULL);
219 elem = &state->element;
221 x = elem->corner.x;
222 y = elem->corner.y;
223 w = elem->width;
224 h = elem->height;
226 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
227 renderer_ops->set_linewidth(renderer, STATE_LINEWIDTH);
228 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
230 p1.x = x;
231 p1.y = y;
232 p2.x = x + w;
233 p2.y = y + h;
234 renderer_ops->fill_rounded_rect(renderer, &p1, &p2,
235 &state->fill_color, 1.0);
236 renderer_ops->draw_rounded_rect(renderer, &p1, &p2,
237 &state->line_color, 1.0);
239 text_draw(state->text, renderer);
243 static void
244 state_update_data(State *state)
246 real w, h;
248 Element *elem = &state->element;
249 DiaObject *obj = &elem->object;
250 Point p;
252 text_calc_boundingbox(state->text, NULL);
253 w = state->text->max_width + 2*STATE_MARGIN_X;
254 h = state->text->height*state->text->numlines +2*STATE_MARGIN_Y;
255 if (w < STATE_WIDTH)
256 w = STATE_WIDTH;
257 p.x = elem->corner.x + w/2.0;
258 p.y = elem->corner.y + STATE_MARGIN_Y + state->text->ascent;
259 text_set_position(state->text, &p);
262 elem->width = w;
263 elem->height = h;
265 /* Update connections: */
266 state->connections[0].pos = elem->corner;
267 state->connections[1].pos.x = elem->corner.x + elem->width / 2.0;
268 state->connections[1].pos.y = elem->corner.y;
269 state->connections[2].pos.x = elem->corner.x + elem->width;
270 state->connections[2].pos.y = elem->corner.y;
271 state->connections[3].pos.x = elem->corner.x;
272 state->connections[3].pos.y = elem->corner.y + elem->height / 2.0;
273 state->connections[4].pos.x = elem->corner.x + elem->width;
274 state->connections[4].pos.y = elem->corner.y + elem->height / 2.0;
275 state->connections[5].pos.x = elem->corner.x;
276 state->connections[5].pos.y = elem->corner.y + elem->height;
277 state->connections[6].pos.x = elem->corner.x + elem->width / 2.0;
278 state->connections[6].pos.y = elem->corner.y + elem->height;
279 state->connections[7].pos.x = elem->corner.x + elem->width;
280 state->connections[7].pos.y = elem->corner.y + elem->height;
282 state->connections[0].directions = DIR_NORTH|DIR_WEST;
283 state->connections[1].directions = DIR_NORTH;
284 state->connections[2].directions = DIR_NORTH|DIR_EAST;
285 state->connections[3].directions = DIR_WEST;
286 state->connections[4].directions = DIR_EAST;
287 state->connections[5].directions = DIR_SOUTH|DIR_WEST;
288 state->connections[6].directions = DIR_SOUTH;
289 state->connections[7].directions = DIR_SOUTH|DIR_EAST;
291 element_update_boundingbox(elem);
293 obj->position = elem->corner;
295 element_update_handles(elem);
299 static DiaObject *
300 state_create_activity(Point *startpoint,
301 void *user_data,
302 Handle **handle1,
303 Handle **handle2)
305 State *state;
306 Element *elem;
307 DiaObject *obj;
308 Point p;
309 DiaFont *font;
310 int i;
312 state = g_malloc0(sizeof(State));
313 elem = &state->element;
314 obj = &elem->object;
316 obj->type = &activity_type;
317 obj->ops = &state_ops;
318 elem->corner = *startpoint;
319 elem->width = STATE_WIDTH;
320 elem->height = STATE_HEIGHT;
322 state->line_color = attributes_get_foreground();
323 state->fill_color = attributes_get_background();
325 font = dia_font_new_from_style (DIA_FONT_SANS, 0.8);
326 p = *startpoint;
327 p.x += STATE_WIDTH/2.0;
328 p.y += STATE_HEIGHT/2.0;
330 state->text = new_text("", font, 0.8, &p, &color_black, ALIGN_CENTER);
331 text_get_attributes(state->text,&state->attrs);
332 element_init(elem, 8, 8);
334 for (i=0;i<8;i++) {
335 obj->connections[i] = &state->connections[i];
336 state->connections[i].object = obj;
337 state->connections[i].connected = NULL;
339 elem->extra_spacing.border_trans = 0.0;
340 state_update_data(state);
342 for (i=0;i<8;i++) {
343 obj->handles[i]->type = HANDLE_NON_MOVABLE;
346 *handle1 = NULL;
347 *handle2 = NULL;
348 return &state->element.object;;
351 static void
352 state_destroy(State *state)
354 text_destroy(state->text);
356 element_destroy(&state->element);
359 static DiaObject *
360 state_load(ObjectNode obj_node, int version, const char *filename)
362 return object_load_using_properties(&activity_type,
363 obj_node,version,filename);