1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* DO NOT USE THIS OBJECT AS A BASIS FOR A NEW OBJECT. */
31 #include "orth_conn.h"
32 #include "diarenderer.h"
33 #include "attributes.h"
35 #include "properties.h"
37 #include "pixmaps/participation.xpm"
39 typedef struct _Participation Participation
;
41 struct _Participation
{
48 #define PARTICIPATION_WIDTH 0.1
49 #define PARTICIPATION_DASHLEN 0.4
50 #define PARTICIPATION_FONTHEIGHT 0.8
51 #define TOTAL_SEPARATION 0.25
53 static real
participation_distance_from(Participation
*dep
, Point
*point
);
54 static void participation_select(Participation
*dep
, Point
*clicked_point
,
55 DiaRenderer
*interactive_renderer
);
56 static ObjectChange
* participation_move_handle(Participation
*dep
, Handle
*handle
,
57 Point
*to
, ConnectionPoint
*cp
,
58 HandleMoveReason reason
, ModifierKeys modifiers
);
59 static ObjectChange
* participation_move(Participation
*dep
, Point
*to
);
60 static void participation_draw(Participation
*dep
, DiaRenderer
*renderer
);
61 static DiaObject
*participation_create(Point
*startpoint
,
65 static DiaObject
*participation_copy(Participation
*dep
);
66 static void participation_save(Participation
*dep
, ObjectNode obj_node
,
67 const char *filename
);
68 static DiaObject
*participation_load(ObjectNode obj_node
, int version
,
69 const char *filename
);
70 static void participation_update_data(Participation
*dep
);
71 static PropDescription
*
72 participation_describe_props(Participation
*participation
);
74 participation_get_props(Participation
*participation
, GPtrArray
*props
);
76 participation_set_props(Participation
*participation
, GPtrArray
*props
);
77 static DiaMenu
*participation_get_object_menu(Participation
*participation
,
80 static ObjectTypeOps participation_type_ops
=
82 (CreateFunc
) participation_create
,
83 (LoadFunc
) participation_load
,
84 (SaveFunc
) participation_save
87 DiaObjectType participation_type
=
89 "ER - Participation", /* name */
90 /* Version 0 had no autorouting and so shouldn't have it set by default. */
92 (char **) participation_xpm
, /* pixmap */
94 &participation_type_ops
/* ops */
97 static ObjectOps participation_ops
= {
98 (DestroyFunc
) orthconn_destroy
,
99 (DrawFunc
) participation_draw
,
100 (DistanceFunc
) participation_distance_from
,
101 (SelectFunc
) participation_select
,
102 (CopyFunc
) participation_copy
,
103 (MoveFunc
) participation_move
,
104 (MoveHandleFunc
) participation_move_handle
,
105 (GetPropertiesFunc
) object_create_props_dialog
,
106 (ApplyPropertiesFunc
) object_apply_props_from_dialog
,
107 (ObjectMenuFunc
) participation_get_object_menu
,
108 (DescribePropsFunc
) participation_describe_props
,
109 (GetPropsFunc
) participation_get_props
,
110 (SetPropsFunc
) participation_set_props
113 static PropDescription participation_props
[] = {
114 ORTHCONN_COMMON_PROPERTIES
,
115 { "total", PROP_TYPE_BOOL
, PROP_FLAG_VISIBLE
,
116 N_("Total:"), NULL
, NULL
},
120 static PropDescription
*
121 participation_describe_props(Participation
*participation
)
123 if (participation_props
[0].quark
== 0)
124 prop_desc_list_calculate_quarks(participation_props
);
125 return participation_props
;
128 static PropOffset participation_offsets
[] = {
129 ORTHCONN_COMMON_PROPERTIES_OFFSETS
,
130 { "total", PROP_TYPE_BOOL
, offsetof(Participation
, total
) },
136 participation_get_props(Participation
*participation
, GPtrArray
*props
)
138 object_get_props_from_offsets(&participation
->orth
.object
,
139 participation_offsets
, props
);
143 participation_set_props(Participation
*participation
, GPtrArray
*props
)
145 object_set_props_from_offsets(&participation
->orth
.object
,
146 participation_offsets
, props
);
147 participation_update_data(participation
);
152 participation_distance_from(Participation
*participation
, Point
*point
)
154 OrthConn
*orth
= &participation
->orth
;
155 return orthconn_distance_from(orth
, point
, PARTICIPATION_WIDTH
);
159 participation_select(Participation
*participation
, Point
*clicked_point
,
160 DiaRenderer
*interactive_renderer
)
162 orthconn_update_data(&participation
->orth
);
166 participation_move_handle(Participation
*participation
, Handle
*handle
,
167 Point
*to
, ConnectionPoint
*cp
,
168 HandleMoveReason reason
, ModifierKeys modifiers
)
170 ObjectChange
*change
;
171 assert(participation
!=NULL
);
172 assert(handle
!=NULL
);
175 change
= orthconn_move_handle(&participation
->orth
, handle
, to
, cp
,
177 participation_update_data(participation
);
183 participation_move(Participation
*participation
, Point
*to
)
185 ObjectChange
*change
;
187 change
= orthconn_move(&participation
->orth
, to
);
188 participation_update_data(participation
);
194 participation_draw(Participation
*participation
, DiaRenderer
*renderer
)
196 DiaRendererClass
*renderer_ops
= DIA_RENDERER_GET_CLASS (renderer
);
197 OrthConn
*orth
= &participation
->orth
;
202 real last_left
, last_right
;
204 points
= &orth
->points
[0];
210 renderer_ops
->set_linewidth(renderer
, PARTICIPATION_WIDTH
);
211 renderer_ops
->set_linestyle(renderer
, LINESTYLE_SOLID
);
212 renderer_ops
->set_linejoin(renderer
, LINEJOIN_MITER
);
213 renderer_ops
->set_linecaps(renderer
, LINECAPS_BUTT
);
215 if (participation
->total
) {
216 left_points
= g_new0(Point
, n
);
217 right_points
= g_new0(Point
, n
);
218 for(i
= 0; i
< n
- 1; i
++) {
219 if(orth
->orientation
[i
] == HORIZONTAL
) { /* HORIZONTAL */
220 if (points
[i
].x
< points
[i
+1].x
) { /* RIGHT */
221 left_points
[i
].x
= points
[i
].x
+ last_left
;
222 left_points
[i
].y
= points
[i
].y
- TOTAL_SEPARATION
/ 2.0;
223 last_left
= - TOTAL_SEPARATION
/2.0;
224 right_points
[i
].x
= points
[i
].x
+ last_right
;
225 right_points
[i
].y
= points
[i
].y
+ TOTAL_SEPARATION
/ 2.0;
226 last_right
= TOTAL_SEPARATION
/2.0;
228 left_points
[i
].x
= points
[i
].x
+ last_left
;
229 left_points
[i
].y
= points
[i
].y
+ TOTAL_SEPARATION
/ 2.0;
230 last_left
= TOTAL_SEPARATION
/2.0;
231 right_points
[i
].x
= points
[i
].x
+ last_right
;
232 right_points
[i
].y
= points
[i
].y
- TOTAL_SEPARATION
/ 2.0;
233 last_right
= - TOTAL_SEPARATION
/2.0;
235 } else { /* VERTICAL */
236 if (points
[i
].y
< points
[i
+1].y
) { /* DOWN */
237 left_points
[i
].x
= points
[i
].x
+ TOTAL_SEPARATION
/ 2.0;
238 left_points
[i
].y
= points
[i
].y
+ last_left
;
239 last_left
= TOTAL_SEPARATION
/2.0;
240 right_points
[i
].x
= points
[i
].x
- TOTAL_SEPARATION
/ 2.0;
241 right_points
[i
].y
= points
[i
].y
+ last_right
;
242 last_right
= - TOTAL_SEPARATION
/2.0;
244 left_points
[i
].x
= points
[i
].x
- TOTAL_SEPARATION
/ 2.0;
245 left_points
[i
].y
= points
[i
].y
+ last_left
;
246 last_left
= - TOTAL_SEPARATION
/2.0;
247 right_points
[i
].x
= points
[i
].x
+ TOTAL_SEPARATION
/ 2.0;
248 right_points
[i
].y
= points
[i
].y
+ last_right
;
249 last_right
= TOTAL_SEPARATION
/2.0;
253 if(orth
->orientation
[i
-1] == HORIZONTAL
) { /* HORIZONTAL */
254 left_points
[i
].x
= points
[i
].x
;
255 left_points
[i
].y
= points
[i
].y
+ last_left
;
256 right_points
[i
].x
= points
[i
].x
;
257 right_points
[i
].y
= points
[i
].y
+ last_right
;
258 } else { /* VERTICAL */
259 left_points
[i
].x
= points
[i
].x
+ last_left
;
260 left_points
[i
].y
= points
[i
].y
;
261 right_points
[i
].x
= points
[i
].x
+ last_right
;
262 right_points
[i
].y
= points
[i
].y
;
265 renderer_ops
->draw_polyline(renderer
, left_points
, n
, &color_black
);
266 renderer_ops
->draw_polyline(renderer
, right_points
, n
, &color_black
);
268 g_free(right_points
);
270 renderer_ops
->draw_polyline(renderer
, points
, n
, &color_black
);
275 participation_update_data(Participation
*participation
)
277 OrthConn
*orth
= &participation
->orth
;
278 PolyBBExtras
*extra
= &orth
->extra_spacing
;
281 orthconn_update_data(orth
);
283 if (participation
->total
) {
284 extra_width
= TOTAL_SEPARATION
/2.0;
288 extra
->middle_trans
=
292 extra
->end_long
= PARTICIPATION_WIDTH
/2.0 + extra_width
;
294 orthconn_update_boundingbox(orth
);
298 participation_create(Point
*startpoint
,
303 Participation
*participation
;
307 participation
= g_malloc0(sizeof(Participation
));
308 orth
= &participation
->orth
;
311 obj
->type
= &participation_type
;
313 obj
->ops
= &participation_ops
;
315 orthconn_init(orth
, startpoint
);
317 participation_update_data(participation
);
319 participation
->total
= FALSE
;
321 *handle1
= orth
->handles
[0];
322 *handle2
= orth
->handles
[orth
->numpoints
-2];
324 return &participation
->orth
.object
;
328 participation_copy(Participation
*participation
)
330 Participation
*newparticipation
;
331 OrthConn
*orth
, *neworth
;
334 orth
= &participation
->orth
;
336 newparticipation
= g_malloc0(sizeof(Participation
));
337 neworth
= &newparticipation
->orth
;
338 newobj
= &neworth
->object
;
340 orthconn_copy(orth
, neworth
);
342 newparticipation
->total
= participation
->total
;
344 participation_update_data(newparticipation
);
346 return &newparticipation
->orth
.object
;
351 participation_save(Participation
*participation
, ObjectNode obj_node
,
352 const char *filename
)
354 orthconn_save(&participation
->orth
, obj_node
);
356 data_add_boolean(new_attribute(obj_node
, "total"),
357 participation
->total
);
361 participation_load(ObjectNode obj_node
, int version
, const char *filename
)
364 Participation
*participation
;
368 participation
= g_new0(Participation
, 1);
370 orth
= &participation
->orth
;
373 obj
->type
= &participation_type
;
374 obj
->ops
= &participation_ops
;
376 orthconn_load(orth
, obj_node
);
378 attr
= object_find_attribute(obj_node
, "total");
380 participation
->total
= data_boolean(attribute_first_data(attr
));
382 participation_update_data(participation
);
384 return &participation
->orth
.object
;
387 static ObjectChange
*
388 participation_add_segment_callback(DiaObject
*obj
, Point
*clicked
, gpointer data
)
390 ObjectChange
*change
;
391 change
= orthconn_add_segment((OrthConn
*)obj
, clicked
);
392 participation_update_data((Participation
*)obj
);
396 static ObjectChange
*
397 participation_delete_segment_callback(DiaObject
*obj
, Point
*clicked
, gpointer data
)
399 ObjectChange
*change
;
400 change
= orthconn_delete_segment((OrthConn
*)obj
, clicked
);
401 participation_update_data((Participation
*)obj
);
405 static DiaMenuItem object_menu_items
[] = {
406 { N_("Add segment"), participation_add_segment_callback
, NULL
, 1 },
407 { N_("Delete segment"), participation_delete_segment_callback
, NULL
, 1 },
408 ORTHCONN_COMMON_MENUS
,
411 static DiaMenu object_menu
= {
413 sizeof(object_menu_items
)/sizeof(DiaMenuItem
),
419 participation_get_object_menu(Participation
*participation
, Point
*clickedpoint
)
423 orth
= &participation
->orth
;
424 /* Set entries sensitive/selected etc here */
425 object_menu_items
[0].active
= orthconn_can_add_segment(orth
, clickedpoint
);
426 object_menu_items
[1].active
= orthconn_can_delete_segment(orth
, clickedpoint
);
427 orthconn_update_object_menu(orth
, clickedpoint
, &object_menu_items
[2]);