LCOV - code coverage report
Current view: top level - pencil/source - pencil_layouter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 0 338 0.0 %
Date: 2024-10-26 21:44:38 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /* File: pencil_layouter.c; Copyright and License: see below */
       2             : 
       3             : #include "pencil_layouter.h"
       4             : #include "geometry/geometry_non_linear_scale.h"
       5             : #include "u8/u8_trace.h"
       6             : #include <pango/pangocairo.h>
       7             : #include <stdio.h>
       8             : #include <stdlib.h>
       9             : #include <math.h>
      10             : 
      11           0 : void pencil_layouter_init( pencil_layouter_t *this_,
      12             :                            const data_visible_set_t *input_data,
      13             :                            const data_profile_part_t *profile )
      14             : {
      15           0 :     U8_TRACE_BEGIN();
      16           0 :     assert( NULL != input_data );
      17           0 :     assert( NULL != profile );
      18             : 
      19           0 :     pencil_size_init_empty( &((*this_).pencil_size) );
      20           0 :     geometry_grid_init( &((*this_).grid), GEOMETRY_GRID_KIND_0 );
      21           0 :     geometry_dimensions_init_empty( &((*this_).default_classifier_size) );
      22           0 :     data_rules_init( &((*this_).rules) );
      23             : 
      24             :     /* initialize the layout data objects */
      25           0 :     layout_visible_set_init( &((*this_).layout_data), input_data );
      26           0 :     (*this_).profile = profile;
      27             : 
      28           0 :     pencil_diagram_painter_init( &((*this_).diagram_painter) );
      29             : 
      30           0 :     pencil_feature_layouter_init( &((*this_).feature_layouter),
      31             :                                   &((*this_).layout_data),
      32             :                                   profile,
      33           0 :                                   &((*this_).pencil_size)
      34             :                                 );
      35           0 :     pencil_feat_label_layouter_init( &((*this_).feature_label_layouter),
      36             :                                      &((*this_).layout_data),
      37             :                                      profile,
      38           0 :                                      &((*this_).pencil_size)
      39             :                                    );
      40           0 :     pencil_classifier_2d_layouter_init( &((*this_).pencil_classifier_2d_layouter),
      41             :                                         &((*this_).layout_data),
      42             :                                         profile,
      43           0 :                                         &((*this_).pencil_size),
      44             :                                         &((*this_).default_classifier_size),
      45           0 :                                         &((*this_).grid),
      46             :                                         &((*this_).feature_layouter)
      47             :                                       );
      48           0 :     pencil_classifier_1d_layouter_init( &((*this_).pencil_classifier_1d_layouter),
      49             :                                         &((*this_).layout_data),
      50             :                                         profile,
      51           0 :                                         &((*this_).pencil_size)
      52             :                                       );
      53           0 :     pencil_relationship_2d_layouter_init( &((*this_).pencil_relationship_2d_layouter),
      54             :                                           &((*this_).layout_data),
      55             :                                           profile,
      56           0 :                                           &((*this_).pencil_size)
      57             :                                         );
      58           0 :     pencil_relationship_1d_layouter_init( &((*this_).pencil_relationship_1d_layouter),
      59             :                                           &((*this_).layout_data),
      60             :                                           profile,
      61           0 :                                           &((*this_).pencil_size)
      62             :                                         );
      63           0 :     pencil_rel_label_layouter_init( &((*this_).relationship_label_layouter),
      64             :                                     &((*this_).layout_data),
      65             :                                     profile,
      66           0 :                                     &((*this_).pencil_size)
      67             :                                   );
      68           0 :     U8_TRACE_END();
      69           0 : }
      70             : 
      71           0 : void pencil_layouter_reinit( pencil_layouter_t *this_,
      72             :                              const data_visible_set_t *input_data,
      73             :                              const data_profile_part_t *profile )
      74             : {
      75           0 :     U8_TRACE_BEGIN();
      76           0 :     assert( NULL != input_data );
      77           0 :     assert( NULL != profile );
      78           0 :     pencil_layouter_destroy( this_ );
      79           0 :     pencil_layouter_init( this_, input_data, profile );
      80           0 :     U8_TRACE_END();
      81           0 : }
      82             : 
      83           0 : void pencil_layouter_destroy( pencil_layouter_t *this_ )
      84             : {
      85           0 :     U8_TRACE_BEGIN();
      86             : 
      87           0 :     pencil_rel_label_layouter_destroy( &((*this_).relationship_label_layouter) );
      88           0 :     pencil_relationship_1d_layouter_destroy( &((*this_).pencil_relationship_1d_layouter) );
      89           0 :     pencil_relationship_2d_layouter_destroy( &((*this_).pencil_relationship_2d_layouter) );
      90           0 :     pencil_classifier_1d_layouter_destroy( &((*this_).pencil_classifier_1d_layouter) );
      91           0 :     pencil_classifier_2d_layouter_destroy( &((*this_).pencil_classifier_2d_layouter) );
      92           0 :     pencil_feat_label_layouter_destroy( &((*this_).feature_label_layouter) );
      93           0 :     pencil_feature_layouter_destroy( &((*this_).feature_layouter) );
      94             : 
      95           0 :     pencil_diagram_painter_destroy( &((*this_).diagram_painter) );
      96             : 
      97           0 :     pencil_size_destroy( &((*this_).pencil_size) );
      98           0 :     geometry_grid_destroy( &((*this_).grid) );
      99           0 :     geometry_dimensions_destroy( &((*this_).default_classifier_size) );
     100           0 :     data_rules_destroy( &((*this_).rules) );
     101             : 
     102           0 :     layout_visible_set_destroy( &((*this_).layout_data) );
     103             : 
     104           0 :     U8_TRACE_END();
     105           0 : }
     106             : 
     107           0 : void pencil_layouter_define_grid ( pencil_layouter_t *this_,
     108             :                                    geometry_rectangle_t diagram_bounds,
     109             :                                    PangoLayout *font_layout )
     110             : {
     111           0 :     U8_TRACE_BEGIN();
     112           0 :     geometry_rectangle_trace( &diagram_bounds );
     113             : 
     114             :     /* get the diagram data */
     115             :     layout_diagram_t *the_diagram;
     116           0 :     the_diagram = layout_visible_set_get_diagram_ptr( &((*this_).layout_data) );
     117             :     const data_diagram_t *const diagram_data
     118           0 :         = layout_diagram_get_data_const ( the_diagram );
     119             : 
     120             :     /* calculate the pencil-sizes and the drawing rectangle */
     121           0 :     const double width = geometry_rectangle_get_width( &diagram_bounds );
     122           0 :     const double height = geometry_rectangle_get_height( &diagram_bounds );
     123           0 :     pencil_size_reinit( &((*this_).pencil_size), width, height );
     124             : 
     125           0 :     pencil_diagram_painter_do_layout( &((*this_).diagram_painter),
     126             :                                       diagram_data,
     127             :                                       &diagram_bounds,
     128             :                                       (*this_).profile,
     129           0 :                                       &((*this_).pencil_size),
     130             :                                       font_layout,
     131             :                                       the_diagram
     132             :                                     );
     133             :     const geometry_rectangle_t *const diagram_draw_area
     134           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     135             : 
     136             :     /* calculate the axis scales */
     137           0 :     geometry_rectangle_trace( diagram_draw_area );
     138           0 :     const double draw_left = geometry_rectangle_get_left( diagram_draw_area );
     139           0 :     const double draw_top = geometry_rectangle_get_top( diagram_draw_area );
     140           0 :     const double draw_right = geometry_rectangle_get_right( diagram_draw_area );
     141           0 :     const double draw_bottom = geometry_rectangle_get_bottom( diagram_draw_area );
     142           0 :     geometry_grid_reinit( &((*this_).grid), GEOMETRY_GRID_KIND_XY );
     143           0 :     geometry_non_linear_scale_t *const x_scale = geometry_grid_get_x_scale_ptr( &((*this_).grid) );
     144           0 :     geometry_non_linear_scale_t *const y_scale = geometry_grid_get_y_scale_ptr( &((*this_).grid) );
     145           0 :     geometry_non_linear_scale_reinit( x_scale, draw_left, draw_right );
     146           0 :     geometry_non_linear_scale_reinit( y_scale, draw_top, draw_bottom );
     147             : 
     148             :     /* iterate over all classifiers */
     149             :     const uint32_t count
     150           0 :         = layout_visible_set_get_visible_classifier_count ( &((*this_).layout_data) );
     151           0 :     for ( uint32_t index = 0; index < count; index ++ )
     152             :     {
     153             :         const layout_visible_classifier_t *const visible_classifier
     154           0 :             = layout_visible_set_get_visible_classifier_ptr ( &((*this_).layout_data), index );
     155             :         const data_classifier_t *const classifier_data
     156           0 :             = layout_visible_classifier_get_classifier_const( visible_classifier );
     157             :         const uint32_t visible_descendants
     158           0 :             = layout_visible_set_count_descendants( &((*this_).layout_data), visible_classifier );
     159             : 
     160             :         /* adjust the non-linear scales for this classifier (if no contained descendants) */
     161           0 :         if ( 0 == visible_descendants )
     162             :         {
     163           0 :             geometry_non_linear_scale_add_order( x_scale, data_classifier_get_x_order( classifier_data ) );
     164           0 :             geometry_non_linear_scale_add_order( y_scale, data_classifier_get_y_order( classifier_data ) );
     165             :         }
     166             :     }
     167             : 
     168           0 :     U8_TRACE_END();
     169           0 : }
     170             : 
     171           0 : void pencil_layouter_layout_elements ( pencil_layouter_t *this_, PangoLayout *font_layout )
     172             : {
     173           0 :     U8_TRACE_BEGIN();
     174           0 :     assert( font_layout != NULL );
     175             : 
     176             :     /* get the diagram data */
     177           0 :     const layout_diagram_t *const the_diagram = layout_visible_set_get_diagram_ptr( &((*this_).layout_data) );
     178           0 :     const data_diagram_t *const diagram_data = layout_diagram_get_data_const ( the_diagram );
     179           0 :     const data_diagram_type_t diag_type = data_diagram_get_diagram_type ( diagram_data );
     180             : 
     181             :     /* adjust the default classifier rectangle */
     182           0 :     pencil_layouter_private_propose_default_classifier_size( this_ );
     183             : 
     184             :     /* store the classifier bounds into input_data_layouter_t */
     185           0 :     if ( DATA_DIAGRAM_TYPE_LIST == diag_type )
     186             :     {
     187             :         /* calculate the classifier shapes */
     188           0 :         pencil_classifier_1d_layouter_layout_for_list( &((*this_).pencil_classifier_1d_layouter), font_layout );
     189             : 
     190             :         /* calculate the feature shapes */
     191           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     192             : 
     193             :         /* hide relationships in simple list and box diagrams */
     194           0 :         pencil_relationship_2d_layouter_layout_void( &((*this_).pencil_relationship_2d_layouter) );
     195             : 
     196             :         /* layout labels of features */
     197           0 :         pencil_feat_label_layouter_do_layout( &((*this_).feature_label_layouter), font_layout );
     198             :     }
     199           0 :     else if ( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )
     200             :     {
     201             :         /* calculate the classifier shapes */
     202           0 :         pencil_classifier_1d_layouter_layout_for_sequence( &((*this_).pencil_classifier_1d_layouter), font_layout );
     203             : 
     204             :         /* calculate the feature shapes */
     205           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     206             : 
     207             :         /* calculate the relationship shapes for a sequence diagram */
     208           0 :         pencil_relationship_1d_layouter_layout_for_sequence( &((*this_).pencil_relationship_1d_layouter) );
     209             : 
     210             :         /* layout labels of relationships */
     211           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     212             :     }
     213           0 :     else if ( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )
     214             :     {
     215             :         /* calculate the classifier shapes */
     216           0 :         pencil_classifier_1d_layouter_layout_for_timing( &((*this_).pencil_classifier_1d_layouter), font_layout );
     217             : 
     218             :         /* calculate the feature shapes */
     219           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     220             : 
     221             :         /* calculate the relationship shapes for a timing diagram */
     222           0 :         pencil_relationship_1d_layouter_layout_for_timing( &((*this_).pencil_relationship_1d_layouter) );
     223             : 
     224             :         /* layout labels of relationships */
     225           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     226             :     }
     227             :     else
     228             :     {
     229             :         /* store the classifier bounds into input_data_layouter_t */
     230           0 :         pencil_classifier_2d_layouter_estimate_bounds( &((*this_).pencil_classifier_2d_layouter), font_layout );
     231             : 
     232             :         /* move the classifiers to avoid overlaps */
     233           0 :         pencil_classifier_2d_layouter_move_to_avoid_overlaps( &((*this_).pencil_classifier_2d_layouter) );
     234             : 
     235             :         /* parent classifiers embrace their children step by step */
     236           0 :         pencil_classifier_2d_layouter_embrace_children( &((*this_).pencil_classifier_2d_layouter), font_layout );
     237             : 
     238             :         /* classifiers embrace all children at once and move them if there is space available */
     239           0 :         pencil_classifier_2d_layouter_move_and_embrace_children( &((*this_).pencil_classifier_2d_layouter), font_layout );
     240             : 
     241             :         /* calculate the feature shapes */
     242           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     243             : 
     244           0 :         if ( DATA_DIAGRAM_TYPE_BOX_DIAGRAM == diag_type )
     245             :         {
     246             :             /* hide relationships in simple list and box diagrams */
     247           0 :             pencil_relationship_2d_layouter_layout_void( &((*this_).pencil_relationship_2d_layouter) );
     248             :         }
     249           0 :         else if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diag_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diag_type ))
     250             :         {
     251             :             /* calculate the relationship shapes for a communication diagram or an interaction overview diagram (scenario-relations only) */
     252           0 :             pencil_relationship_2d_layouter_layout_for_communication( &((*this_).pencil_relationship_2d_layouter) );
     253             :         }
     254             :         else
     255             :         {
     256             :             /* calculate the relationship shapes */
     257           0 :             pencil_relationship_2d_layouter_layout_standard( &((*this_).pencil_relationship_2d_layouter) );
     258             :         }
     259             : 
     260             :         /* hide containment relationships if children are embraced */
     261           0 :         pencil_classifier_2d_layouter_hide_relations_of_embraced_children( &((*this_).pencil_classifier_2d_layouter) );
     262             : 
     263             :         /* layout labels of features and relationships */
     264           0 :         pencil_feat_label_layouter_do_layout( &((*this_).feature_label_layouter), font_layout );
     265           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     266             :     }
     267             : 
     268           0 :     U8_TRACE_END();
     269           0 : }
     270             : 
     271           0 : void pencil_layouter_private_propose_default_classifier_size ( pencil_layouter_t *this_ )
     272             : {
     273           0 :     U8_TRACE_BEGIN();
     274             : 
     275             :     /* determine grid cell size */
     276           0 :     const geometry_non_linear_scale_t *const x_scale = geometry_grid_get_x_scale_const( &((*this_).grid) );
     277           0 :     const geometry_non_linear_scale_t *const y_scale = geometry_grid_get_y_scale_const( &((*this_).grid) );
     278           0 :     const double grid_width = geometry_non_linear_scale_get_grid_distances( x_scale );
     279           0 :     const double grid_height = geometry_non_linear_scale_get_grid_distances( y_scale );
     280           0 :     double cell_width = grid_width;
     281           0 :     double cell_height = grid_height;
     282             : 
     283             :     /* check if the grid has enough points for all classifiers */
     284           0 :     const uint_fast32_t interv_count_x = geometry_non_linear_scale_get_grid_intervals( x_scale );
     285           0 :     const uint_fast32_t interv_count_y = geometry_non_linear_scale_get_grid_intervals( y_scale );
     286           0 :     const uint_fast32_t inner_point_count = (interv_count_x-1)*(interv_count_y-1);
     287           0 :     const uint_fast32_t c_count = layout_visible_set_get_visible_classifier_count ( &((*this_).layout_data) );
     288           0 :     if ( inner_point_count < c_count )
     289             :     {
     290             :         /* many classifiers share the same location */
     291             :         /* default size is calculated based on count and size, not on grid */
     292             :         /* get the diagram data */
     293             :         const layout_diagram_t *const the_diagram
     294           0 :             = layout_visible_set_get_diagram_ptr( &((*this_).layout_data) );
     295             :         const geometry_rectangle_t *const diagram_draw_area
     296           0 :             = layout_diagram_get_draw_area_const( the_diagram );
     297           0 :         const double draw_width = geometry_rectangle_get_width ( diagram_draw_area );
     298           0 :         const double draw_height = geometry_rectangle_get_height ( diagram_draw_area );
     299           0 :         const uint_fast32_t border = 1;
     300             :         uint_fast32_t rows;
     301             :         uint_fast32_t columns;
     302           0 :         if ( c_count <= 6 )
     303             :         {
     304           0 :             columns = 2;
     305           0 :             rows = (c_count+1)/2;
     306             :         }
     307           0 :         else if ( c_count <= 12 )
     308             :         {
     309           0 :             columns = 3;
     310           0 :             rows = (c_count+2)/3;
     311             :         }
     312           0 :         else if ( c_count <= 24 )
     313             :         {
     314           0 :             columns = 4;
     315           0 :             rows = (c_count+3)/4;
     316             :         }
     317             :         else
     318             :         {
     319           0 :             columns = 5;
     320           0 :             rows = (c_count+4)/5;
     321             :         }
     322           0 :         cell_width = draw_width / (columns+border);
     323           0 :         cell_height = draw_height / (rows+border);
     324             :     }
     325             : 
     326             :     /* determine standard gap between objects */
     327           0 :     const double gap = pencil_size_get_preferred_object_distance( &((*this_).pencil_size) );
     328             : 
     329             :     /* set the default size to grid cell minus a gap on each side, minus extra gap on top for containers */
     330           0 :     geometry_dimensions_t *const default_size = &((*this_).default_classifier_size);
     331           0 :     geometry_dimensions_reinit( default_size, cell_width, cell_height );
     332           0 :     const double x_space = 3.0 * gap;  /* space for enclosing parents and for relationships */
     333           0 :     const double y_space = 4.0 * gap;  /* space for enclosing parents (including title-line) and for relationships */
     334           0 :     geometry_dimensions_expand ( default_size, -x_space, -y_space ); /* ensures non-negative values */
     335             : 
     336             :     /* for aesthetic reasons, ensure that the default dimension is more wide than high */
     337           0 :     const double w = geometry_dimensions_get_width( default_size );
     338           0 :     const double h = geometry_dimensions_get_height( default_size );
     339           0 :     if ( w * 0.75 < h )
     340             :     {
     341           0 :         geometry_dimensions_reinit( default_size, w, w * 0.75 );
     342             :     }
     343             : 
     344           0 :     U8_TRACE_END();
     345           0 : }
     346             : 
     347           0 : pencil_error_t pencil_layouter_get_classifier_order_at_pos ( const pencil_layouter_t *this_,
     348             :                                                              data_classifier_type_t c_type,
     349             :                                                              double x,
     350             :                                                              double y,
     351             :                                                              double snap_distance,
     352             :                                                              layout_order_t* out_layout_order )
     353             : {
     354           0 :     U8_TRACE_BEGIN();
     355           0 :     assert ( NULL != out_layout_order );
     356             : 
     357           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     358             : 
     359             :     /* get the bounding box of the diagram */
     360             :     const layout_diagram_t *const the_diagram
     361           0 :         = layout_visible_set_get_diagram_const( &((*this_).layout_data) );
     362             :     const geometry_rectangle_t *const diagram_bounds
     363           0 :         = layout_diagram_get_bounds_const( the_diagram );
     364             :     const geometry_rectangle_t *const diagram_draw_area
     365           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     366             : 
     367             :     /* get the diagram type */
     368             :     const data_diagram_t *const diagram_data
     369           0 :         = layout_diagram_get_data_const ( the_diagram );
     370             :     const data_diagram_type_t diag_type
     371           0 :         = data_diagram_get_diagram_type ( diagram_data );
     372             : 
     373             :     /* get the classifier type */
     374             :     const bool scenario_semantics
     375           0 :         = data_rules_classifier_has_scenario_semantics( &((*this_).rules),
     376             :                                                         diag_type,
     377             :                                                         c_type
     378             :                                                       );
     379             : 
     380           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     381             :     {
     382           0 :         layout_order_init_empty( out_layout_order );
     383           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     384             :     }
     385             :     else
     386             :     {
     387           0 :         if ((( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )&& scenario_semantics)
     388           0 :             || (( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type)&&( ! scenario_semantics)))
     389           0 :         {
     390             :             /* classifiers are a horizontal list */
     391           0 :             const double draw_left = geometry_rectangle_get_left(diagram_draw_area);
     392           0 :             const double draw_right = geometry_rectangle_get_right(diagram_draw_area);
     393             :             int32_t list_order;
     394           0 :             if ( x <= draw_left )
     395             :             {
     396           0 :                 list_order = INT32_MIN;
     397             :             }
     398           0 :             else if ( x >= draw_right )
     399             :             {
     400           0 :                 list_order = INT32_MAX;
     401             :             }
     402             :             else
     403             :             {
     404           0 :                 list_order = ((uint32_t)(( x - draw_left ) / ( draw_right - draw_left ) * UINT32_MAX));
     405           0 :                 list_order += INT32_MIN;
     406             :             }
     407           0 :             layout_order_init_list( out_layout_order, list_order );
     408             :         }
     409           0 :         else if ((( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )&& scenario_semantics)
     410           0 :             || ( DATA_DIAGRAM_TYPE_LIST == diag_type )
     411           0 :             || (( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type)&&( ! scenario_semantics)))
     412           0 :         {
     413             :             /* classifiers are a vertical list */
     414           0 :             const double draw_top = geometry_rectangle_get_top(diagram_draw_area);
     415           0 :             const double draw_bottom = geometry_rectangle_get_bottom(diagram_draw_area);
     416             :             int32_t list_order;
     417           0 :             if ( y <= draw_top )
     418             :             {
     419           0 :                 list_order = INT32_MIN;
     420             :             }
     421           0 :             else if ( y >= draw_bottom )
     422             :             {
     423           0 :                 list_order = INT32_MAX;
     424             :             }
     425             :             else
     426             :             {
     427           0 :                 list_order = ((uint32_t)(( y - draw_top ) / ( draw_bottom - draw_top ) * UINT32_MAX));
     428           0 :                 list_order += INT32_MIN;
     429             :             }
     430           0 :             layout_order_init_list( out_layout_order, list_order );
     431             :         }
     432             :         else
     433             :         {
     434             :             /* classifiers are x/y arranged */
     435             :             const geometry_non_linear_scale_t *const x_scale
     436           0 :                 = geometry_grid_get_x_scale_const( &((*this_).grid) );
     437             :             const geometry_non_linear_scale_t *const y_scale
     438           0 :                 = geometry_grid_get_y_scale_const( &((*this_).grid) );
     439           0 :             const int32_t x_order = geometry_non_linear_scale_get_order( x_scale, x, snap_distance );
     440           0 :             const int32_t y_order = geometry_non_linear_scale_get_order( y_scale, y, snap_distance );
     441           0 :             layout_order_init_x_y( out_layout_order, x_order, y_order );
     442             :         }
     443             :     }
     444             : 
     445           0 :     U8_TRACE_END_ERR( result );
     446           0 :     return result;
     447             : }
     448             : 
     449           0 : pencil_error_t pencil_layouter_get_feature_order_at_pos ( const pencil_layouter_t *this_,
     450             :                                                           const data_feature_t *feature_ptr,
     451             :                                                           double x,
     452             :                                                           double y,
     453             :                                                           layout_order_t* out_layout_order )
     454             : {
     455           0 :     U8_TRACE_BEGIN();
     456           0 :     assert ( NULL != out_layout_order );
     457           0 :     assert ( NULL != feature_ptr );
     458             : 
     459           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     460             : 
     461             :     /* get data of feature */
     462             :     data_row_id_t parent_classifier_id;
     463             :     data_feature_type_t feature_type;
     464           0 :     feature_type = data_feature_get_main_type ( feature_ptr );
     465           0 :     parent_classifier_id = data_feature_get_classifier_row_id ( feature_ptr );
     466             : 
     467             :     /* get the bounding box of the diagram */
     468             :     const layout_diagram_t *const the_diagram
     469           0 :         = layout_visible_set_get_diagram_const( &((*this_).layout_data) );
     470             :     const geometry_rectangle_t *const diagram_bounds
     471           0 :         = layout_diagram_get_bounds_const( the_diagram );
     472             : 
     473           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     474             :     {
     475           0 :         layout_order_init_empty( out_layout_order );
     476           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     477             :     }
     478           0 :     else if ( DATA_ROW_ID_VOID == parent_classifier_id ) {
     479           0 :         U8_LOG_WARNING( "feature to move has no parent classifier!" );
     480           0 :         layout_order_init_empty( out_layout_order );
     481           0 :         result = PENCIL_ERROR_UNKNOWN_OBJECT;
     482             :     }
     483             :     else
     484             :     {
     485             :         /* iterate over all classifiers, search the closest_parent_instance */
     486           0 :         const layout_visible_classifier_t *closest_parent_instance = NULL;
     487             :         const uint32_t classfy_count
     488           0 :             = layout_visible_set_get_visible_classifier_count ( &((*this_).layout_data) );
     489           0 :         for ( uint32_t classfy_index = 0; classfy_index < classfy_count; classfy_index ++ )
     490             :         {
     491             :             const layout_visible_classifier_t *const visible_classifier
     492           0 :                 = layout_visible_set_get_visible_classifier_const ( &((*this_).layout_data), classfy_index );
     493             :             const data_row_id_t classfy_id
     494           0 :                 = layout_visible_classifier_get_classifier_id ( visible_classifier );
     495           0 :             if ( parent_classifier_id == classfy_id )
     496             :             {
     497           0 :                 if ( NULL == closest_parent_instance )
     498             :                 {
     499           0 :                     closest_parent_instance = visible_classifier;
     500             :                 }
     501             :                 else
     502             :                 {
     503             :                     const geometry_rectangle_t *const classfier_symbol_box
     504           0 :                         = layout_visible_classifier_get_symbol_box_const ( visible_classifier );
     505             :                     const geometry_rectangle_t *const closest_parent_symbol_box
     506           0 :                         = layout_visible_classifier_get_symbol_box_const ( closest_parent_instance );
     507           0 :                     const double classfy_distance = geometry_rectangle_calc_chess_distance( classfier_symbol_box, x, y );
     508             :                     const double closest_parent_distance
     509           0 :                         = geometry_rectangle_calc_chess_distance( closest_parent_symbol_box, x, y );
     510           0 :                     if ( classfy_distance < closest_parent_distance )
     511             :                     {
     512           0 :                         closest_parent_instance = visible_classifier;
     513             :                     }
     514             :                 }
     515             :             }
     516             :         }
     517             : 
     518           0 :         if ( NULL != closest_parent_instance )
     519             :         {
     520           0 :             switch (feature_type)
     521             :             {
     522           0 :                 case DATA_FEATURE_TYPE_PROPERTY:  /* or */
     523             :                 case DATA_FEATURE_TYPE_OPERATION:  /* or */
     524             :                 case DATA_FEATURE_TYPE_TAGGED_VALUE:  /* or */
     525             :                 default: /* this may happen if a new database file has been read by an old program version */
     526             :                 {
     527           0 :                     int32_t max_order_above = INT32_MIN;
     528           0 :                     int32_t min_order_below = INT32_MAX;
     529             :                     /* iterate over all contained features */
     530           0 :                     const uint32_t f_count = layout_visible_set_get_feature_count( &((*this_).layout_data) );
     531           0 :                     for ( uint32_t f_idx = 0; f_idx < f_count; f_idx ++ )
     532             :                     {
     533             :                         /* check if feature belongs to same parent classifier */
     534             :                         const layout_feature_t *const the_feature
     535           0 :                             = layout_visible_set_get_feature_const ( &((*this_).layout_data), f_idx );
     536             :                         const layout_visible_classifier_t *const vis_classfy
     537           0 :                             = layout_feature_get_classifier_const ( the_feature );
     538           0 :                         if ( closest_parent_instance == vis_classfy )
     539             :                         {
     540             :                             /* check if feature is not the moved one */
     541             :                             const data_feature_t *const data_feature
     542           0 :                                 = layout_feature_get_data_const ( the_feature );
     543           0 :                             if ( data_feature_get_row_id ( feature_ptr ) != data_feature_get_row_id ( data_feature ) )
     544             :                             {
     545             :                                 const int32_t list_order
     546           0 :                                     = data_feature_get_list_order( data_feature );
     547             :                                 const geometry_rectangle_t *const feature_symbol_box
     548           0 :                                     = layout_feature_get_symbol_box_const ( the_feature );
     549           0 :                                 if ( y < geometry_rectangle_get_center_y( feature_symbol_box ) )
     550             :                                 {
     551           0 :                                     if ( list_order < min_order_below ) { min_order_below = list_order; }
     552             :                                 }
     553             :                                 else
     554             :                                 {
     555           0 :                                     if ( list_order > max_order_above ) { max_order_above = list_order; }
     556             :                                 }
     557             :                             }
     558             :                         }
     559             :                     }
     560             : 
     561           0 :                     if ( max_order_above == INT32_MIN )
     562             :                     {
     563           0 :                         if ( min_order_below == INT32_MAX )
     564             :                         {
     565             :                             /* nothing above, nothing below */
     566           0 :                             layout_order_init_list( out_layout_order, 0 );
     567             :                         }
     568             :                         else
     569             :                         {
     570             :                             /* nothing above */
     571           0 :                             layout_order_init_list( out_layout_order, min_order_below - 32768 );
     572             :                         }
     573             :                     }
     574             :                     else
     575             :                     {
     576           0 :                         if ( min_order_below == INT32_MAX )
     577             :                         {
     578             :                             /* nothing below */
     579           0 :                             layout_order_init_list( out_layout_order, max_order_above + 32768 );
     580             :                         }
     581             :                         else
     582             :                         {
     583             :                             /* regular interval */
     584           0 :                             layout_order_init_list( out_layout_order, (max_order_above + min_order_below)/2 );
     585             :                         }
     586             :                     }
     587             :                 }
     588           0 :                 break;
     589             : 
     590           0 :                 case DATA_FEATURE_TYPE_PORT:  /* or */
     591             :                 case DATA_FEATURE_TYPE_PROVIDED_INTERFACE:  /* or */
     592             :                 case DATA_FEATURE_TYPE_REQUIRED_INTERFACE:  /* or */
     593             :                 case DATA_FEATURE_TYPE_IN_PORT_PIN:  /* or */
     594             :                 case DATA_FEATURE_TYPE_OUT_PORT_PIN:  /* or */
     595             :                 case DATA_FEATURE_TYPE_ENTRY:  /* or */
     596             :                 case DATA_FEATURE_TYPE_EXIT:
     597             :                 {
     598             :                     const geometry_rectangle_t *const closest_parent_symbol_box
     599           0 :                         = layout_visible_classifier_get_symbol_box_const ( closest_parent_instance );
     600           0 :                     const double center_x = geometry_rectangle_get_center_x( closest_parent_symbol_box );
     601           0 :                     const double center_y = geometry_rectangle_get_center_y( closest_parent_symbol_box );
     602           0 :                     const double width = geometry_rectangle_get_width( closest_parent_symbol_box );
     603           0 :                     const double height = geometry_rectangle_get_height( closest_parent_symbol_box );
     604           0 :                     const double delta_x = x - center_x;
     605           0 :                     const double delty_y = y - center_y;
     606           0 :                     const double relative_delta_x = delta_x * height;
     607           0 :                     const double relative_delta_y = delty_y * width;
     608           0 :                     const double distance_x = ( x < center_x ) ? (center_x - x) : (x - center_x);
     609           0 :                     const double distance_y = ( y < center_y ) ? (center_y - y) : (y - center_y);
     610           0 :                     const double relative_dist_x = distance_x * height;
     611           0 :                     const double relative_dist_y = distance_y * width;
     612             :                     int32_t order;
     613           0 :                     if ( relative_dist_x > relative_dist_y )
     614             :                     {
     615           0 :                         if ( x < center_x )
     616             :                         {
     617             :                             /* x,y is on left side, order is between 0 and INT32_MAX/2 */
     618           0 :                             order = INT32_MAX*(relative_delta_y/(relative_dist_x+0.1)*0.25+0.25);
     619             :                         }
     620             :                         else
     621             :                         {
     622             :                             /* x,y is on right side, order is between INT32_MIN and INT32_MIN/2 */
     623           0 :                             order = INT32_MIN*(relative_delta_y/(relative_dist_x+0.1)*0.25+0.75);
     624             :                         }
     625             :                     }
     626             :                     else
     627             :                     {
     628           0 :                         if ( y < center_y )
     629             :                         {
     630             :                             /* x,y is on upper side, order is between INT32_MIN/2 and 0 */
     631           0 :                             order = INT32_MIN*(relative_delta_x/(relative_dist_y+0.1)*0.25+0.25);
     632             :                         }
     633             :                         else
     634             :                         {
     635             :                             /* x,y is on lower side, order is between INT32_MAX/2 and INT32_MAX */
     636           0 :                             order = INT32_MAX*(relative_delta_x/(relative_dist_y+0.1)*0.25+0.75);
     637             :                         }
     638             :                     }
     639           0 :                     layout_order_init_list( out_layout_order, order );
     640             :                 }
     641           0 :                 break;
     642             : 
     643           0 :                 case DATA_FEATURE_TYPE_LIFELINE:
     644             :                 {
     645           0 :                     U8_TRACE_INFO( "feature to move is a lifeline and therefore cannot move." );
     646           0 :                     layout_order_init_empty( out_layout_order );
     647           0 :                     result = PENCIL_ERROR_UNKNOWN_OBJECT;
     648             :                 }
     649           0 :                 break;
     650             :             }
     651             :         }
     652             :         else
     653             :         {
     654           0 :             U8_LOG_WARNING( "parent classifier of feature is not visible; possibly array size too small?" );
     655           0 :             layout_order_init_empty( out_layout_order );
     656           0 :             result = PENCIL_ERROR_UNKNOWN_OBJECT;
     657             :         }
     658             :     }
     659             : 
     660           0 :     U8_TRACE_END_ERR( result );
     661           0 :     return result;
     662             : }
     663             : 
     664           0 : pencil_error_t pencil_layouter_get_relationship_order_at_pos ( const pencil_layouter_t *this_,
     665             :                                                                double x,
     666             :                                                                double y,
     667             :                                                                layout_order_t* out_layout_order )
     668             : {
     669           0 :     U8_TRACE_BEGIN();
     670           0 :     assert ( NULL != out_layout_order );
     671             : 
     672           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     673             : 
     674             :     /* get the bounding box of the diagram */
     675             :     const layout_diagram_t *const the_diagram
     676           0 :         = layout_visible_set_get_diagram_const( &((*this_).layout_data) );
     677             :     const geometry_rectangle_t *const diagram_bounds
     678           0 :         = layout_diagram_get_bounds_const( the_diagram );
     679             :     const geometry_rectangle_t *const diagram_draw_area
     680           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     681             : 
     682             :     /* get the diagram type */
     683             :     const data_diagram_t *const diagram_data
     684           0 :         = layout_diagram_get_data_const ( the_diagram );
     685             :     const data_diagram_type_t diag_type
     686           0 :         = data_diagram_get_diagram_type ( diagram_data );
     687             : 
     688           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     689             :     {
     690           0 :         layout_order_init_empty( out_layout_order );
     691           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     692             :     }
     693             :     else
     694             :     {
     695           0 :         if (( DATA_DIAGRAM_TYPE_BOX_DIAGRAM == diag_type )
     696           0 :             || ( DATA_DIAGRAM_TYPE_LIST == diag_type ))
     697             :         {
     698             :             /* relationships are hidden in lists and box-diagrams */
     699           0 :             layout_order_init_empty( out_layout_order );
     700           0 :             result = PENCIL_ERROR_OUT_OF_BOUNDS;
     701             :         }
     702           0 :         else if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diag_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diag_type ))
     703             :         {
     704             :             /* communication diagrams and interaction overview diagrams do not care about list_orders of relationships */
     705           0 :             layout_order_init_empty( out_layout_order );
     706             :         }
     707           0 :         else if ( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )
     708             :         {
     709           0 :             const double draw_top = geometry_rectangle_get_top(diagram_draw_area);
     710           0 :             const double draw_bottom = geometry_rectangle_get_bottom(diagram_draw_area);
     711             :             int32_t list_order;
     712           0 :             if ( y <= draw_top )
     713             :             {
     714           0 :                 list_order = INT32_MIN;
     715             :             }
     716           0 :             else if ( y >= draw_bottom )
     717             :             {
     718           0 :                 list_order = INT32_MAX;
     719             :             }
     720             :             else
     721             :             {
     722           0 :                 list_order = ((uint32_t)(( y - draw_top ) / ( draw_bottom - draw_top ) * UINT32_MAX));
     723           0 :                 list_order += INT32_MIN;
     724             :             }
     725           0 :             layout_order_init_list( out_layout_order, list_order );
     726             :         }
     727           0 :         else if ( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )
     728             :         {
     729           0 :             const double draw_left = geometry_rectangle_get_left(diagram_draw_area);
     730           0 :             const double draw_right = geometry_rectangle_get_right(diagram_draw_area);
     731             :             int32_t list_order;
     732           0 :             if ( x <= draw_left )
     733             :             {
     734           0 :                 list_order = INT32_MIN;
     735             :             }
     736           0 :             else if ( x >= draw_right )
     737             :             {
     738           0 :                 list_order = INT32_MAX;
     739             :             }
     740             :             else
     741             :             {
     742           0 :                 list_order = ((uint32_t)(( x - draw_left ) / ( draw_right - draw_left ) * UINT32_MAX));
     743           0 :                 list_order += INT32_MIN;
     744             :             }
     745           0 :             layout_order_init_list( out_layout_order, list_order );
     746             :         }
     747             :         else
     748             :         {
     749             :             /* all other diagram types do not care about list_orders of relationships */
     750           0 :             layout_order_init_empty( out_layout_order );
     751             :         }
     752             :     }
     753             : 
     754           0 :     U8_TRACE_END_ERR( result );
     755           0 :     return result;
     756             : }
     757             : 
     758             : 
     759             : /*
     760             : Copyright 2017-2024 Andreas Warnke
     761             : 
     762             : Licensed under the Apache License, Version 2.0 (the "License");
     763             : you may not use this file except in compliance with the License.
     764             : You may obtain a copy of the License at
     765             : 
     766             :     http://www.apache.org/licenses/LICENSE-2.0
     767             : 
     768             : Unless required by applicable law or agreed to in writing, software
     769             : distributed under the License is distributed on an "AS IS" BASIS,
     770             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     771             : See the License for the specific language governing permissions and
     772             : limitations under the License.
     773             : */

Generated by: LCOV version 1.16