2006-12-05 David Lodge <dave@cirt.net>
[dia.git] / objects / UML / state_term.c
blob016b784eeb0f9f9fa2e55b8cb03207e8652f3e42
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * State terminal 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 #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 "pixmaps/state_term.xpm"
40 #define NUM_CONNECTIONS 9
42 typedef struct _State State;
43 struct _State {
44 Element element;
46 ConnectionPoint connections[NUM_CONNECTIONS];
48 int is_final;
52 #define STATE_WIDTH 4
53 #define STATE_HEIGHT 3
54 #define STATE_RATIO 1
55 #define STATE_ENDRATIO 1.5
56 #define STATE_LINEWIDTH 0.1
57 #define STATE_MARGIN_X 0.5
58 #define STATE_MARGIN_Y 0.5
60 static real state_distance_from(State *state, Point *point);
61 static void state_select(State *state, Point *clicked_point,
62 DiaRenderer *interactive_renderer);
63 static ObjectChange* state_move_handle(State *state, Handle *handle,
64 Point *to, ConnectionPoint *cp,
65 HandleMoveReason reason, ModifierKeys modifiers);
66 static ObjectChange* state_move(State *state, Point *to);
67 static void state_draw(State *state, DiaRenderer *renderer);
68 static DiaObject *state_create(Point *startpoint,
69 void *user_data,
70 Handle **handle1,
71 Handle **handle2);
72 static void state_destroy(State *state);
73 static DiaObject *state_load(ObjectNode obj_node, int version,
74 const char *filename);
75 static PropDescription *state_describe_props(State *state);
76 static void state_get_props(State *state, GPtrArray *props);
77 static void state_set_props(State *state, GPtrArray *props);
78 static void state_update_data(State *state);
80 void
81 draw_rounded_rectangle(DiaRenderer *renderer, Point p1, Point p2, real radio);
83 static ObjectTypeOps state_type_ops =
85 (CreateFunc) state_create,
86 (LoadFunc) state_load,/*using_properties*/ /* load */
87 (SaveFunc) object_save_using_properties, /* save */
88 (GetDefaultsFunc) NULL,
89 (ApplyDefaultsFunc) NULL
92 DiaObjectType state_term_type =
94 "UML - State Term", /* name */
95 0, /* version */
96 (char **) state_term_xpm, /* pixmap */
98 &state_type_ops /* ops */
101 static ObjectOps state_ops = {
102 (DestroyFunc) state_destroy,
103 (DrawFunc) state_draw,
104 (DistanceFunc) state_distance_from,
105 (SelectFunc) state_select,
106 (CopyFunc) object_copy_using_properties,
107 (MoveFunc) state_move,
108 (MoveHandleFunc) state_move_handle,
109 (GetPropertiesFunc) object_create_props_dialog,
110 (ApplyPropertiesFunc) object_apply_props_from_dialog,
111 (ObjectMenuFunc) NULL,
112 (DescribePropsFunc) state_describe_props,
113 (GetPropsFunc) state_get_props,
114 (SetPropsFunc) state_set_props
117 static PropDescription state_props[] = {
118 ELEMENT_COMMON_PROPERTIES,
119 { "is_final", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE,
120 N_("Is final"), NULL, NULL },
121 PROP_DESC_END
124 static PropDescription *
125 state_describe_props(State *state)
127 if (state_props[0].quark == 0) {
128 prop_desc_list_calculate_quarks(state_props);
130 return state_props;
133 static PropOffset state_offsets[] = {
134 ELEMENT_COMMON_PROPERTIES_OFFSETS,
135 { "is_final", PROP_TYPE_BOOL, offsetof(State, is_final) },
137 { NULL, 0, 0 },
140 static void
141 state_get_props(State * state, GPtrArray *props)
143 object_get_props_from_offsets(&state->element.object,
144 state_offsets,props);
147 static void
148 state_set_props(State *state, GPtrArray *props)
150 object_set_props_from_offsets(&state->element.object,
151 state_offsets,props);
152 state_update_data(state);
155 static real
156 state_distance_from(State *state, Point *point)
158 DiaObject *obj = &state->element.object;
159 return distance_rectangle_point(&obj->bounding_box, point);
162 static void
163 state_select(State *state, Point *clicked_point,
164 DiaRenderer *interactive_renderer)
166 element_update_handles(&state->element);
169 static ObjectChange*
170 state_move_handle(State *state, Handle *handle,
171 Point *to, ConnectionPoint *cp,
172 HandleMoveReason reason, ModifierKeys modifiers)
174 assert(state!=NULL);
175 assert(handle!=NULL);
176 assert(to!=NULL);
178 assert(handle->id < 8);
180 return NULL;
183 static ObjectChange*
184 state_move(State *state, Point *to)
186 state->element.corner = *to;
187 state_update_data(state);
189 return NULL;
192 static void
193 state_draw(State *state, DiaRenderer *renderer)
195 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
196 Element *elem;
197 real x, y, w, h, r;
198 Point p1;
200 assert(state != NULL);
201 assert(renderer != NULL);
203 elem = &state->element;
205 x = elem->corner.x;
206 y = elem->corner.y;
207 w = elem->width;
208 h = elem->height;
210 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
211 renderer_ops->set_linewidth(renderer, STATE_LINEWIDTH);
212 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
214 p1.x = x + w/2;
215 p1.y = y + h/2;
216 if (state->is_final==1) {
217 r = STATE_ENDRATIO;
218 renderer_ops->fill_ellipse(renderer,
219 &p1,
220 r, r,
221 &color_white);
223 renderer_ops->draw_ellipse(renderer,
224 &p1,
225 r, r,
226 &color_black);
228 r = STATE_RATIO;
229 renderer_ops->fill_ellipse(renderer,
230 &p1,
231 r, r,
232 &color_black);
236 static void
237 state_update_data(State *state)
239 real w, h;
241 Element *elem = &state->element;
242 DiaObject *obj = &elem->object;
244 w = h = (state->is_final) ? STATE_ENDRATIO: STATE_RATIO;
246 elem->width = w;
247 elem->height = h;
249 /* Update connections: */
250 element_update_connections_rectangle(elem, state->connections);
252 element_update_boundingbox(elem);
254 obj->position = elem->corner;
256 element_update_handles(elem);
259 static DiaObject *
260 state_create(Point *startpoint,
261 void *user_data,
262 Handle **handle1,
263 Handle **handle2)
265 State *state;
266 Element *elem;
267 DiaObject *obj;
268 Point p;
269 int i;
271 state = g_malloc0(sizeof(State));
272 elem = &state->element;
273 obj = &elem->object;
275 obj->type = &state_term_type;
276 obj->ops = &state_ops;
277 elem->corner = *startpoint;
278 elem->width = STATE_WIDTH;
279 elem->height = STATE_HEIGHT;
281 p = *startpoint;
282 p.x += STATE_WIDTH/2.0;
283 p.y += STATE_HEIGHT/2.0;
285 state->is_final = 0;
286 element_init(elem, 8, NUM_CONNECTIONS);
288 for (i=0;i<NUM_CONNECTIONS;i++) {
289 obj->connections[i] = &state->connections[i];
290 state->connections[i].object = obj;
291 state->connections[i].connected = NULL;
293 state->connections[8].flags = CP_FLAGS_MAIN;
294 elem->extra_spacing.border_trans = 0.0;
295 state_update_data(state);
297 for (i=0;i<8;i++) {
298 obj->handles[i]->type = HANDLE_NON_MOVABLE;
301 *handle1 = NULL;
302 *handle2 = NULL;
303 return &state->element.object;
306 static void
307 state_destroy(State *state)
309 element_destroy(&state->element);
312 static DiaObject *
313 state_load(ObjectNode obj_node, int version, const char *filename)
315 return object_load_using_properties(&state_term_type,
316 obj_node,version,filename);