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_symbol_box_const ( the_relationship ); 116 : const geometry_rectangle_t *const dest_rect 117 0 : = layout_relationship_get_to_symbol_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 : } 193 : 194 0 : U8_TRACE_END(); 195 0 : } 196 : 197 0 : void pencil_relationship_1d_layouter_layout_for_timing( pencil_relationship_1d_layouter_t *this_ ) 198 : { 199 0 : U8_TRACE_BEGIN(); 200 : 201 0 : pencil_relationship_1d_layouter_private_make_all_visible( this_ ); 202 : 203 : /* get draw area */ 204 : const layout_diagram_t *const diagram_layout 205 0 : = layout_visible_set_get_diagram_ptr( (*this_).layout_data ); 206 : const geometry_rectangle_t *const diagram_draw_area 207 0 : = layout_diagram_get_draw_area_const( diagram_layout ); 208 : 209 : /* layout the relationships */ 210 : const uint32_t count_relations 211 0 : = layout_visible_set_get_relationship_count( (*this_).layout_data ); 212 0 : U8_TRACE_INFO_INT( "count_relations:", count_relations ); 213 0 : for ( uint32_t index = 0; index < count_relations; index ++ ) 214 : { 215 : /* get the relationship to layout */ 216 : layout_relationship_t *const the_relationship 217 0 : = layout_visible_set_get_relationship_ptr( (*this_).layout_data, index ); 218 : 219 : /* adjust visibility */ 220 0 : if ( ( NULL == layout_relationship_get_from_feature_ptr( the_relationship ) ) 221 0 : && ( NULL == layout_relationship_get_to_feature_ptr( the_relationship ) ) ) 222 : { 223 : /* this is a globally visible relation, not local/scenario-based */ 224 0 : layout_visible_set_set_relationship_visibility( (*this_).layout_data, index, PENCIL_VISIBILITY_IMPLICIT ); 225 : } 226 : 227 : /* calculate layout */ 228 : { 229 : /* determine x-coordinate */ 230 : const data_relationship_t *const the_relationdata 231 0 : = layout_relationship_get_data_const( the_relationship ); 232 0 : const int32_t list_order = data_relationship_get_list_order ( the_relationdata ); 233 0 : const double x_value_rel = (list_order/((double)UINT32_MAX))+0.5; 234 0 : const double draw_left = geometry_rectangle_get_left(diagram_draw_area); 235 0 : const double draw_right = geometry_rectangle_get_right(diagram_draw_area); 236 0 : const double x_value = ( (draw_right - draw_left) * x_value_rel ) + draw_left; 237 : 238 : /* get source and destination rectangles */ 239 : const geometry_rectangle_t *const source_rect 240 0 : = layout_relationship_get_from_symbol_box_const( the_relationship ); 241 : const geometry_rectangle_t *const dest_rect 242 0 : = layout_relationship_get_to_symbol_box_const( the_relationship ); 243 : 244 : /* calculate coordinates */ 245 0 : const double src_left = geometry_rectangle_get_left(source_rect); 246 : /*const double src_center_x = geometry_rectangle_get_center_x(source_rect);*/ 247 0 : const double src_right = geometry_rectangle_get_right(source_rect); 248 0 : const double src_top = geometry_rectangle_get_top(source_rect); 249 0 : const double src_center_y = geometry_rectangle_get_center_y(source_rect); 250 0 : const double src_bottom = geometry_rectangle_get_bottom(source_rect); 251 : 252 0 : const double dst_left = geometry_rectangle_get_left(dest_rect); 253 : /*const double dst_center_x = geometry_rectangle_get_center_x(dest_rect);*/ 254 0 : const double dst_right = geometry_rectangle_get_right(dest_rect); 255 0 : const double dst_top = geometry_rectangle_get_top(dest_rect); 256 0 : const double dst_center_y = geometry_rectangle_get_center_y(dest_rect); 257 0 : const double dst_bottom = geometry_rectangle_get_bottom(dest_rect); 258 : 259 : /* is interaction relation */ 260 : const data_relationship_type_t rel_type 261 0 : = data_relationship_get_main_type( the_relationdata ); 262 0 : const bool is_interaction 263 : = ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL ) 264 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_SYNC_CALL ) 265 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_RETURN_CALL ) 266 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_CONTROL_FLOW ) 267 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_OBJECT_FLOW ) 268 0 : || ( rel_type == DATA_RELATIONSHIP_TYPE_UML_ASYNC_CALL ); 269 : 270 0 : const double src_from_x 271 0 : = ( x_value < src_left ) ? src_left : ( x_value > src_right ) ? src_right : x_value; 272 0 : const double dst_to_x 273 0 : = ( x_value < dst_left ) ? dst_left : ( x_value > dst_right ) ? dst_right : x_value; 274 0 : const double src_from_y 275 0 : = (( x_value < src_left )||( x_value > src_right )|| is_interaction ) 276 : ? src_center_y 277 0 : : ( src_center_y < dst_center_y ) 278 : ? src_bottom 279 0 : : src_top; 280 0 : const double dst_to_y 281 0 : = (( x_value < dst_left )||( x_value > dst_right )|| is_interaction ) 282 : ? dst_center_y 283 0 : : ( src_center_y < dst_center_y ) 284 : ? dst_top 285 0 : : dst_bottom; 286 : 287 : /* determine minimum arrow size for self transition */ 288 0 : const double good_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size ); 289 : 290 : /* define relation */ 291 : geometry_connector_t relationship_shape; 292 0 : if ( fabs( src_center_y - dst_center_y ) < 0.0001 ) 293 : { 294 : /* transition to self */ 295 0 : geometry_connector_init_horizontal ( &relationship_shape, 296 0 : src_from_x - (good_dist/2.0), 297 : src_center_y, 298 0 : dst_to_x + (good_dist/2.0), 299 : dst_center_y, 300 : src_center_y - good_dist /* the main connector shall be above the start/end points */ 301 : ); 302 : } 303 : else 304 : { 305 : /* normal transition */ 306 0 : geometry_connector_init_vertical ( &relationship_shape, 307 : src_from_x, 308 : src_from_y, 309 : dst_to_x, 310 : dst_to_y, 311 : x_value 312 : ); 313 : } 314 0 : layout_relationship_set_shape( the_relationship, &relationship_shape ); 315 0 : geometry_connector_destroy( &relationship_shape ); 316 : } 317 : } 318 : 319 0 : U8_TRACE_END(); 320 0 : } 321 : 322 : 323 : /* 324 : Copyright 2017-2024 Andreas Warnke 325 : 326 : Licensed under the Apache License, Version 2.0 (the "License"); 327 : you may not use this file except in compliance with the License. 328 : You may obtain a copy of the License at 329 : 330 : http://www.apache.org/licenses/LICENSE-2.0 331 : 332 : Unless required by applicable law or agreed to in writing, software 333 : distributed under the License is distributed on an "AS IS" BASIS, 334 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 335 : See the License for the specific language governing permissions and 336 : limitations under the License. 337 : */