2006-12-05 David Lodge <dave@cirt.net>
[dia.git] / objects / GRAFCET / vector.c
blobc5c790f819d0854706edeecf4d0c6054773b4c99
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * GRAFCET charts support for Dia
5 * Copyright (C) 2000 Cyrille Chepelov
7 * This file is derived from objects/standard/zigzag.c
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <assert.h>
29 #include <math.h>
31 #include "intl.h"
32 #include "object.h"
33 #include "orth_conn.h"
34 #include "connectionpoint.h"
35 #include "diarenderer.h"
36 #include "attributes.h"
37 #include "widgets.h"
38 #include "message.h"
39 #include "properties.h"
41 #include "grafcet.h"
42 #include "pixmaps/vector.xpm"
44 #define ARC_LINE_WIDTH (GRAFCET_GENERAL_LINE_WIDTH)
45 #define ARC_ARROW_LENGTH .8
46 #define ARC_ARROW_WIDTH .6
47 #define ARC_ARROW_TYPE ARROW_FILLED_TRIANGLE
49 #define HANDLE_MIDDLE HANDLE_CUSTOM1
51 typedef struct _Arc {
52 OrthConn orth;
54 gboolean uparrow;
55 } Arc;
57 static ObjectChange* arc_move_handle(Arc *arc, Handle *handle,
58 Point *to, ConnectionPoint *cp,
59 HandleMoveReason reason, ModifierKeys modifiers);
60 static ObjectChange* arc_move(Arc *arc, Point *to);
61 static void arc_select(Arc *arc, Point *clicked_point,
62 DiaRenderer *interactive_renderer);
63 static void arc_draw(Arc *arc, DiaRenderer *renderer);
64 static DiaObject *arc_create(Point *startpoint,
65 void *user_data,
66 Handle **handle1,
67 Handle **handle2);
68 static real arc_distance_from(Arc *arc, Point *point);
69 static void arc_update_data(Arc *arc);
70 static void arc_destroy(Arc *arc);
71 static DiaMenu *arc_get_object_menu(Arc *arc,
72 Point *clickedpoint);
74 static DiaObject *arc_load(ObjectNode obj_node, int version,
75 const char *filename);
76 static PropDescription *arc_describe_props(Arc *arc);
77 static void arc_get_props(Arc *arc,
78 GPtrArray *props);
79 static void arc_set_props(Arc *arc,
80 GPtrArray *props);
82 static ObjectTypeOps arc_type_ops =
84 (CreateFunc)arc_create, /* create */
85 (LoadFunc) arc_load,/* using_properties */ /* load */
86 (SaveFunc) object_save_using_properties,
87 (GetDefaultsFunc) NULL,
88 (ApplyDefaultsFunc) NULL,
91 DiaObjectType old_arc_type =
93 "GRAFCET - Vector", /* name */
94 /* Version 0 had no autorouting and so shouldn't have it set by default. */
95 1, /* version */
96 (char **) vector_xpm, /* pixmap */
98 &arc_type_ops /* ops */
101 DiaObjectType grafcet_arc_type =
103 "GRAFCET - Arc", /* name */
104 0, /* version */
105 (char **) vector_xpm, /* pixmap */
107 &arc_type_ops /* ops */
110 static ObjectOps arc_ops = {
111 (DestroyFunc) arc_destroy,
112 (DrawFunc) arc_draw,
113 (DistanceFunc) arc_distance_from,
114 (SelectFunc) arc_select,
115 (CopyFunc) object_copy_using_properties,
116 (MoveFunc) arc_move,
117 (MoveHandleFunc) arc_move_handle,
118 (GetPropertiesFunc) object_create_props_dialog,
119 (ApplyPropertiesFunc) object_apply_props_from_dialog,
120 (ObjectMenuFunc) arc_get_object_menu,
121 (DescribePropsFunc) arc_describe_props,
122 (GetPropsFunc) arc_get_props,
123 (SetPropsFunc) arc_set_props
126 static PropDescription arc_props[] = {
127 ORTHCONN_COMMON_PROPERTIES,
128 { "uparrow",PROP_TYPE_BOOL,PROP_FLAG_VISIBLE,
129 N_("Draw arrow heads on upward arcs:"),NULL},
130 PROP_DESC_END
133 static PropDescription *
134 arc_describe_props(Arc *arc)
136 if (arc_props[0].quark == 0) {
137 prop_desc_list_calculate_quarks(arc_props);
139 return arc_props;
142 static PropOffset arc_offsets[] = {
143 ORTHCONN_COMMON_PROPERTIES_OFFSETS,
144 { "uparrow",PROP_TYPE_BOOL,offsetof(Arc,uparrow)},
145 { NULL,0,0 }
148 static void
149 arc_get_props(Arc *arc, GPtrArray *props)
151 object_get_props_from_offsets(&arc->orth.object,
152 arc_offsets,props);
155 static void
156 arc_set_props(Arc *arc, GPtrArray *props)
158 object_set_props_from_offsets(&arc->orth.object,
159 arc_offsets,props);
160 arc_update_data(arc);
163 static real
164 arc_distance_from(Arc *arc, Point *point)
166 OrthConn *orth = &arc->orth;
167 return orthconn_distance_from(orth, point, ARC_LINE_WIDTH);
170 static void
171 arc_select(Arc *arc, Point *clicked_point,
172 DiaRenderer *interactive_renderer)
174 orthconn_update_data(&arc->orth);
177 static ObjectChange*
178 arc_move_handle(Arc *arc, Handle *handle,
179 Point *to, ConnectionPoint *cp,
180 HandleMoveReason reason, ModifierKeys modifiers)
182 ObjectChange *change;
183 change = orthconn_move_handle(&arc->orth, handle, to, cp, reason, modifiers);
184 arc_update_data(arc);
186 return change;
190 static ObjectChange*
191 arc_move(Arc *arc, Point *to)
193 ObjectChange *change;
195 change = orthconn_move(&arc->orth, to);
196 arc_update_data(arc);
198 return change;
201 static void
202 arc_draw(Arc *arc, DiaRenderer *renderer)
204 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
205 OrthConn *orth = &arc->orth;
206 Point *points;
207 int n,i;
209 points = &orth->points[0];
210 n = orth->numpoints;
212 renderer_ops->set_linewidth(renderer, ARC_LINE_WIDTH);
213 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
214 renderer_ops->set_linejoin(renderer, LINEJOIN_MITER);
215 renderer_ops->set_linecaps(renderer, LINECAPS_BUTT);
217 renderer_ops->draw_polyline(renderer, points, n, &color_black);
219 if (arc->uparrow) {
220 for (i=0;i<n-1; i++) {
221 if ((points[i].y > points[i+1].y) &&
222 (ABS(points[i+1].y-points[i].y) > 5 * ARC_ARROW_LENGTH)) {
223 /* Draw an arrow on the middle of the line */
224 Point m;
225 m.x = points[i].x; /* == points[i+1].x */
226 m.y = .5 * (points[i].y + points[i+1].y) - (.5 * ARC_ARROW_LENGTH);
227 arrow_draw(renderer, ARC_ARROW_TYPE,
228 &m,&points[i],
229 ARC_ARROW_LENGTH, ARC_ARROW_WIDTH,
230 ARC_LINE_WIDTH,
231 &color_black, &color_white);
237 static DiaObject *
238 arc_create(Point *startpoint,
239 void *user_data,
240 Handle **handle1,
241 Handle **handle2)
243 Arc *arc;
244 OrthConn *orth;
245 DiaObject *obj;
247 arc = g_malloc0(sizeof(Arc));
248 orth = &arc->orth;
249 obj = &orth->object;
251 obj->type = &grafcet_arc_type;
252 obj->ops = &arc_ops;
254 orthconn_init(orth, startpoint);
257 arc->uparrow = TRUE;
258 arc_update_data(arc);
260 *handle1 = orth->handles[0];
261 *handle2 = orth->handles[orth->numhandles-1];
262 return &arc->orth.object;
265 static void
266 arc_destroy(Arc *arc)
268 orthconn_destroy(&arc->orth);
271 static void
272 arc_update_data(Arc *arc)
274 OrthConn *orth = &arc->orth;
275 PolyBBExtras *extra = &orth->extra_spacing;
277 orthconn_update_data(&arc->orth);
279 extra->start_trans =
280 extra->start_long =
281 extra->end_long =
282 extra->end_trans = ARC_LINE_WIDTH/2.0;
283 if (arc->uparrow) {
284 extra->middle_trans = (ARC_LINE_WIDTH + ARC_ARROW_WIDTH)/2.0;
285 } else {
286 extra->middle_trans = ARC_LINE_WIDTH/2.0;
289 orthconn_update_boundingbox(orth);
293 static ObjectChange *
294 arc_add_segment_callback(DiaObject *obj, Point *clicked, gpointer data)
296 ObjectChange *change;
297 change = orthconn_add_segment((OrthConn *)obj, clicked);
298 arc_update_data((Arc *)obj);
299 return change;
302 static ObjectChange *
303 arc_delete_segment_callback(DiaObject *obj, Point *clicked, gpointer data)
305 ObjectChange *change;
306 change = orthconn_delete_segment((OrthConn *)obj, clicked);
307 arc_update_data((Arc *)obj);
308 return change;
311 static DiaMenuItem object_menu_items[] = {
312 { N_("Add segment"), arc_add_segment_callback, NULL, 1 },
313 { N_("Delete segment"), arc_delete_segment_callback, NULL, 1 },
314 ORTHCONN_COMMON_MENUS,
317 static DiaMenu object_menu = {
318 "Arc",
319 sizeof(object_menu_items)/sizeof(DiaMenuItem),
320 object_menu_items,
321 NULL
324 static DiaMenu *
325 arc_get_object_menu(Arc *arc, Point *clickedpoint)
327 OrthConn *orth;
329 orth = &arc->orth;
330 /* Set entries sensitive/selected etc here */
331 object_menu_items[0].active = orthconn_can_add_segment(orth, clickedpoint);
332 object_menu_items[1].active = orthconn_can_delete_segment(orth, clickedpoint);
333 orthconn_update_object_menu(orth, clickedpoint, &object_menu_items[2]);
334 return &object_menu;
338 static DiaObject *
339 arc_load(ObjectNode obj_node, int version, const char *filename)
341 DiaObject *obj = object_load_using_properties(&grafcet_arc_type,
342 obj_node,version,filename);
343 if (version == 0) {
344 AttributeNode attr;
345 /* In old objects with no autorouting, set it to false. */
346 attr = object_find_attribute(obj_node, "autorouting");
347 if (attr == NULL)
348 ((OrthConn*)obj)->autorouting = FALSE;
350 return obj;