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.
33 #include "orth_conn.h"
34 #include "connectionpoint.h"
35 #include "diarenderer.h"
36 #include "attributes.h"
39 #include "properties.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
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
,
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
,
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
,
79 static void arc_set_props(Arc
*arc
,
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. */
96 (char **) vector_xpm
, /* pixmap */
98 &arc_type_ops
/* ops */
101 DiaObjectType grafcet_arc_type
=
103 "GRAFCET - Arc", /* name */
105 (char **) vector_xpm
, /* pixmap */
107 &arc_type_ops
/* ops */
110 static ObjectOps arc_ops
= {
111 (DestroyFunc
) arc_destroy
,
113 (DistanceFunc
) arc_distance_from
,
114 (SelectFunc
) arc_select
,
115 (CopyFunc
) object_copy_using_properties
,
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
},
133 static PropDescription
*
134 arc_describe_props(Arc
*arc
)
136 if (arc_props
[0].quark
== 0) {
137 prop_desc_list_calculate_quarks(arc_props
);
142 static PropOffset arc_offsets
[] = {
143 ORTHCONN_COMMON_PROPERTIES_OFFSETS
,
144 { "uparrow",PROP_TYPE_BOOL
,offsetof(Arc
,uparrow
)},
149 arc_get_props(Arc
*arc
, GPtrArray
*props
)
151 object_get_props_from_offsets(&arc
->orth
.object
,
156 arc_set_props(Arc
*arc
, GPtrArray
*props
)
158 object_set_props_from_offsets(&arc
->orth
.object
,
160 arc_update_data(arc
);
164 arc_distance_from(Arc
*arc
, Point
*point
)
166 OrthConn
*orth
= &arc
->orth
;
167 return orthconn_distance_from(orth
, point
, ARC_LINE_WIDTH
);
171 arc_select(Arc
*arc
, Point
*clicked_point
,
172 DiaRenderer
*interactive_renderer
)
174 orthconn_update_data(&arc
->orth
);
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
);
191 arc_move(Arc
*arc
, Point
*to
)
193 ObjectChange
*change
;
195 change
= orthconn_move(&arc
->orth
, to
);
196 arc_update_data(arc
);
202 arc_draw(Arc
*arc
, DiaRenderer
*renderer
)
204 DiaRendererClass
*renderer_ops
= DIA_RENDERER_GET_CLASS (renderer
);
205 OrthConn
*orth
= &arc
->orth
;
209 points
= &orth
->points
[0];
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
);
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 */
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
,
229 ARC_ARROW_LENGTH
, ARC_ARROW_WIDTH
,
231 &color_black
, &color_white
);
238 arc_create(Point
*startpoint
,
247 arc
= g_malloc0(sizeof(Arc
));
251 obj
->type
= &grafcet_arc_type
;
254 orthconn_init(orth
, startpoint
);
258 arc_update_data(arc
);
260 *handle1
= orth
->handles
[0];
261 *handle2
= orth
->handles
[orth
->numhandles
-1];
262 return &arc
->orth
.object
;
266 arc_destroy(Arc
*arc
)
268 orthconn_destroy(&arc
->orth
);
272 arc_update_data(Arc
*arc
)
274 OrthConn
*orth
= &arc
->orth
;
275 PolyBBExtras
*extra
= &orth
->extra_spacing
;
277 orthconn_update_data(&arc
->orth
);
282 extra
->end_trans
= ARC_LINE_WIDTH
/2.0;
284 extra
->middle_trans
= (ARC_LINE_WIDTH
+ ARC_ARROW_WIDTH
)/2.0;
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
);
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
);
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
= {
319 sizeof(object_menu_items
)/sizeof(DiaMenuItem
),
325 arc_get_object_menu(Arc
*arc
, Point
*clickedpoint
)
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]);
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
);
345 /* In old objects with no autorouting, set it to false. */
346 attr
= object_find_attribute(obj_node
, "autorouting");
348 ((OrthConn
*)obj
)->autorouting
= FALSE
;