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 : */