Line data Source code
1 : /* File: pencil_relationship_1d_layouter.c; Copyright and License: see below */
2 :
3 : #include "pencil_relationship_1d_layouter.h"
4 : #include "u8/u8_trace.h"
5 : #include <pango/pangocairo.h>
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <math.h>
9 : #include <stdint.h>
10 :
11 0 : void pencil_relationship_1d_layouter_init( pencil_relationship_1d_layouter_t *this_,
12 : layout_visible_set_t *layout_data,
13 : const data_profile_part_t *profile,
14 : const pencil_size_t *pencil_size )
15 : {
16 0 : U8_TRACE_BEGIN();
17 0 : assert( NULL != layout_data );
18 0 : assert( NULL != profile );
19 0 : assert( NULL != pencil_size );
20 :
21 0 : (*this_).layout_data = layout_data;
22 0 : (*this_).profile = profile;
23 0 : (*this_).pencil_size = pencil_size;
24 :
25 0 : pencil_relationship_painter_init( &((*this_).relationship_painter) );
26 :
27 0 : U8_TRACE_END();
28 0 : }
29 :
30 0 : void pencil_relationship_1d_layouter_destroy( pencil_relationship_1d_layouter_t *this_ )
31 : {
32 0 : U8_TRACE_BEGIN();
33 :
34 0 : pencil_relationship_painter_destroy( &((*this_).relationship_painter) );
35 :
36 0 : U8_TRACE_END();
37 0 : }
38 :
39 0 : void pencil_relationship_1d_layouter_private_make_all_visible ( pencil_relationship_1d_layouter_t *this_ )
40 : {
41 0 : U8_TRACE_BEGIN();
42 :
43 : /* determine visibility */
44 0 : const uint32_t count_relations = layout_visible_set_get_relationship_count ( (*this_).layout_data );
45 0 : for ( uint32_t index = 0; index < count_relations; index ++ )
46 : {
47 0 : layout_relationship_t *const the_relation = layout_visible_set_get_relationship_ptr ( (*this_).layout_data, index );
48 0 : const layout_visible_classifier_t *const from_layout = layout_relationship_get_from_classifier_ptr ( the_relation );
49 0 : const layout_visible_classifier_t *const to_layout = layout_relationship_get_to_classifier_ptr ( the_relation );
50 0 : assert( from_layout != NULL );
51 0 : assert( to_layout != NULL );
52 0 : const data_visible_classifier_t *const from_data = layout_visible_classifier_get_data_const( from_layout );
53 0 : const data_visible_classifier_t *const to_data = layout_visible_classifier_get_data_const( to_layout );
54 0 : const data_diagramelement_t *const from_diagele = data_visible_classifier_get_diagramelement_const( from_data );
55 0 : const data_diagramelement_t *const to_diagele = data_visible_classifier_get_diagramelement_const( to_data );
56 0 : const data_diagramelement_flag_t from_flags = data_diagramelement_get_display_flags ( from_diagele );
57 0 : const data_diagramelement_flag_t to_flags = data_diagramelement_get_display_flags ( to_diagele );
58 0 : if (( 0 != ( DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT & from_flags ))
59 0 : || ( 0 != ( DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT & to_flags )))
60 : {
61 0 : layout_relationship_set_visibility ( the_relation, PENCIL_VISIBILITY_GRAY_OUT );
62 : }
63 : else
64 : {
65 0 : layout_relationship_set_visibility ( the_relation, PENCIL_VISIBILITY_SHOW );
66 : }
67 : }
68 :
69 0 : U8_TRACE_END();
70 0 : }
71 :
72 0 : void pencil_relationship_1d_layouter_layout_for_sequence( pencil_relationship_1d_layouter_t *this_ )
73 : {
74 0 : U8_TRACE_BEGIN();
75 :
76 0 : pencil_relationship_1d_layouter_private_make_all_visible( this_ );
77 :
78 : /* get draw area */
79 : const layout_diagram_t *const diagram_layout
80 0 : = layout_visible_set_get_diagram_const( (*this_).layout_data );
81 : const geometry_rectangle_t *const diagram_draw_area
82 0 : = layout_diagram_get_draw_area_const( diagram_layout );
83 :
84 : /* layout the relationships */
85 : const uint32_t count_relations
86 0 : = layout_visible_set_get_relationship_count( (*this_).layout_data );
87 0 : U8_TRACE_INFO_INT( "count_relations:", count_relations );
88 0 : for ( uint32_t index = 0; index < count_relations; index ++ )
89 : {
90 : /* get the relationship to layout */
91 : layout_relationship_t *const the_relationship
92 0 : = layout_visible_set_get_relationship_ptr( (*this_).layout_data, index );
93 :
94 : /* adjust visibility */
95 0 : if ( ( NULL == layout_relationship_get_from_feature_ptr( the_relationship ) )
96 0 : && ( NULL == layout_relationship_get_to_feature_ptr( the_relationship ) ) )
97 : {
98 : /* this is a globally visible relation, not local/scenario-based */
99 0 : layout_visible_set_set_relationship_visibility( (*this_).layout_data, index, PENCIL_VISIBILITY_IMPLICIT );
100 : }
101 :
102 : /* calculate layout */
103 : {
104 : /* determine y-coordinate */
105 : const data_relationship_t *const the_relationdata
106 0 : = layout_relationship_get_data_const( the_relationship );
107 0 : int32_t list_order = data_relationship_get_list_order( the_relationdata );
108 0 : const double y_value_rel = (list_order/((double)UINT32_MAX))+0.5;
109 0 : const double draw_top = geometry_rectangle_get_top(diagram_draw_area);
110 0 : const double draw_bottom = geometry_rectangle_get_bottom(diagram_draw_area);
111 0 : const double y_value = ( (draw_bottom - draw_top) * y_value_rel ) + draw_top;
112 :
113 : /* get source and destination rectangles */
114 : const geometry_rectangle_t *const source_rect
115 0 : = layout_relationship_get_from_box_const ( the_relationship );
116 : const geometry_rectangle_t *const dest_rect
117 0 : = layout_relationship_get_to_box_const ( the_relationship );
118 :
119 : /* calculate coordinates */
120 0 : const double src_left = geometry_rectangle_get_left(source_rect);
121 0 : const double src_center_x = geometry_rectangle_get_center_x(source_rect);
122 0 : const double src_right = geometry_rectangle_get_right(source_rect);
123 0 : const double src_top = geometry_rectangle_get_top(source_rect);
124 : /*const double src_center_y = geometry_rectangle_get_center_y(source_rect);*/
125 0 : const double src_bottom = geometry_rectangle_get_bottom(source_rect);
126 :
127 0 : const double dst_left = geometry_rectangle_get_left(dest_rect);
128 0 : const double dst_center_x = geometry_rectangle_get_center_x(dest_rect);
129 0 : const double dst_right = geometry_rectangle_get_right(dest_rect);
130 0 : const double dst_top = geometry_rectangle_get_top(dest_rect);
131 : /*const double dst_center_y = geometry_rectangle_get_center_y(dest_rect);*/
132 0 : const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
133 :
134 : /* is interaction relation */
135 : const data_relationship_type_t rel_type
136 0 : = data_relationship_get_main_type( the_relationdata );
137 0 : const bool is_interaction
138 : = ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL )
139 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_SYNC_CALL )
140 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_RETURN_CALL )
141 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_CONTROL_FLOW )
142 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_OBJECT_FLOW )
143 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL );
144 :
145 0 : const double src_from_y
146 0 : = ( y_value < src_top ) ? src_top : ( y_value > src_bottom ) ? src_bottom : y_value;
147 0 : const double dst_to_y
148 0 : = ( y_value < dst_top ) ? dst_top : ( y_value > dst_bottom ) ? dst_bottom : y_value;
149 0 : const double src_from_x
150 0 : = (( y_value < src_top )||( y_value > src_bottom )|| is_interaction )
151 : ? src_center_x
152 0 : : ( src_center_x < dst_center_x )
153 : ? src_right
154 0 : : src_left;
155 0 : const double dst_to_x
156 0 : = (( y_value < dst_top )||( y_value > dst_bottom )|| is_interaction )
157 : ? dst_center_x
158 0 : : ( src_center_x < dst_center_x )
159 : ? dst_left
160 0 : : dst_right;
161 :
162 : /* determine minimum arrow size for message/call to self */
163 0 : const double good_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
164 :
165 : /* define relation */
166 : geometry_connector_t relationship_shape;
167 0 : if ( fabs( src_center_x - dst_center_x ) < 0.0001 )
168 : {
169 : /* message/call to self */
170 0 : geometry_connector_init_vertical ( &relationship_shape,
171 : src_center_x,
172 0 : src_from_y - (good_dist/2.0),
173 : dst_center_x,
174 0 : dst_to_y + (good_dist/2.0),
175 : src_center_x + good_dist /* the main connector shall be right to the start/end points */
176 : );
177 : }
178 : else
179 : {
180 : /* normal message/call */
181 0 : geometry_connector_init_horizontal ( &relationship_shape,
182 : src_from_x,
183 : src_from_y,
184 : dst_to_x,
185 : dst_to_y,
186 : y_value
187 : );
188 : }
189 0 : layout_relationship_set_shape( the_relationship, &relationship_shape );
190 0 : geometry_connector_destroy( &relationship_shape );
191 :
192 : /* initialize also the label (to empty), this is updated later */
193 : {
194 : geometry_rectangle_t void_rect;
195 0 : geometry_rectangle_init_empty( &void_rect );
196 0 : layout_relationship_set_label_box( the_relationship, &void_rect );
197 0 : geometry_rectangle_destroy( &void_rect );
198 : }
199 : }
200 : }
201 :
202 0 : U8_TRACE_END();
203 0 : }
204 :
205 0 : void pencil_relationship_1d_layouter_layout_for_timing( pencil_relationship_1d_layouter_t *this_ )
206 : {
207 0 : U8_TRACE_BEGIN();
208 :
209 0 : pencil_relationship_1d_layouter_private_make_all_visible( this_ );
210 :
211 : /* get draw area */
212 : const layout_diagram_t *const diagram_layout
213 0 : = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
214 : const geometry_rectangle_t *const diagram_draw_area
215 0 : = layout_diagram_get_draw_area_const( diagram_layout );
216 :
217 : /* layout the relationships */
218 : const uint32_t count_relations
219 0 : = layout_visible_set_get_relationship_count( (*this_).layout_data );
220 0 : U8_TRACE_INFO_INT( "count_relations:", count_relations );
221 0 : for ( uint32_t index = 0; index < count_relations; index ++ )
222 : {
223 : /* get the relationship to layout */
224 : layout_relationship_t *const the_relationship
225 0 : = layout_visible_set_get_relationship_ptr( (*this_).layout_data, index );
226 :
227 : /* adjust visibility */
228 0 : if ( ( NULL == layout_relationship_get_from_feature_ptr( the_relationship ) )
229 0 : && ( NULL == layout_relationship_get_to_feature_ptr( the_relationship ) ) )
230 : {
231 : /* this is a globally visible relation, not local/scenario-based */
232 0 : layout_visible_set_set_relationship_visibility( (*this_).layout_data, index, PENCIL_VISIBILITY_IMPLICIT );
233 : }
234 :
235 : /* calculate layout */
236 : {
237 : /* determine x-coordinate */
238 : const data_relationship_t *const the_relationdata
239 0 : = layout_relationship_get_data_const( the_relationship );
240 0 : const int32_t list_order = data_relationship_get_list_order ( the_relationdata );
241 0 : const double x_value_rel = (list_order/((double)UINT32_MAX))+0.5;
242 0 : const double draw_left = geometry_rectangle_get_left(diagram_draw_area);
243 0 : const double draw_right = geometry_rectangle_get_right(diagram_draw_area);
244 0 : const double x_value = ( (draw_right - draw_left) * x_value_rel ) + draw_left;
245 :
246 : /* get source and destination rectangles */
247 : const geometry_rectangle_t *const source_rect
248 0 : = layout_relationship_get_from_box_const( the_relationship );
249 : const geometry_rectangle_t *const dest_rect
250 0 : = layout_relationship_get_to_box_const( the_relationship );
251 :
252 : /* calculate coordinates */
253 0 : const double src_left = geometry_rectangle_get_left(source_rect);
254 : /*const double src_center_x = geometry_rectangle_get_center_x(source_rect);*/
255 0 : const double src_right = geometry_rectangle_get_right(source_rect);
256 0 : const double src_top = geometry_rectangle_get_top(source_rect);
257 0 : const double src_center_y = geometry_rectangle_get_center_y(source_rect);
258 0 : const double src_bottom = geometry_rectangle_get_bottom(source_rect);
259 :
260 0 : const double dst_left = geometry_rectangle_get_left(dest_rect);
261 : /*const double dst_center_x = geometry_rectangle_get_center_x(dest_rect);*/
262 0 : const double dst_right = geometry_rectangle_get_right(dest_rect);
263 0 : const double dst_top = geometry_rectangle_get_top(dest_rect);
264 0 : const double dst_center_y = geometry_rectangle_get_center_y(dest_rect);
265 0 : const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
266 :
267 : /* is interaction relation */
268 : const data_relationship_type_t rel_type
269 0 : = data_relationship_get_main_type( the_relationdata );
270 0 : const bool is_interaction
271 : = ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL )
272 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_SYNC_CALL )
273 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_RETURN_CALL )
274 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_CONTROL_FLOW )
275 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_OBJECT_FLOW )
276 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL );
277 :
278 0 : const double src_from_x
279 0 : = ( x_value < src_left ) ? src_left : ( x_value > src_right ) ? src_right : x_value;
280 0 : const double dst_to_x
281 0 : = ( x_value < dst_left ) ? dst_left : ( x_value > dst_right ) ? dst_right : x_value;
282 0 : const double src_from_y
283 0 : = (( x_value < src_left )||( x_value > src_right )|| is_interaction )
284 : ? src_center_y
285 0 : : ( src_center_y < dst_center_y )
286 : ? src_bottom
287 0 : : src_top;
288 0 : const double dst_to_y
289 0 : = (( x_value < dst_left )||( x_value > dst_right )|| is_interaction )
290 : ? dst_center_y
291 0 : : ( src_center_y < dst_center_y )
292 : ? dst_top
293 0 : : dst_bottom;
294 :
295 : /* determine minimum arrow size for self transition */
296 0 : const double good_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
297 :
298 : /* define relation */
299 : geometry_connector_t relationship_shape;
300 0 : if ( fabs( src_center_y - dst_center_y ) < 0.0001 )
301 : {
302 : /* transition to self */
303 0 : geometry_connector_init_horizontal ( &relationship_shape,
304 0 : src_from_x - (good_dist/2.0),
305 : src_center_y,
306 0 : dst_to_x + (good_dist/2.0),
307 : dst_center_y,
308 : src_center_y - good_dist /* the main connector shall be above the start/end points */
309 : );
310 : }
311 : else
312 : {
313 : /* normal transition */
314 0 : geometry_connector_init_vertical ( &relationship_shape,
315 : src_from_x,
316 : src_from_y,
317 : dst_to_x,
318 : dst_to_y,
319 : x_value
320 : );
321 : }
322 0 : layout_relationship_set_shape( the_relationship, &relationship_shape );
323 0 : geometry_connector_destroy( &relationship_shape );
324 :
325 : /* initialize also the label (to empty), this is updated later */
326 : {
327 : geometry_rectangle_t void_rect;
328 0 : geometry_rectangle_init_empty( &void_rect );
329 0 : layout_relationship_set_label_box( the_relationship, &void_rect );
330 0 : geometry_rectangle_destroy( &void_rect );
331 : }
332 : }
333 : }
334 :
335 0 : U8_TRACE_END();
336 0 : }
337 :
338 :
339 : /*
340 : Copyright 2017-2025 Andreas Warnke
341 :
342 : Licensed under the Apache License, Version 2.0 (the "License");
343 : you may not use this file except in compliance with the License.
344 : You may obtain a copy of the License at
345 :
346 : http://www.apache.org/licenses/LICENSE-2.0
347 :
348 : Unless required by applicable law or agreed to in writing, software
349 : distributed under the License is distributed on an "AS IS" BASIS,
350 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
351 : See the License for the specific language governing permissions and
352 : limitations under the License.
353 : */
|