LCOV - code coverage report
Current view: top level - pencil/source - pencil_layouter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 0 424 0.0 %
Date: 2024-04-07 11:14:42 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /* File: pencil_layouter.c; Copyright and License: see below */
       2             : 
       3             : #include "pencil_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             : 
      10           0 : void pencil_layouter_init( pencil_layouter_t *this_,
      11             :                            const data_visible_set_t *input_data,
      12             :                            const data_profile_part_t *profile )
      13             : {
      14           0 :     U8_TRACE_BEGIN();
      15           0 :     assert( NULL != input_data );
      16           0 :     assert( NULL != profile );
      17             : 
      18           0 :     pencil_size_init_empty( &((*this_).pencil_size) );
      19           0 :     geometry_non_linear_scale_init( &((*this_).x_scale), 0.0, 1.0 );
      20           0 :     geometry_non_linear_scale_init( &((*this_).y_scale), 0.0, 1.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 :     pencil_layout_data_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             :                                         &((*this_).x_scale),
      46             :                                         &((*this_).y_scale),
      47             :                                         &((*this_).feature_layouter)
      48             :                                       );
      49           0 :     pencil_classifier_1d_layouter_init( &((*this_).pencil_classifier_1d_layouter),
      50             :                                         &((*this_).layout_data),
      51             :                                         profile,
      52           0 :                                         &((*this_).pencil_size)
      53             :                                       );
      54           0 :     pencil_relationship_2d_layouter_init( &((*this_).pencil_relationship_2d_layouter),
      55             :                                           &((*this_).layout_data),
      56             :                                           profile,
      57           0 :                                           &((*this_).pencil_size)
      58             :                                         );
      59           0 :     pencil_relationship_1d_layouter_init( &((*this_).pencil_relationship_1d_layouter),
      60             :                                           &((*this_).layout_data),
      61             :                                           profile,
      62           0 :                                           &((*this_).pencil_size)
      63             :                                         );
      64           0 :     pencil_rel_label_layouter_init( &((*this_).relationship_label_layouter),
      65             :                                     &((*this_).layout_data),
      66             :                                     profile,
      67           0 :                                     &((*this_).pencil_size)
      68             :                                   );
      69           0 :     U8_TRACE_END();
      70           0 : }
      71             : 
      72           0 : void pencil_layouter_reinit( pencil_layouter_t *this_,
      73             :                              const data_visible_set_t *input_data,
      74             :                              const data_profile_part_t *profile )
      75             : {
      76           0 :     U8_TRACE_BEGIN();
      77           0 :     assert( NULL != input_data );
      78           0 :     assert( NULL != profile );
      79           0 :     pencil_layouter_destroy( this_ );
      80           0 :     pencil_layouter_init( this_, input_data, profile );
      81           0 :     U8_TRACE_END();
      82           0 : }
      83             : 
      84           0 : void pencil_layouter_destroy( pencil_layouter_t *this_ )
      85             : {
      86           0 :     U8_TRACE_BEGIN();
      87             : 
      88           0 :     pencil_rel_label_layouter_destroy( &((*this_).relationship_label_layouter) );
      89           0 :     pencil_relationship_1d_layouter_destroy( &((*this_).pencil_relationship_1d_layouter) );
      90           0 :     pencil_relationship_2d_layouter_destroy( &((*this_).pencil_relationship_2d_layouter) );
      91           0 :     pencil_classifier_1d_layouter_destroy( &((*this_).pencil_classifier_1d_layouter) );
      92           0 :     pencil_classifier_2d_layouter_destroy( &((*this_).pencil_classifier_2d_layouter) );
      93           0 :     pencil_feat_label_layouter_destroy( &((*this_).feature_label_layouter) );
      94           0 :     pencil_feature_layouter_destroy( &((*this_).feature_layouter) );
      95             : 
      96           0 :     pencil_diagram_painter_destroy( &((*this_).diagram_painter) );
      97             : 
      98           0 :     pencil_size_destroy( &((*this_).pencil_size) );
      99           0 :     geometry_non_linear_scale_destroy( &((*this_).x_scale) );
     100           0 :     geometry_non_linear_scale_destroy( &((*this_).y_scale) );
     101           0 :     geometry_dimensions_destroy( &((*this_).default_classifier_size) );
     102           0 :     data_rules_destroy( &((*this_).rules) );
     103             : 
     104           0 :     pencil_layout_data_destroy( &((*this_).layout_data) );
     105             : 
     106           0 :     U8_TRACE_END();
     107           0 : }
     108             : 
     109           0 : void pencil_layouter_define_grid ( pencil_layouter_t *this_,
     110             :                                    geometry_rectangle_t diagram_bounds,
     111             :                                    PangoLayout *font_layout )
     112             : {
     113           0 :     U8_TRACE_BEGIN();
     114           0 :     geometry_rectangle_trace( &diagram_bounds );
     115             : 
     116             :     /* get the diagram data */
     117             :     layout_diagram_t *the_diagram;
     118           0 :     the_diagram = pencil_layout_data_get_diagram_ptr( &((*this_).layout_data) );
     119             :     const data_diagram_t *const diagram_data
     120           0 :         = layout_diagram_get_data_const ( the_diagram );
     121             : 
     122             :     /* calculate the pencil-sizes and the drawing rectangle */
     123           0 :     const double width = geometry_rectangle_get_width( &diagram_bounds );
     124           0 :     const double height = geometry_rectangle_get_height( &diagram_bounds );
     125           0 :     pencil_size_reinit( &((*this_).pencil_size), width, height );
     126             : 
     127           0 :     pencil_diagram_painter_do_layout( &((*this_).diagram_painter),
     128             :                                       diagram_data,
     129             :                                       &diagram_bounds,
     130             :                                       (*this_).profile,
     131           0 :                                       &((*this_).pencil_size),
     132             :                                       font_layout,
     133             :                                       the_diagram
     134             :                                     );
     135             :     const geometry_rectangle_t *const diagram_draw_area
     136           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     137             : 
     138             :     /* calculate the axis scales */
     139           0 :     geometry_rectangle_trace( diagram_draw_area );
     140           0 :     const double draw_left = geometry_rectangle_get_left( diagram_draw_area );
     141           0 :     const double draw_top = geometry_rectangle_get_top( diagram_draw_area );
     142           0 :     const double draw_right = geometry_rectangle_get_right( diagram_draw_area );
     143           0 :     const double draw_bottom = geometry_rectangle_get_bottom( diagram_draw_area );
     144           0 :     geometry_non_linear_scale_reinit( &((*this_).x_scale), draw_left, draw_right );
     145           0 :     geometry_non_linear_scale_reinit( &((*this_).y_scale), draw_top, draw_bottom );
     146             : 
     147             :     /* iterate over all classifiers */
     148             :     const uint32_t count
     149           0 :         = pencil_layout_data_get_visible_classifier_count ( &((*this_).layout_data) );
     150           0 :     for ( uint32_t index = 0; index < count; index ++ )
     151             :     {
     152             :         const layout_visible_classifier_t *const visible_classifier
     153           0 :             = pencil_layout_data_get_visible_classifier_ptr ( &((*this_).layout_data), index );
     154             :         const data_classifier_t *const classifier_data
     155           0 :             = layout_visible_classifier_get_classifier_const( visible_classifier );
     156             :         const uint32_t visible_descendants
     157           0 :             = pencil_layout_data_count_descendants( &((*this_).layout_data), visible_classifier );
     158             : 
     159             :         /* adjust the non-linear scales for this classifier (if no contained descendants) */
     160           0 :         if ( 0 == visible_descendants )
     161             :         {
     162           0 :             geometry_non_linear_scale_add_order ( &((*this_).x_scale), data_classifier_get_x_order( classifier_data ) );
     163           0 :             geometry_non_linear_scale_add_order ( &((*this_).y_scale), data_classifier_get_y_order( classifier_data ) );
     164             :         }
     165             :     }
     166             : 
     167           0 :     U8_TRACE_END();
     168           0 : }
     169             : 
     170           0 : void pencil_layouter_layout_elements ( pencil_layouter_t *this_, PangoLayout *font_layout )
     171             : {
     172           0 :     U8_TRACE_BEGIN();
     173           0 :     assert( font_layout != NULL );
     174             : 
     175             :     /* get the diagram data */
     176           0 :     const layout_diagram_t *const the_diagram = pencil_layout_data_get_diagram_ptr( &((*this_).layout_data) );
     177           0 :     const data_diagram_t *const diagram_data = layout_diagram_get_data_const ( the_diagram );
     178           0 :     const data_diagram_type_t diag_type = data_diagram_get_diagram_type ( diagram_data );
     179             : 
     180             :     /* adjust the default classifier rectangle */
     181           0 :     pencil_layouter_private_propose_default_classifier_size( this_ );
     182             : 
     183             :     /* store the classifier bounds into input_data_layouter_t */
     184           0 :     if ( DATA_DIAGRAM_TYPE_LIST == diag_type )
     185             :     {
     186             :         /* calculate the classifier shapes */
     187           0 :         pencil_classifier_1d_layouter_layout_for_list( &((*this_).pencil_classifier_1d_layouter), font_layout );
     188             : 
     189             :         /* calculate the feature shapes */
     190           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     191             : 
     192             :         /* hide relationships in simple list and box diagrams */
     193           0 :         pencil_relationship_2d_layouter_layout_void( &((*this_).pencil_relationship_2d_layouter) );
     194             : 
     195             :         /* layout labels of features */
     196           0 :         pencil_feat_label_layouter_do_layout( &((*this_).feature_label_layouter), font_layout );
     197             :     }
     198           0 :     else if ( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )
     199             :     {
     200             :         /* calculate the classifier shapes */
     201           0 :         pencil_classifier_1d_layouter_layout_for_sequence( &((*this_).pencil_classifier_1d_layouter), font_layout );
     202             : 
     203             :         /* calculate the feature shapes */
     204           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     205             : 
     206             :         /* calculate the relationship shapes for a sequence diagram */
     207           0 :         pencil_relationship_1d_layouter_layout_for_sequence( &((*this_).pencil_relationship_1d_layouter) );
     208             : 
     209             :         /* layout labels of relationships */
     210           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     211             :     }
     212           0 :     else if ( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )
     213             :     {
     214             :         /* calculate the classifier shapes */
     215           0 :         pencil_classifier_1d_layouter_layout_for_timing( &((*this_).pencil_classifier_1d_layouter), font_layout );
     216             : 
     217             :         /* calculate the feature shapes */
     218           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     219             : 
     220             :         /* calculate the relationship shapes for a timing diagram */
     221           0 :         pencil_relationship_1d_layouter_layout_for_timing( &((*this_).pencil_relationship_1d_layouter) );
     222             : 
     223             :         /* layout labels of relationships */
     224           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     225             :     }
     226             :     else
     227             :     {
     228             :         /* store the classifier bounds into input_data_layouter_t */
     229           0 :         pencil_classifier_2d_layouter_estimate_bounds( &((*this_).pencil_classifier_2d_layouter), font_layout );
     230             : 
     231             :         /* move the classifiers to avoid overlaps */
     232           0 :         pencil_classifier_2d_layouter_move_to_avoid_overlaps( &((*this_).pencil_classifier_2d_layouter) );
     233             : 
     234             :         /* parent classifiers embrace their children step by step */
     235           0 :         pencil_classifier_2d_layouter_embrace_children( &((*this_).pencil_classifier_2d_layouter), font_layout );
     236             : 
     237             :         /* classifiers embrace all children at once and move them if there is space available */
     238           0 :         pencil_classifier_2d_layouter_move_and_embrace_children( &((*this_).pencil_classifier_2d_layouter), font_layout );
     239             : 
     240             :         /* calculate the feature shapes */
     241           0 :         pencil_feature_layouter_do_layout( &((*this_).feature_layouter), font_layout );
     242             : 
     243           0 :         if ( DATA_DIAGRAM_TYPE_BOX_DIAGRAM == diag_type )
     244             :         {
     245             :             /* hide relationships in simple list and box diagrams */
     246           0 :             pencil_relationship_2d_layouter_layout_void( &((*this_).pencil_relationship_2d_layouter) );
     247             :         }
     248           0 :         else if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diag_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diag_type ))
     249             :         {
     250             :             /* calculate the relationship shapes for a communication diagram or an interaction overview diagram (scenario-relations only) */
     251           0 :             pencil_relationship_2d_layouter_layout_for_communication( &((*this_).pencil_relationship_2d_layouter) );
     252             :         }
     253             :         else
     254             :         {
     255             :             /* calculate the relationship shapes */
     256           0 :             pencil_relationship_2d_layouter_layout_standard( &((*this_).pencil_relationship_2d_layouter) );
     257             :         }
     258             : 
     259             :         /* hide containment relationships if children are embraced */
     260           0 :         pencil_classifier_2d_layouter_hide_relations_of_embraced_children( &((*this_).pencil_classifier_2d_layouter) );
     261             : 
     262             :         /* layout labels of features and relationships */
     263           0 :         pencil_feat_label_layouter_do_layout( &((*this_).feature_label_layouter), font_layout );
     264           0 :         pencil_rel_label_layouter_do_layout( &((*this_).relationship_label_layouter), font_layout );
     265             :     }
     266             : 
     267           0 :     U8_TRACE_END();
     268           0 : }
     269             : 
     270           0 : void pencil_layouter_private_propose_default_classifier_size ( pencil_layouter_t *this_ )
     271             : {
     272           0 :     U8_TRACE_BEGIN();
     273             : 
     274             :     /* determine grid cell size */
     275           0 :     const double grid_width = geometry_non_linear_scale_get_grid_distances ( &((*this_).x_scale) );
     276           0 :     const double grid_height = geometry_non_linear_scale_get_grid_distances ( &((*this_).y_scale) );
     277           0 :     double cell_width = grid_width;
     278           0 :     double cell_height = grid_height;
     279             : 
     280             :     /* check if the grid has enough points for all classifiers */
     281           0 :     const uint_fast32_t interv_count_x = geometry_non_linear_scale_get_grid_intervals ( &((*this_).x_scale) );
     282           0 :     const uint_fast32_t interv_count_y = geometry_non_linear_scale_get_grid_intervals ( &((*this_).y_scale) );
     283           0 :     const uint_fast32_t inner_point_count = (interv_count_x-1)*(interv_count_y-1);
     284           0 :     const uint_fast32_t c_count = pencil_layout_data_get_visible_classifier_count ( &((*this_).layout_data) );
     285           0 :     if ( inner_point_count < c_count )
     286             :     {
     287             :         /* many classifiers share the same location */
     288             :         /* default size is calculated based on count and size, not on grid */
     289             :         /* get the diagram data */
     290             :         const layout_diagram_t *const the_diagram
     291           0 :             = pencil_layout_data_get_diagram_ptr( &((*this_).layout_data) );
     292             :         const geometry_rectangle_t *const diagram_draw_area
     293           0 :             = layout_diagram_get_draw_area_const( the_diagram );
     294           0 :         const double draw_width = geometry_rectangle_get_width ( diagram_draw_area );
     295           0 :         const double draw_height = geometry_rectangle_get_height ( diagram_draw_area );
     296           0 :         const uint_fast32_t border = 1;
     297             :         uint_fast32_t rows;
     298             :         uint_fast32_t columns;
     299           0 :         if ( c_count <= 6 )
     300             :         {
     301           0 :             columns = 2;
     302           0 :             rows = (c_count+1)/2;
     303             :         }
     304           0 :         else if ( c_count <= 12 )
     305             :         {
     306           0 :             columns = 3;
     307           0 :             rows = (c_count+2)/3;
     308             :         }
     309           0 :         else if ( c_count <= 24 )
     310             :         {
     311           0 :             columns = 4;
     312           0 :             rows = (c_count+3)/4;
     313             :         }
     314             :         else
     315             :         {
     316           0 :             columns = 5;
     317           0 :             rows = (c_count+4)/5;
     318             :         }
     319           0 :         cell_width = draw_width / (columns+border);
     320           0 :         cell_height = draw_height / (rows+border);
     321             :     }
     322             : 
     323             :     /* determine standard gap between objects */
     324           0 :     const double gap = pencil_size_get_preferred_object_distance( &((*this_).pencil_size) );
     325             : 
     326             :     /* set the default size to grid cell minus a gap on each side, minus extra gap on top for containers */
     327           0 :     geometry_dimensions_t *const default_size = &((*this_).default_classifier_size);
     328           0 :     geometry_dimensions_reinit( default_size, cell_width, cell_height );
     329           0 :     const double x_space = 3.0 * gap;  /* space for enclosing parents and for relationships */
     330           0 :     const double y_space = 4.0 * gap;  /* space for enclosing parents (including title-line) and for relationships */
     331           0 :     geometry_dimensions_expand ( default_size, -x_space, -y_space ); /* ensures non-negative values */
     332             : 
     333             :     /* for aesthetic reasons, ensure that the default dimension is more wide than high */
     334           0 :     const double w = geometry_dimensions_get_width( default_size );
     335           0 :     const double h = geometry_dimensions_get_height( default_size );
     336           0 :     if ( w * 0.75 < h )
     337             :     {
     338           0 :         geometry_dimensions_reinit( default_size, w, w * 0.75 );
     339             :     }
     340             : 
     341           0 :     U8_TRACE_END();
     342           0 : }
     343             : 
     344           0 : pencil_error_t pencil_layouter_get_object_id_at_pos ( const pencil_layouter_t *this_,
     345             :                                                       double x,
     346             :                                                       double y,
     347             :                                                       double snap_distance,
     348             :                                                       pencil_type_filter_t filter,
     349             :                                                       data_full_id_t* out_selected_id,
     350             :                                                       data_full_id_t* out_surrounding_id )
     351             : {
     352           0 :     U8_TRACE_BEGIN();
     353           0 :     assert( NULL != out_selected_id );
     354           0 :     assert( NULL != out_surrounding_id );
     355             : 
     356           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     357           0 :     data_full_id_reinit_void( out_selected_id );
     358           0 :     data_full_id_reinit_void( out_surrounding_id );
     359             :     const layout_diagram_t *the_diagram;
     360           0 :     the_diagram = pencil_layout_data_get_diagram_const( &((*this_).layout_data) );
     361             :     const data_diagram_t *diagram_data;
     362           0 :     diagram_data = layout_diagram_get_data_const ( the_diagram );
     363             : 
     364             :     /* get bounding box */
     365             :     const geometry_rectangle_t *diagram_bounds;
     366           0 :     diagram_bounds = layout_diagram_get_bounds_const( the_diagram );
     367             : 
     368           0 :     if ( geometry_rectangle_contains( diagram_bounds, x, y ) )
     369             :     {
     370             :         /* check the relationship shapes */
     371             :         {
     372           0 :             result = pencil_layouter_private_get_relationship_id_at_pos( this_,
     373             :                                                                          x,
     374             :                                                                          y,
     375             :                                                                          snap_distance,
     376             :                                                                          out_selected_id
     377             :                                                                        );
     378             :         }
     379             : 
     380             :         /* determine a feature at the given position */
     381           0 :         if ( ! data_full_id_is_valid( out_selected_id ) )
     382             :         {
     383           0 :             result = pencil_layouter_private_get_feature_id_at_pos( this_,
     384             :                                                                     x,
     385             :                                                                     y,
     386             :                                                                     filter,
     387             :                                                                     out_selected_id,
     388             :                                                                     out_surrounding_id
     389             :                                                                   );
     390             :         }
     391             : 
     392             :         /* determine a classifier at the given position */
     393           0 :         if ( ! data_full_id_is_valid( out_selected_id ) )
     394             :         {
     395           0 :             result = pencil_layouter_private_get_classifier_id_at_pos( this_,
     396             :                                                                        x,
     397             :                                                                        y,
     398             :                                                                        out_selected_id,
     399             :                                                                        out_surrounding_id
     400             :                                                                      );
     401             :         }
     402             : 
     403             :         /* fallback: return the diagram */
     404           0 :         if ( ! data_full_id_is_valid( out_selected_id ) )
     405             :         {
     406           0 :             data_full_id_reinit_by_table_and_id ( out_selected_id,
     407             :                                                   DATA_TABLE_DIAGRAM,
     408             :                                                   data_diagram_get_row_id(diagram_data),
     409             :                                                   DATA_TABLE_VOID,
     410             :                                                   DATA_ROW_ID_VOID
     411             :                                                 );
     412             :         }
     413           0 :         if ( ! data_full_id_is_valid( out_surrounding_id ) )
     414             :         {
     415           0 :             data_full_id_reinit_by_table_and_id ( out_surrounding_id,
     416             :                                                   DATA_TABLE_DIAGRAM,
     417             :                                                   data_diagram_get_row_id(diagram_data),
     418             :                                                   DATA_TABLE_VOID,
     419             :                                                   DATA_ROW_ID_VOID
     420             :                                                 );
     421             :         }
     422             :     }
     423             :     else
     424             :     {
     425           0 :         U8_TRACE_INFO( "given location outside diagram or no diagram chosen" );
     426           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     427             :     }
     428             : 
     429           0 :     U8_TRACE_END_ERR( result );
     430           0 :     return result;
     431             : }
     432             : 
     433           0 : pencil_error_t pencil_layouter_private_get_classifier_id_at_pos ( const pencil_layouter_t *this_,
     434             :                                                                   double x,
     435             :                                                                   double y,
     436             :                                                                   data_full_id_t* out_selected_id,
     437             :                                                                   data_full_id_t* out_surrounding_id )
     438             : {
     439           0 :     U8_TRACE_BEGIN();
     440           0 :     assert( NULL != out_selected_id );
     441           0 :     assert( NULL != out_surrounding_id );
     442             : 
     443           0 :     pencil_error_t result = PENCIL_ERROR_OUT_OF_BOUNDS;
     444             : 
     445             :     /* get draw area */
     446             :     const layout_diagram_t *const the_diagram
     447           0 :         = pencil_layout_data_get_diagram_const( &((*this_).layout_data) );
     448             :     const geometry_rectangle_t *const diagram_draw_area
     449           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     450             : 
     451           0 :     if ( geometry_rectangle_contains( diagram_draw_area, x, y ) )
     452             :     {
     453             :         /* iterate over all classifiers */
     454             :         const uint32_t count
     455           0 :             = pencil_layout_data_get_visible_classifier_count ( &((*this_).layout_data) );
     456           0 :         double surrounding_classifier_area = geometry_rectangle_get_area( diagram_draw_area );
     457             : 
     458           0 :         for ( uint32_t index = 0; index < count; index ++ )
     459             :         {
     460             :             const layout_visible_classifier_t *const visible_classifier
     461           0 :                 = pencil_layout_data_get_visible_classifier_const ( &((*this_).layout_data), index );
     462             :             const geometry_rectangle_t *const classifier_symbol_box
     463           0 :                 = layout_visible_classifier_get_symbol_box_const ( visible_classifier );
     464             :             const geometry_rectangle_t *const classifier_space
     465           0 :                 = layout_visible_classifier_get_space_const ( visible_classifier );
     466             :             const geometry_rectangle_t *const classifier_label_box
     467           0 :                 = layout_visible_classifier_get_label_box_const( visible_classifier );
     468             : 
     469           0 :             if ( geometry_rectangle_contains( classifier_symbol_box, x, y )
     470           0 :                 || geometry_rectangle_contains( classifier_label_box, x, y ) )
     471             :             {
     472           0 :                 if ( geometry_rectangle_contains( classifier_space, x, y ) )
     473             :                 {
     474             :                     /* surrounding classifier is found. select it if it is the smallest found area */
     475           0 :                     const double current_classifier_area = geometry_rectangle_get_area( classifier_space );
     476           0 :                     if ( current_classifier_area < surrounding_classifier_area )
     477             :                     {
     478           0 :                         surrounding_classifier_area = current_classifier_area;
     479           0 :                         data_full_id_reinit_by_table_and_id ( out_surrounding_id,
     480             :                                                               DATA_TABLE_DIAGRAMELEMENT,
     481             :                                                               layout_visible_classifier_get_diagramelement_id( visible_classifier ),
     482             :                                                               DATA_TABLE_CLASSIFIER,
     483             :                                                               layout_visible_classifier_get_classifier_id( visible_classifier )
     484             :                                                             );
     485             :                     }
     486             :                 }
     487             :                 else
     488             :                 {
     489             :                     /* classifier is found */
     490           0 :                     data_full_id_reinit_by_table_and_id ( out_selected_id,
     491             :                                                           DATA_TABLE_DIAGRAMELEMENT,
     492             :                                                           layout_visible_classifier_get_diagramelement_id( visible_classifier ),
     493             :                                                           DATA_TABLE_CLASSIFIER,
     494             :                                                           layout_visible_classifier_get_classifier_id( visible_classifier )
     495             :                                                         );
     496             : 
     497           0 :                     result = PENCIL_ERROR_NONE;
     498             :                 }
     499             :             }
     500             :         }
     501             :     }
     502             : 
     503           0 :     U8_TRACE_END_ERR( result );
     504           0 :     return result;
     505             : }
     506             : 
     507           0 : pencil_error_t pencil_layouter_private_get_feature_id_at_pos ( const pencil_layouter_t *this_,
     508             :                                                                double x,
     509             :                                                                double y,
     510             :                                                                pencil_type_filter_t filter,
     511             :                                                                data_full_id_t* out_selected_id,
     512             :                                                                data_full_id_t* out_surrounding_id )
     513             : {
     514           0 :     U8_TRACE_BEGIN();
     515           0 :     assert( NULL != out_selected_id );
     516           0 :     assert( NULL != out_surrounding_id );
     517             : 
     518           0 :     pencil_error_t result = PENCIL_ERROR_OUT_OF_BOUNDS;
     519             : 
     520             :     /* check all contained features */
     521           0 :     const uint32_t f_count = pencil_layout_data_get_feature_count( &((*this_).layout_data) );
     522           0 :     for ( uint32_t f_idx = 0; f_idx < f_count; f_idx ++ )
     523             :     {
     524             :         const layout_feature_t *const the_feature
     525           0 :             = pencil_layout_data_get_feature_const ( &((*this_).layout_data), f_idx );
     526             :         const geometry_rectangle_t *const feature_symbol_box
     527           0 :             = layout_feature_get_symbol_box_const ( the_feature );
     528             :         const geometry_rectangle_t *const feature_label_box
     529           0 :             = layout_feature_get_label_box_const( the_feature );
     530             : 
     531           0 :         if ( geometry_rectangle_contains( feature_symbol_box, x, y )
     532           0 :             || geometry_rectangle_contains( feature_label_box, x, y ) )
     533             :         {
     534             :             /* feature is found */
     535             :             const data_feature_t *const data_feature
     536           0 :                 = layout_feature_get_data_const ( the_feature );
     537             :             const layout_visible_classifier_t *const layout_classifier
     538           0 :                 = layout_feature_get_classifier_const ( the_feature );
     539           0 :             if (( PENCIL_TYPE_FILTER_LIFELINE == filter )
     540           0 :                 &&( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( data_feature ) ))
     541             :             {
     542           0 :                 data_full_id_reinit_by_table_and_id ( out_selected_id,
     543             :                                                       DATA_TABLE_DIAGRAMELEMENT,
     544             :                                                       layout_visible_classifier_get_diagramelement_id( layout_classifier ),
     545             :                                                       DATA_TABLE_CLASSIFIER,
     546             :                                                       layout_visible_classifier_get_classifier_id( layout_classifier )
     547             :                                                     );
     548             :             }
     549             :             else
     550             :             {
     551           0 :                 data_full_id_reinit_by_table_and_id ( out_selected_id,
     552             :                                                       DATA_TABLE_FEATURE,
     553             :                                                       layout_feature_get_feature_id( the_feature ),
     554             :                                                       DATA_TABLE_CLASSIFIER,
     555             :                                                       data_feature_get_classifier_row_id( data_feature )
     556             :                                                     );
     557             :             }
     558             : 
     559           0 :             data_full_id_reinit_by_table_and_id ( out_surrounding_id,
     560             :                                                   DATA_TABLE_DIAGRAMELEMENT,
     561             :                                                   layout_visible_classifier_get_diagramelement_id( layout_classifier ),
     562             :                                                   DATA_TABLE_CLASSIFIER,
     563             :                                                   layout_visible_classifier_get_classifier_id( layout_classifier )
     564             :                                                 );
     565             : 
     566           0 :             result = PENCIL_ERROR_NONE;
     567             :         }
     568             :     }
     569             : 
     570           0 :     U8_TRACE_END_ERR( result );
     571           0 :     return result;
     572             : }
     573             : 
     574           0 : pencil_error_t pencil_layouter_private_get_relationship_id_at_pos ( const pencil_layouter_t *this_,
     575             :                                                                     double x,
     576             :                                                                     double y,
     577             :                                                                     double snap_distance,
     578             :                                                                     data_full_id_t* out_selected_id )
     579             : {
     580           0 :     U8_TRACE_BEGIN();
     581           0 :     assert( NULL != out_selected_id );
     582             : 
     583           0 :     pencil_error_t result = PENCIL_ERROR_OUT_OF_BOUNDS;
     584             : 
     585             :     const uint32_t count_relations
     586           0 :         = pencil_layout_data_get_relationship_count ( &((*this_).layout_data) );
     587           0 :     uint32_t matching_relations_found = 0;
     588           0 :     for ( uint32_t rel_index = 0; rel_index < count_relations; rel_index ++ )
     589             :     {
     590             :         const layout_relationship_t *const the_relationship
     591           0 :             = pencil_layout_data_get_relationship_const( &((*this_).layout_data), rel_index );
     592             :         const geometry_connector_t *const relationship_shape
     593           0 :             = layout_relationship_get_shape_const( the_relationship );
     594             :         const geometry_rectangle_t *const rel_label_box
     595           0 :             = layout_relationship_get_label_box_const( the_relationship );
     596             : 
     597           0 :         if ( geometry_connector_is_close( relationship_shape, x, y, snap_distance )
     598           0 :             || geometry_rectangle_contains( rel_label_box, x, y ) )
     599             :         {
     600             :             /* ensure that every relation at that location can be selected by small mouse movements */
     601           0 :             if ( ((uint32_t)(x+y))%(matching_relations_found+1) == 0 )
     602             :             {
     603             :                 const layout_relationship_t *current_relation;
     604           0 :                 current_relation = pencil_layout_data_get_relationship_const ( &((*this_).layout_data), rel_index );
     605             :                 const data_relationship_t *relation_data;
     606           0 :                 relation_data = layout_relationship_get_data_const( current_relation );
     607             : 
     608           0 :                 data_full_id_reinit_by_table_and_id ( out_selected_id,
     609             :                                                       DATA_TABLE_RELATIONSHIP,
     610             :                                                       data_relationship_get_row_id( relation_data ),
     611             :                                                       DATA_TABLE_VOID,
     612             :                                                       DATA_ROW_ID_VOID
     613             :                                                     );
     614           0 :                 result = PENCIL_ERROR_NONE;
     615             :             }
     616           0 :             matching_relations_found ++;
     617             :         }
     618             :     }
     619             : 
     620           0 :     U8_TRACE_END_ERR( result );
     621           0 :     return result;
     622             : }
     623             : 
     624           0 : pencil_error_t pencil_layouter_get_classifier_order_at_pos ( const pencil_layouter_t *this_,
     625             :                                                              data_classifier_type_t c_type,
     626             :                                                              double x,
     627             :                                                              double y,
     628             :                                                              double snap_distance,
     629             :                                                              layout_order_t* out_layout_order )
     630             : {
     631           0 :     U8_TRACE_BEGIN();
     632           0 :     assert ( NULL != out_layout_order );
     633             : 
     634           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     635             : 
     636             :     /* get the bounding box of the diagram */
     637             :     const layout_diagram_t *const the_diagram
     638           0 :         = pencil_layout_data_get_diagram_const( &((*this_).layout_data) );
     639             :     const geometry_rectangle_t *const diagram_bounds
     640           0 :         = layout_diagram_get_bounds_const( the_diagram );
     641             :     const geometry_rectangle_t *const diagram_draw_area
     642           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     643             : 
     644             :     /* get the diagram type */
     645             :     const data_diagram_t *const diagram_data
     646           0 :         = layout_diagram_get_data_const ( the_diagram );
     647             :     const data_diagram_type_t diag_type
     648           0 :         = data_diagram_get_diagram_type ( diagram_data );
     649             : 
     650             :     /* get the classifier type */
     651             :     const bool scenario_semantics
     652           0 :         = data_rules_classifier_has_scenario_semantics( &((*this_).rules),
     653             :                                                         diag_type,
     654             :                                                         c_type
     655             :                                                       );
     656             : 
     657           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     658             :     {
     659           0 :         layout_order_init_empty( out_layout_order );
     660           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     661             :     }
     662             :     else
     663             :     {
     664           0 :         if ((( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )&& scenario_semantics)
     665           0 :             || (( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type)&&( ! scenario_semantics)))
     666           0 :         {
     667             :             /* classifiers are a horizontal list */
     668           0 :             const double draw_left = geometry_rectangle_get_left(diagram_draw_area);
     669           0 :             const double draw_right = geometry_rectangle_get_right(diagram_draw_area);
     670             :             int32_t list_order;
     671           0 :             if ( x <= draw_left )
     672             :             {
     673           0 :                 list_order = INT32_MIN;
     674             :             }
     675           0 :             else if ( x >= draw_right )
     676             :             {
     677           0 :                 list_order = INT32_MAX;
     678             :             }
     679             :             else
     680             :             {
     681           0 :                 list_order = ((uint32_t)(( x - draw_left ) / ( draw_right - draw_left ) * UINT32_MAX));
     682           0 :                 list_order += INT32_MIN;
     683             :             }
     684           0 :             layout_order_init_list( out_layout_order, list_order );
     685             :         }
     686           0 :         else if ((( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )&& scenario_semantics)
     687           0 :             || ( DATA_DIAGRAM_TYPE_LIST == diag_type )
     688           0 :             || (( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type)&&( ! scenario_semantics)))
     689           0 :         {
     690             :             /* classifiers are a vertical list */
     691           0 :             const double draw_top = geometry_rectangle_get_top(diagram_draw_area);
     692           0 :             const double draw_bottom = geometry_rectangle_get_bottom(diagram_draw_area);
     693             :             int32_t list_order;
     694           0 :             if ( y <= draw_top )
     695             :             {
     696           0 :                 list_order = INT32_MIN;
     697             :             }
     698           0 :             else if ( y >= draw_bottom )
     699             :             {
     700           0 :                 list_order = INT32_MAX;
     701             :             }
     702             :             else
     703             :             {
     704           0 :                 list_order = ((uint32_t)(( y - draw_top ) / ( draw_bottom - draw_top ) * UINT32_MAX));
     705           0 :                 list_order += INT32_MIN;
     706             :             }
     707           0 :             layout_order_init_list( out_layout_order, list_order );
     708             :         }
     709             :         else
     710             :         {
     711             :             /* classifiers are x/y arranged */
     712             :             const int32_t x_order
     713           0 :                 = geometry_non_linear_scale_get_order( &((*this_).x_scale), x, snap_distance );
     714             :             const int32_t y_order
     715           0 :                 = geometry_non_linear_scale_get_order( &((*this_).y_scale), y, snap_distance );
     716           0 :             layout_order_init_x_y( out_layout_order, x_order, y_order );
     717             :         }
     718             :     }
     719             : 
     720           0 :     U8_TRACE_END_ERR( result );
     721           0 :     return result;
     722             : }
     723             : 
     724           0 : pencil_error_t pencil_layouter_get_feature_order_at_pos ( const pencil_layouter_t *this_,
     725             :                                                           const data_feature_t *feature_ptr,
     726             :                                                           double x,
     727             :                                                           double y,
     728             :                                                           layout_order_t* out_layout_order )
     729             : {
     730           0 :     U8_TRACE_BEGIN();
     731           0 :     assert ( NULL != out_layout_order );
     732           0 :     assert ( NULL != feature_ptr );
     733             : 
     734           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     735             : 
     736             :     /* get data of feature */
     737             :     data_row_id_t parent_classifier_id;
     738             :     data_feature_type_t feature_type;
     739           0 :     feature_type = data_feature_get_main_type ( feature_ptr );
     740           0 :     parent_classifier_id = data_feature_get_classifier_row_id ( feature_ptr );
     741             : 
     742             :     /* get the bounding box of the diagram */
     743             :     const layout_diagram_t *const the_diagram
     744           0 :         = pencil_layout_data_get_diagram_const( &((*this_).layout_data) );
     745             :     const geometry_rectangle_t *const diagram_bounds
     746           0 :         = layout_diagram_get_bounds_const( the_diagram );
     747             : 
     748           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     749             :     {
     750           0 :         layout_order_init_empty( out_layout_order );
     751           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     752             :     }
     753           0 :     else if ( DATA_ROW_ID_VOID == parent_classifier_id ) {
     754           0 :         U8_LOG_WARNING( "feature to move has no parent classifier!" );
     755           0 :         layout_order_init_empty( out_layout_order );
     756           0 :         result = PENCIL_ERROR_UNKNOWN_OBJECT;
     757             :     }
     758             :     else
     759             :     {
     760             :         /* iterate over all classifiers, search the closest_parent_instance */
     761           0 :         const layout_visible_classifier_t *closest_parent_instance = NULL;
     762             :         const uint32_t classfy_count
     763           0 :             = pencil_layout_data_get_visible_classifier_count ( &((*this_).layout_data) );
     764           0 :         for ( uint32_t classfy_index = 0; classfy_index < classfy_count; classfy_index ++ )
     765             :         {
     766             :             const layout_visible_classifier_t *const visible_classifier
     767           0 :                 = pencil_layout_data_get_visible_classifier_const ( &((*this_).layout_data), classfy_index );
     768             :             const data_row_id_t classfy_id
     769           0 :                 = layout_visible_classifier_get_classifier_id ( visible_classifier );
     770           0 :             if ( parent_classifier_id == classfy_id )
     771             :             {
     772           0 :                 if ( NULL == closest_parent_instance )
     773             :                 {
     774           0 :                     closest_parent_instance = visible_classifier;
     775             :                 }
     776             :                 else
     777             :                 {
     778             :                     const geometry_rectangle_t *const classfier_symbol_box
     779           0 :                         = layout_visible_classifier_get_symbol_box_const ( visible_classifier );
     780             :                     const geometry_rectangle_t *const closest_parent_symbol_box
     781           0 :                         = layout_visible_classifier_get_symbol_box_const ( closest_parent_instance );
     782           0 :                     const double classfy_distance = geometry_rectangle_calc_chess_distance( classfier_symbol_box, x, y );
     783             :                     const double closest_parent_distance
     784           0 :                         = geometry_rectangle_calc_chess_distance( closest_parent_symbol_box, x, y );
     785           0 :                     if ( classfy_distance < closest_parent_distance )
     786             :                     {
     787           0 :                         closest_parent_instance = visible_classifier;
     788             :                     }
     789             :                 }
     790             :             }
     791             :         }
     792             : 
     793           0 :         if ( NULL != closest_parent_instance )
     794             :         {
     795           0 :             switch (feature_type)
     796             :             {
     797           0 :                 case DATA_FEATURE_TYPE_PROPERTY:  /* or */
     798             :                 case DATA_FEATURE_TYPE_OPERATION:  /* or */
     799             :                 case DATA_FEATURE_TYPE_TAGGED_VALUE:  /* or */
     800             :                 default: /* this may happen if a new database file has been read by an old program version */
     801             :                 {
     802           0 :                     int32_t max_order_above = INT32_MIN;
     803           0 :                     int32_t min_order_below = INT32_MAX;
     804             :                     /* iterate over all contained features */
     805           0 :                     const uint32_t f_count = pencil_layout_data_get_feature_count( &((*this_).layout_data) );
     806           0 :                     for ( uint32_t f_idx = 0; f_idx < f_count; f_idx ++ )
     807             :                     {
     808             :                         /* check if feature belongs to same parent classifier */
     809             :                         const layout_feature_t *const the_feature
     810           0 :                             = pencil_layout_data_get_feature_const ( &((*this_).layout_data), f_idx );
     811             :                         const layout_visible_classifier_t *const vis_classfy
     812           0 :                             = layout_feature_get_classifier_const ( the_feature );
     813           0 :                         if ( closest_parent_instance == vis_classfy )
     814             :                         {
     815             :                             /* check if feature is not the moved one */
     816             :                             const data_feature_t *const data_feature
     817           0 :                                 = layout_feature_get_data_const ( the_feature );
     818           0 :                             if ( data_feature_get_row_id ( feature_ptr ) != data_feature_get_row_id ( data_feature ) )
     819             :                             {
     820             :                                 const int32_t list_order
     821           0 :                                     = data_feature_get_list_order( data_feature );
     822             :                                 const geometry_rectangle_t *const feature_symbol_box
     823           0 :                                     = layout_feature_get_symbol_box_const ( the_feature );
     824           0 :                                 if ( y < geometry_rectangle_get_center_y( feature_symbol_box ) )
     825             :                                 {
     826           0 :                                     if ( list_order < min_order_below ) { min_order_below = list_order; }
     827             :                                 }
     828             :                                 else
     829             :                                 {
     830           0 :                                     if ( list_order > max_order_above ) { max_order_above = list_order; }
     831             :                                 }
     832             :                             }
     833             :                         }
     834             :                     }
     835             : 
     836           0 :                     if ( max_order_above == INT32_MIN )
     837             :                     {
     838           0 :                         if ( min_order_below == INT32_MAX )
     839             :                         {
     840             :                             /* nothing above, nothing below */
     841           0 :                             layout_order_init_list( out_layout_order, 0 );
     842             :                         }
     843             :                         else
     844             :                         {
     845             :                             /* nothing above */
     846           0 :                             layout_order_init_list( out_layout_order, min_order_below - 32768 );
     847             :                         }
     848             :                     }
     849             :                     else
     850             :                     {
     851           0 :                         if ( min_order_below == INT32_MAX )
     852             :                         {
     853             :                             /* nothing below */
     854           0 :                             layout_order_init_list( out_layout_order, max_order_above + 32768 );
     855             :                         }
     856             :                         else
     857             :                         {
     858             :                             /* regular interval */
     859           0 :                             layout_order_init_list( out_layout_order, (max_order_above + min_order_below)/2 );
     860             :                         }
     861             :                     }
     862             :                 }
     863           0 :                 break;
     864             : 
     865           0 :                 case DATA_FEATURE_TYPE_PORT:  /* or */
     866             :                 case DATA_FEATURE_TYPE_PROVIDED_INTERFACE:  /* or */
     867             :                 case DATA_FEATURE_TYPE_REQUIRED_INTERFACE:  /* or */
     868             :                 case DATA_FEATURE_TYPE_IN_PORT_PIN:  /* or */
     869             :                 case DATA_FEATURE_TYPE_OUT_PORT_PIN:  /* or */
     870             :                 case DATA_FEATURE_TYPE_ENTRY:  /* or */
     871             :                 case DATA_FEATURE_TYPE_EXIT:
     872             :                 {
     873             :                     const geometry_rectangle_t *const closest_parent_symbol_box
     874           0 :                         = layout_visible_classifier_get_symbol_box_const ( closest_parent_instance );
     875           0 :                     const double center_x = geometry_rectangle_get_center_x( closest_parent_symbol_box );
     876           0 :                     const double center_y = geometry_rectangle_get_center_y( closest_parent_symbol_box );
     877           0 :                     const double width = geometry_rectangle_get_width( closest_parent_symbol_box );
     878           0 :                     const double height = geometry_rectangle_get_height( closest_parent_symbol_box );
     879           0 :                     const double delta_x = x - center_x;
     880           0 :                     const double delty_y = y - center_y;
     881           0 :                     const double relative_delta_x = delta_x * height;
     882           0 :                     const double relative_delta_y = delty_y * width;
     883           0 :                     const double distance_x = ( x < center_x ) ? (center_x - x) : (x - center_x);
     884           0 :                     const double distance_y = ( y < center_y ) ? (center_y - y) : (y - center_y);
     885           0 :                     const double relative_dist_x = distance_x * height;
     886           0 :                     const double relative_dist_y = distance_y * width;
     887             :                     int32_t order;
     888           0 :                     if ( relative_dist_x > relative_dist_y )
     889             :                     {
     890           0 :                         if ( x < center_x )
     891             :                         {
     892             :                             /* x,y is on left side, order is between 0 and INT32_MAX/2 */
     893           0 :                             order = INT32_MAX*(relative_delta_y/(relative_dist_x+0.1)*0.25+0.25);
     894             :                         }
     895             :                         else
     896             :                         {
     897             :                             /* x,y is on right side, order is between INT32_MIN and INT32_MIN/2 */
     898           0 :                             order = INT32_MIN*(relative_delta_y/(relative_dist_x+0.1)*0.25+0.75);
     899             :                         }
     900             :                     }
     901             :                     else
     902             :                     {
     903           0 :                         if ( y < center_y )
     904             :                         {
     905             :                             /* x,y is on upper side, order is between INT32_MIN/2 and 0 */
     906           0 :                             order = INT32_MIN*(relative_delta_x/(relative_dist_y+0.1)*0.25+0.25);
     907             :                         }
     908             :                         else
     909             :                         {
     910             :                             /* x,y is on lower side, order is between INT32_MAX/2 and INT32_MAX */
     911           0 :                             order = INT32_MAX*(relative_delta_x/(relative_dist_y+0.1)*0.25+0.75);
     912             :                         }
     913             :                     }
     914           0 :                     layout_order_init_list( out_layout_order, order );
     915             :                 }
     916           0 :                 break;
     917             : 
     918           0 :                 case DATA_FEATURE_TYPE_LIFELINE:
     919             :                 {
     920           0 :                     U8_TRACE_INFO( "feature to move is a lifeline and therefore cannot move." );
     921           0 :                     layout_order_init_empty( out_layout_order );
     922           0 :                     result = PENCIL_ERROR_UNKNOWN_OBJECT;
     923             :                 }
     924           0 :                 break;
     925             :             }
     926             :         }
     927             :         else
     928             :         {
     929           0 :             U8_LOG_WARNING( "parent classifier of feature is not visible; possibly array size too small?" );
     930           0 :             layout_order_init_empty( out_layout_order );
     931           0 :             result = PENCIL_ERROR_UNKNOWN_OBJECT;
     932             :         }
     933             :     }
     934             : 
     935           0 :     U8_TRACE_END_ERR( result );
     936           0 :     return result;
     937             : }
     938             : 
     939           0 : pencil_error_t pencil_layouter_get_relationship_order_at_pos ( const pencil_layouter_t *this_,
     940             :                                                                double x,
     941             :                                                                double y,
     942             :                                                                layout_order_t* out_layout_order )
     943             : {
     944           0 :     U8_TRACE_BEGIN();
     945           0 :     assert ( NULL != out_layout_order );
     946             : 
     947           0 :     pencil_error_t result = PENCIL_ERROR_NONE;
     948             : 
     949             :     /* get the bounding box of the diagram */
     950             :     const layout_diagram_t *const the_diagram
     951           0 :         = pencil_layout_data_get_diagram_const( &((*this_).layout_data) );
     952             :     const geometry_rectangle_t *const diagram_bounds
     953           0 :         = layout_diagram_get_bounds_const( the_diagram );
     954             :     const geometry_rectangle_t *const diagram_draw_area
     955           0 :         = layout_diagram_get_draw_area_const( the_diagram );
     956             : 
     957             :     /* get the diagram type */
     958             :     const data_diagram_t *const diagram_data
     959           0 :         = layout_diagram_get_data_const ( the_diagram );
     960             :     const data_diagram_type_t diag_type
     961           0 :         = data_diagram_get_diagram_type ( diagram_data );
     962             : 
     963           0 :     if ( ! geometry_rectangle_contains( diagram_bounds, x, y ) )
     964             :     {
     965           0 :         layout_order_init_empty( out_layout_order );
     966           0 :         result = PENCIL_ERROR_OUT_OF_BOUNDS;
     967             :     }
     968             :     else
     969             :     {
     970           0 :         if (( DATA_DIAGRAM_TYPE_BOX_DIAGRAM == diag_type )
     971           0 :             || ( DATA_DIAGRAM_TYPE_LIST == diag_type ))
     972             :         {
     973             :             /* relationships are hidden in lists and box-diagrams */
     974           0 :             layout_order_init_empty( out_layout_order );
     975           0 :             result = PENCIL_ERROR_OUT_OF_BOUNDS;
     976             :         }
     977           0 :         else if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diag_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diag_type ))
     978             :         {
     979             :             /* communication diagrams and interaction overview diagrams do not care about list_orders of relationships */
     980           0 :             layout_order_init_empty( out_layout_order );
     981             :         }
     982           0 :         else if ( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diag_type )
     983             :         {
     984           0 :             const double draw_top = geometry_rectangle_get_top(diagram_draw_area);
     985           0 :             const double draw_bottom = geometry_rectangle_get_bottom(diagram_draw_area);
     986             :             int32_t list_order;
     987           0 :             if ( y <= draw_top )
     988             :             {
     989           0 :                 list_order = INT32_MIN;
     990             :             }
     991           0 :             else if ( y >= draw_bottom )
     992             :             {
     993           0 :                 list_order = INT32_MAX;
     994             :             }
     995             :             else
     996             :             {
     997           0 :                 list_order = ((uint32_t)(( y - draw_top ) / ( draw_bottom - draw_top ) * UINT32_MAX));
     998           0 :                 list_order += INT32_MIN;
     999             :             }
    1000           0 :             layout_order_init_list( out_layout_order, list_order );
    1001             :         }
    1002           0 :         else if ( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diag_type )
    1003             :         {
    1004           0 :             const double draw_left = geometry_rectangle_get_left(diagram_draw_area);
    1005           0 :             const double draw_right = geometry_rectangle_get_right(diagram_draw_area);
    1006             :             int32_t list_order;
    1007           0 :             if ( x <= draw_left )
    1008             :             {
    1009           0 :                 list_order = INT32_MIN;
    1010             :             }
    1011           0 :             else if ( x >= draw_right )
    1012             :             {
    1013           0 :                 list_order = INT32_MAX;
    1014             :             }
    1015             :             else
    1016             :             {
    1017           0 :                 list_order = ((uint32_t)(( x - draw_left ) / ( draw_right - draw_left ) * UINT32_MAX));
    1018           0 :                 list_order += INT32_MIN;
    1019             :             }
    1020           0 :             layout_order_init_list( out_layout_order, list_order );
    1021             :         }
    1022             :         else
    1023             :         {
    1024             :             /* all other diagram types do not care about list_orders of relationships */
    1025           0 :             layout_order_init_empty( out_layout_order );
    1026             :         }
    1027             :     }
    1028             : 
    1029           0 :     U8_TRACE_END_ERR( result );
    1030           0 :     return result;
    1031             : }
    1032             : 
    1033             : 
    1034             : /*
    1035             : Copyright 2017-2024 Andreas Warnke
    1036             : 
    1037             : Licensed under the Apache License, Version 2.0 (the "License");
    1038             : you may not use this file except in compliance with the License.
    1039             : You may obtain a copy of the License at
    1040             : 
    1041             :     http://www.apache.org/licenses/LICENSE-2.0
    1042             : 
    1043             : Unless required by applicable law or agreed to in writing, software
    1044             : distributed under the License is distributed on an "AS IS" BASIS,
    1045             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1046             : See the License for the specific language governing permissions and
    1047             : limitations under the License.
    1048             : */

Generated by: LCOV version 1.16