LCOV - code coverage report
Current view: top level - pencil/source - pencil_feature_layouter.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 0.0 % 294 0
Test Date: 2025-05-01 10:10:14 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /* File: pencil_feature_layouter.c; Copyright and License: see below */
       2              : 
       3              : #include "pencil_feature_layouter.h"
       4              : #include "u8/u8_f64.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_feature_layouter_init( pencil_feature_layouter_t *this_,
      12              :                                    layout_visible_set_t *layout_data,
      13              :                                    const data_profile_part_t *profile,
      14              :                                    const pencil_size_t *pencil_size )
      15              : {
      16            0 :     U8_TRACE_BEGIN();
      17            0 :     assert( NULL != layout_data );
      18            0 :     assert( NULL != profile );
      19            0 :     assert( NULL != pencil_size );
      20              : 
      21            0 :     (*this_).layout_data = layout_data;
      22            0 :     (*this_).profile = profile;
      23            0 :     (*this_).pencil_size = pencil_size;
      24            0 :     data_rules_init( &((*this_).rules) );
      25            0 :     (*this_).label_dimensions_initialized = false;
      26            0 :     pencil_feature_painter_init( &((*this_).feature_painter) );
      27              : 
      28            0 :     U8_TRACE_END();
      29            0 : }
      30              : 
      31            0 : void pencil_feature_layouter_reset( pencil_feature_layouter_t *this_ )
      32              : {
      33            0 :     U8_TRACE_BEGIN();
      34              : 
      35            0 :     (*this_).label_dimensions_initialized = false;
      36              : 
      37            0 :     U8_TRACE_END();
      38            0 : }
      39              : 
      40            0 : void pencil_feature_layouter_destroy( pencil_feature_layouter_t *this_ )
      41              : {
      42            0 :     U8_TRACE_BEGIN();
      43              : 
      44            0 :     data_rules_destroy( &((*this_).rules) );
      45            0 :     (*this_).label_dimensions_initialized = false;
      46            0 :     pencil_feature_painter_destroy( &((*this_).feature_painter) );
      47              : 
      48            0 :     U8_TRACE_END();
      49            0 : }
      50              : 
      51            0 : void pencil_feature_layouter_do_layout ( pencil_feature_layouter_t *this_, PangoLayout *font_layout )
      52              : {
      53            0 :     U8_TRACE_BEGIN();
      54              :     assert( (unsigned int) UNIVERSAL_ARRAY_INDEX_SORTER_MAX_ARRAY_SIZE >= (unsigned int) LAYOUT_VISIBLE_SET_MAX_FEATURES );
      55              : 
      56              :     /* establish precondition: precalculate the dimensions of labels */
      57            0 :     if ( ! (*this_).label_dimensions_initialized )
      58              :     {
      59            0 :         pencil_feature_layouter_private_init_label_dimensions( this_, font_layout );
      60              :     }
      61              :     /* get diagram draw area */
      62              :     const layout_diagram_t *const diagram_layout
      63            0 :         = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
      64              :     const geometry_rectangle_t *const diagram_draw_area
      65            0 :         = layout_diagram_get_draw_area_const( diagram_layout );
      66              :     const data_diagram_t *const diagram_data
      67            0 :         = layout_diagram_get_data_const ( diagram_layout );
      68              :     const data_diagram_type_t diag_type
      69            0 :         = data_diagram_get_diagram_type ( diagram_data );
      70              : 
      71              :     /* layout the unsorted features */
      72              :     const uint32_t count_features
      73            0 :         = layout_visible_set_get_feature_count ( (*this_).layout_data );
      74            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
      75              :     {
      76              :         layout_feature_t *const feature_layout
      77            0 :             = layout_visible_set_get_feature_ptr ( (*this_).layout_data, f_idx );
      78              :         const data_feature_t *const the_feature
      79            0 :             = layout_feature_get_data_const ( feature_layout );
      80              :         const layout_visible_classifier_t *const layout_classifier
      81            0 :             = layout_feature_get_classifier_const ( feature_layout );
      82              :         const data_classifier_t *const classifier
      83            0 :             = layout_visible_classifier_get_classifier_const( layout_classifier );
      84              :         const data_classifier_type_t classifier_type
      85            0 :             = data_classifier_get_main_type( classifier );
      86              : 
      87              :         const geometry_rectangle_t *const c_symbol_box
      88            0 :             = layout_visible_classifier_get_symbol_box_const ( layout_classifier );
      89              :         const geometry_rectangle_t *const c_envelope_box
      90            0 :             = layout_visible_classifier_get_envelope_box_const ( layout_classifier );
      91            0 :         switch ( data_feature_get_main_type (the_feature) )
      92              :         {
      93            0 :             case DATA_FEATURE_TYPE_LIFELINE:
      94              :             {
      95              :                 /* layout lifeline feature next to parent classifier */
      96            0 :                 pencil_feature_layouter_private_layout_lifeline ( this_,
      97              :                                                                   diagram_draw_area,
      98              :                                                                   diag_type,
      99              :                                                                   classifier_type,
     100              :                                                                   c_symbol_box,
     101              :                                                                   c_envelope_box,
     102              :                                                                   feature_layout
     103              :                                                                 );
     104              :             }
     105            0 :             break;
     106              : 
     107            0 :             case DATA_FEATURE_TYPE_PORT:  /* or */
     108              :             case DATA_FEATURE_TYPE_IN_PORT_PIN:  /* or */
     109              :             case DATA_FEATURE_TYPE_OUT_PORT_PIN:  /* or */
     110              :             case DATA_FEATURE_TYPE_ENTRY:  /* or */
     111              :             case DATA_FEATURE_TYPE_EXIT:
     112              :             {
     113              :                 /* layout port feature onto parent classifier box */
     114            0 :                 pencil_feature_layouter_private_layout_port_pin ( this_,
     115              :                                                                   classifier_type,
     116              :                                                                   c_symbol_box,
     117              :                                                                   the_feature,
     118              :                                                                   font_layout,
     119              :                                                                   feature_layout
     120              :                                                                 );
     121              :             }
     122            0 :             break;
     123              : 
     124            0 :             case DATA_FEATURE_TYPE_PROVIDED_INTERFACE:  /* or */
     125              :             case DATA_FEATURE_TYPE_REQUIRED_INTERFACE:
     126              :             {
     127              :                 /* layout interface feature close to parent classifier */
     128            0 :                 pencil_feature_layouter_private_layout_interface ( this_,
     129              :                                                                    c_symbol_box,
     130              :                                                                    the_feature,
     131              :                                                                    font_layout,
     132              :                                                                    feature_layout
     133              :                                                                  );
     134              :             }
     135            0 :             break;
     136              : 
     137            0 :             case DATA_FEATURE_TYPE_PROPERTY:  /* or */
     138              :             case DATA_FEATURE_TYPE_OPERATION:  /* or */
     139              :             case DATA_FEATURE_TYPE_TAGGED_VALUE:
     140              :             {
     141              :                 /* layout property or operation feature within the space area, also the tagged values */
     142            0 :                 const geometry_rectangle_t *const c_space = layout_visible_classifier_get_space_const ( layout_classifier );
     143            0 :                 pencil_feature_layouter_private_layout_compartment ( this_,
     144              :                                                                      c_space,
     145              :                                                                      font_layout,
     146              :                                                                      feature_layout
     147              :                                                                    );
     148              :             }
     149            0 :             break;
     150              : 
     151            0 :             default:
     152              :             {
     153            0 :                 U8_LOG_ANOMALY("unknown feature type in pencil_feature_layouter_do_layout");
     154              :                 /* this may happen if a new database file has been read by an old program version */
     155              :                 /* layout like property or operation or tagged values */
     156            0 :                 const geometry_rectangle_t *const c_space = layout_visible_classifier_get_space_const ( layout_classifier );
     157            0 :                 pencil_feature_layouter_private_layout_compartment ( this_,
     158              :                                                                      c_space,
     159              :                                                                      font_layout,
     160              :                                                                      feature_layout
     161              :                                                                    );
     162              :             }
     163            0 :             break;
     164              :         }
     165              :     }
     166              : 
     167            0 :     U8_TRACE_END();
     168            0 : }
     169              : 
     170            0 : void pencil_feature_layouter_calculate_features_bounds( pencil_feature_layouter_t *this_,
     171              :                                                         data_row_t diagramelement_id,
     172              :                                                         PangoLayout *font_layout,
     173              :                                                         geometry_dimensions_t *out_features_bounds )
     174              : {
     175            0 :     U8_TRACE_BEGIN();
     176            0 :     assert( NULL != font_layout );
     177            0 :     assert( NULL != out_features_bounds );
     178              : 
     179              :     /* establish precondition: precalculate the dimensions of labels */
     180            0 :     if ( ! (*this_).label_dimensions_initialized )
     181              :     {
     182            0 :         pencil_feature_layouter_private_init_label_dimensions( this_, font_layout );
     183              :     }
     184              : 
     185            0 :     double width = 0.0;
     186            0 :     double height = 0.0;
     187              : 
     188              :     /* search all contained features */
     189              :     const uint32_t count_features
     190            0 :         = layout_visible_set_get_feature_count( (*this_).layout_data );
     191            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
     192              :     {
     193              :         const layout_feature_t *const feature_layout
     194            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_idx );
     195              :         const data_feature_t *const the_feature
     196            0 :             = layout_feature_get_data_const( feature_layout );
     197              :         const layout_visible_classifier_t *const layout_classifier
     198            0 :             = layout_feature_get_classifier_const( feature_layout );
     199            0 :         const data_feature_type_t the_feature_type = data_feature_get_main_type( the_feature );
     200              : 
     201            0 :         if (( diagramelement_id == layout_visible_classifier_get_diagramelement_id( layout_classifier ) )
     202            0 :             && data_feature_type_inside_compartment( the_feature_type ) )
     203              :         {
     204              :             /* feature label sizes are already precalculated */
     205            0 :             assert( (*this_).label_dimensions_initialized );
     206            0 :             const geometry_rectangle_t *const label_box = layout_feature_get_label_box_const( feature_layout );
     207              : 
     208              :             /* update width and height */
     209            0 :             width = u8_f64_max2( width, geometry_rectangle_get_width( label_box ) );
     210            0 :             height += geometry_rectangle_get_height( label_box );
     211              :         }
     212              :     }
     213              : 
     214            0 :     const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     215            0 :     const double sum_of_gaps = 6.0 * gap;  /* gaps above and below each of the 3 compartment lines */
     216              : 
     217            0 :     geometry_dimensions_reinit( out_features_bounds, width + 2.0 * gap, height + sum_of_gaps );
     218            0 :     U8_TRACE_END();
     219            0 : }
     220              : 
     221            0 : void pencil_feature_layouter_private_init_label_dimensions( pencil_feature_layouter_t *this_,
     222              :                                                             PangoLayout *font_layout
     223              :                                                           )
     224              : {
     225            0 :     U8_TRACE_BEGIN();
     226            0 :     assert ( NULL != font_layout );
     227              : 
     228              :     const uint32_t count_features
     229            0 :         = layout_visible_set_get_feature_count( (*this_).layout_data );
     230            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
     231              :     {
     232              :         layout_feature_t *const feature_layout
     233            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_idx );
     234              :         const data_feature_t *const the_feature
     235            0 :             = layout_feature_get_data_const( feature_layout );
     236            0 :         const data_feature_type_t the_feature_type = data_feature_get_main_type( the_feature );
     237              : 
     238            0 :         if ( data_feature_type_inside_compartment( the_feature_type ) )
     239              :         {
     240              :             geometry_dimensions_t min_feature_bounds;
     241            0 :             geometry_dimensions_init_empty( &min_feature_bounds );
     242            0 :             pencil_feature_painter_get_minimum_bounds( &((*this_).feature_painter),
     243              :                                                        the_feature,
     244              :                                                        (*this_).profile,
     245              :                                                        (*this_).pencil_size,
     246              :                                                        font_layout,
     247              :                                                        &min_feature_bounds
     248              :                                                      );
     249              : 
     250            0 :             const geometry_rectangle_t label_box = {
     251              :                 .left = 0.0,
     252              :                 .top = 0.0,
     253            0 :                 .width = geometry_dimensions_get_width( &min_feature_bounds ),
     254            0 :                 .height = geometry_dimensions_get_height( &min_feature_bounds ),
     255              :             };
     256            0 :             layout_feature_set_label_box( feature_layout, &label_box );
     257            0 :             geometry_dimensions_destroy( &min_feature_bounds );
     258              :         }
     259              :     }
     260              : 
     261            0 :     (*this_).label_dimensions_initialized = true;
     262            0 :     U8_TRACE_END();
     263            0 : }
     264              : 
     265            0 : void pencil_feature_layouter_private_layout_lifeline ( pencil_feature_layouter_t *this_,
     266              :                                                        const geometry_rectangle_t *diagram_space,
     267              :                                                        data_diagram_type_t diagram_type,
     268              :                                                        data_classifier_type_t classifier_type,
     269              :                                                        const geometry_rectangle_t *classifier_symbol_box,
     270              :                                                        const geometry_rectangle_t *classifier_envelope_box,
     271              :                                                        layout_feature_t *out_feature_layout )
     272              : {
     273            0 :     U8_TRACE_BEGIN();
     274            0 :     assert ( NULL != diagram_space );
     275            0 :     assert ( NULL != classifier_symbol_box );
     276            0 :     assert ( NULL != classifier_envelope_box );
     277            0 :     assert ( NULL != out_feature_layout );
     278              : 
     279              :     /* get preferred object distance */
     280              :     const double obj_dist
     281            0 :         = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     282            0 :     const double feature_width = obj_dist;
     283              : 
     284              :     const bool lifeline_has_semantics
     285            0 :         = data_rules_classifier_has_scenario_semantics( &((*this_).rules),
     286              :                                                         diagram_type,
     287              :                                                         classifier_type
     288              :                                                       );
     289              : 
     290            0 :     if (( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diagram_type ) && lifeline_has_semantics )
     291            0 :     {
     292            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_RIGHT );
     293            0 :         const double c_right = geometry_rectangle_get_right( classifier_envelope_box );
     294            0 :         const double c_top = geometry_rectangle_get_top( classifier_envelope_box );
     295            0 :         const double c_height = geometry_rectangle_get_height( classifier_envelope_box );
     296            0 :         const double dda_right = geometry_rectangle_get_right ( diagram_space );
     297              :         geometry_rectangle_t lifeline_bounds;
     298            0 :         geometry_rectangle_init ( &lifeline_bounds,
     299              :                                   c_right,
     300            0 :                                   c_top + ( 0.5 * ( c_height - feature_width ) ),
     301            0 :                                   dda_right - c_right - obj_dist,
     302              :                                   feature_width
     303              :                                 );
     304            0 :         layout_feature_set_symbol_box ( out_feature_layout, &lifeline_bounds );
     305            0 :         layout_feature_set_label_box ( out_feature_layout, &lifeline_bounds );
     306              :     }
     307            0 :     else if (( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diagram_type ) && lifeline_has_semantics )
     308            0 :     {
     309            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_DOWN );
     310            0 :         const double c_bottom = geometry_rectangle_get_bottom( classifier_envelope_box );
     311            0 :         const double c_left = geometry_rectangle_get_left( classifier_envelope_box );
     312            0 :         const double c_width = geometry_rectangle_get_width( classifier_envelope_box );
     313            0 :         const double dda_bottom = geometry_rectangle_get_bottom ( diagram_space );
     314              :         geometry_rectangle_t lifeline_bounds;
     315            0 :         geometry_rectangle_init ( &lifeline_bounds,
     316            0 :                                   c_left + ( 0.5 * ( c_width - feature_width ) ),
     317              :                                   c_bottom,
     318              :                                   feature_width,
     319            0 :                                   dda_bottom - c_bottom - obj_dist
     320              :                                 );
     321            0 :         layout_feature_set_symbol_box ( out_feature_layout, &lifeline_bounds );
     322            0 :         layout_feature_set_label_box ( out_feature_layout, &lifeline_bounds );
     323              :     }
     324              :     else /*if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diagram_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diagram_type ))*/
     325              :     {
     326            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_CENTER );
     327            0 :         layout_feature_set_symbol_box ( out_feature_layout, classifier_symbol_box );
     328            0 :         layout_feature_set_label_box ( out_feature_layout, classifier_symbol_box );
     329              :     }
     330              : 
     331            0 :     U8_TRACE_END();
     332            0 : }
     333              : 
     334            0 : void pencil_feature_layouter_private_layout_port_pin ( pencil_feature_layouter_t *this_,
     335              :                                                        data_classifier_type_t classifier_type,
     336              :                                                        const geometry_rectangle_t *classifier_symbol_box,
     337              :                                                        const data_feature_t *the_feature,
     338              :                                                        PangoLayout *font_layout,
     339              :                                                        layout_feature_t *out_feature_layout )
     340              : {
     341            0 :     U8_TRACE_BEGIN();
     342            0 :     assert ( NULL != classifier_symbol_box );
     343            0 :     assert ( NULL != the_feature );
     344            0 :     assert ( NULL != font_layout );
     345            0 :     assert ( NULL != out_feature_layout );
     346              : 
     347              :     /* get preferred object distance */
     348              :     const double gap
     349            0 :         = pencil_size_get_standard_object_border( (*this_).pencil_size );
     350              : 
     351              :     const double port_icon_size
     352            0 :         = pencil_size_get_standard_font_size( (*this_).pencil_size );
     353              : 
     354              :     /* determine the coordinates of the box-line */
     355              :     geometry_rectangle_t classifier_box;
     356            0 :     geometry_rectangle_copy( &classifier_box, classifier_symbol_box );
     357            0 :     geometry_rectangle_shift( &classifier_box, gap, gap );
     358            0 :     geometry_rectangle_enlarge( &classifier_box, -2.0*gap, -2.0*gap );
     359              : 
     360              :     const int32_t list_order
     361            0 :         = data_feature_get_list_order( the_feature );
     362              : 
     363              :     /* position the port icon */
     364            0 :     const bool is_sysml_constraint_block = (classifier_type == DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK);
     365            0 :     const bool is_behavioral = data_classifier_type_is_behavioral( classifier_type );
     366            0 :     const data_feature_type_t feat_type = data_feature_get_main_type( the_feature );
     367            0 :     const bool is_state_entry_exit
     368            0 :         = (( feat_type == DATA_FEATURE_TYPE_ENTRY )||( feat_type == DATA_FEATURE_TYPE_EXIT ));
     369            0 :     const double outwards_distance
     370            0 :         = is_sysml_constraint_block ? 0.0 : (is_behavioral&&(!is_state_entry_exit)) ? port_icon_size : (0.5*port_icon_size);
     371              :     double port_icon_left;
     372              :     double port_icon_top;
     373            0 :     const double show_arrow_in = ( feat_type == DATA_FEATURE_TYPE_IN_PORT_PIN );
     374            0 :     const double show_arrow_out = ( feat_type == DATA_FEATURE_TYPE_OUT_PORT_PIN );
     375            0 :     geometry_direction_t arrow_dir = GEOMETRY_DIRECTION_CENTER;
     376            0 :     if ( list_order < 0 )
     377              :     {
     378              :         static const int32_t INT32_MIN_HALF = INT32_MIN/2;
     379            0 :         if ( list_order < INT32_MIN_HALF )  /* SHOW ON RIGHT BORDER */
     380              :         {
     381            0 :             const double y_pos_rel
     382            0 :                 = (list_order - INT32_MIN_HALF) / ((double)(INT32_MIN_HALF));
     383            0 :             port_icon_left = geometry_rectangle_get_right( &classifier_box ) - port_icon_size + outwards_distance;
     384            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) + y_pos_rel * ( geometry_rectangle_get_height( &classifier_box ) - port_icon_size );
     385            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_LEFT : show_arrow_out ? GEOMETRY_DIRECTION_RIGHT : GEOMETRY_DIRECTION_CENTER;
     386              :         }
     387              :         else  /* SHOW ON TOP BORDER */
     388              :         {
     389            0 :             const double x_pos_rel
     390            0 :                 = (list_order) / ((double)(INT32_MIN_HALF));
     391            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) + x_pos_rel * ( geometry_rectangle_get_width( &classifier_box ) - port_icon_size );
     392            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) - outwards_distance;
     393            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_DOWN : show_arrow_out ? GEOMETRY_DIRECTION_UP : GEOMETRY_DIRECTION_CENTER;
     394              :         }
     395              :     }
     396              :     else
     397              :     {
     398              :         static const int32_t INT32_MAX_HALF = (INT32_MAX/2)+1;  /* round to ceiling */
     399            0 :         if ( list_order < INT32_MAX_HALF )  /* SHOW ON LEFT BORDER */
     400              :         {
     401            0 :             const double y_pos_rel
     402            0 :                 = (list_order) / ((double)(INT32_MAX_HALF));
     403            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) - outwards_distance;
     404            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) + y_pos_rel * ( geometry_rectangle_get_height( &classifier_box ) - port_icon_size );
     405            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_RIGHT : show_arrow_out ? GEOMETRY_DIRECTION_LEFT : GEOMETRY_DIRECTION_CENTER;
     406              :         }
     407              :         else  /* SHOW ON BOTTOM BORDER */
     408              :         {
     409            0 :             const double x_pos_rel
     410            0 :                 = (list_order - INT32_MAX_HALF) / ((double)(INT32_MAX_HALF));
     411            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) + x_pos_rel * ( geometry_rectangle_get_width( &classifier_box ) - port_icon_size );
     412            0 :             port_icon_top = geometry_rectangle_get_bottom( &classifier_box ) - port_icon_size + outwards_distance;
     413            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_UP : show_arrow_out ? GEOMETRY_DIRECTION_DOWN : GEOMETRY_DIRECTION_CENTER;
     414              :         }
     415              :     }
     416              : 
     417              :     /* set feature bounding box */
     418              :     geometry_rectangle_t f_bounds;
     419            0 :     geometry_rectangle_init ( &f_bounds,
     420              :                               port_icon_left,
     421              :                               port_icon_top,
     422              :                               port_icon_size,
     423              :                               port_icon_size
     424              :                             );
     425            0 :     layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     426            0 :     layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     427            0 :     layout_feature_set_icon_direction ( out_feature_layout, arrow_dir );
     428              : 
     429            0 :     U8_TRACE_END();
     430            0 : }
     431              : 
     432            0 : void pencil_feature_layouter_private_layout_interface ( pencil_feature_layouter_t *this_,
     433              :                                                         const geometry_rectangle_t *classifier_symbol_box,
     434              :                                                         const data_feature_t *the_feature,
     435              :                                                         PangoLayout *font_layout,
     436              :                                                         layout_feature_t *out_feature_layout )
     437              : {
     438            0 :     U8_TRACE_BEGIN();
     439            0 :     assert ( NULL != classifier_symbol_box );
     440            0 :     assert ( NULL != the_feature );
     441            0 :     assert ( NULL != font_layout );
     442            0 :     assert ( NULL != out_feature_layout );
     443              : 
     444              :     /* get preferred object size + distance */
     445            0 :     const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     446            0 :     const double interface_icon_size = pencil_size_get_standard_font_size( (*this_).pencil_size );
     447            0 :     const double interface_distance
     448            0 :         = 2.001 * pencil_size_get_preferred_object_distance( (*this_).pencil_size ) + gap;  /* min dist formula as in relationship layouter */
     449              : 
     450            0 :     const int32_t list_order = data_feature_get_list_order( the_feature );
     451              : 
     452              :     /* position the interface icon */
     453            0 :     if ( list_order < 0 )
     454              :     {
     455              :         static const int32_t INT32_MIN_HALF = INT32_MIN/2;
     456            0 :         if ( list_order < INT32_MIN_HALF )  /* SHOW ON RIGHT BORDER */
     457              :         {
     458            0 :             const double y_pos_rel
     459            0 :                 = (list_order - INT32_MIN_HALF) / ((double)(INT32_MIN_HALF));
     460              :             geometry_rectangle_t f_bounds;
     461            0 :             geometry_rectangle_init ( &f_bounds,
     462            0 :                                       geometry_rectangle_get_right( classifier_symbol_box ) + interface_distance,
     463            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) + y_pos_rel * ( geometry_rectangle_get_height( classifier_symbol_box ) - interface_icon_size ),
     464              :                                       interface_icon_size,
     465              :                                       interface_icon_size
     466              :                                     );
     467            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     468            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     469            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_RIGHT );
     470              :         }
     471              :         else  /* SHOW ON TOP BORDER */
     472              :         {
     473            0 :             const double x_pos_rel
     474            0 :                 = (list_order) / ((double)(INT32_MIN_HALF));
     475              :             geometry_rectangle_t f_bounds;
     476            0 :             geometry_rectangle_init ( &f_bounds,
     477            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) + x_pos_rel * ( geometry_rectangle_get_width( classifier_symbol_box ) - interface_icon_size ),
     478            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) - interface_distance - interface_icon_size,
     479              :                                       interface_icon_size,
     480              :                                       interface_icon_size
     481              :                                     );
     482            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     483            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     484            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_UP );
     485              :         }
     486              :     }
     487              :     else
     488              :     {
     489              :         static const int32_t INT32_MAX_HALF = (INT32_MAX/2)+1;  /* round to ceiling */
     490            0 :         if ( list_order < INT32_MAX_HALF )  /* SHOW ON LEFT BORDER */
     491              :         {
     492            0 :             const double y_pos_rel
     493            0 :                 = (list_order) / ((double)(INT32_MAX_HALF));
     494              :             geometry_rectangle_t f_bounds;
     495            0 :             geometry_rectangle_init ( &f_bounds,
     496            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) - interface_distance - interface_icon_size,
     497            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) + y_pos_rel * ( geometry_rectangle_get_height( classifier_symbol_box ) - interface_icon_size ),
     498              :                                       interface_icon_size,
     499              :                                       interface_icon_size
     500              :                                     );
     501            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     502            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     503            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_LEFT );
     504              :         }
     505              :         else  /* SHOW ON BOTTOM BORDER */
     506              :         {
     507            0 :             const double x_pos_rel
     508            0 :                 = (list_order - INT32_MAX_HALF) / ((double)(INT32_MAX_HALF));
     509              :             geometry_rectangle_t f_bounds;
     510            0 :             geometry_rectangle_init ( &f_bounds,
     511            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) + x_pos_rel * ( geometry_rectangle_get_width( classifier_symbol_box ) - interface_icon_size ),
     512            0 :                                       geometry_rectangle_get_bottom( classifier_symbol_box ) + interface_distance,
     513              :                                       interface_icon_size,
     514              :                                       interface_icon_size
     515              :                                     );
     516            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     517            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     518            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_DOWN );
     519              :         }
     520              :     }
     521              : 
     522            0 :     if ( DATA_FEATURE_TYPE_PROVIDED_INTERFACE == data_feature_get_main_type (the_feature) )
     523              :     {
     524              :         /* a provided interface has no direction, it is a circle */
     525            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_CENTER );
     526              :     }
     527              : 
     528            0 :     U8_TRACE_END();
     529            0 : }
     530              : 
     531            0 : void pencil_feature_layouter_private_layout_compartment ( pencil_feature_layouter_t *this_,
     532              :                                                           const geometry_rectangle_t *classifier_space,
     533              :                                                           PangoLayout *font_layout,
     534              :                                                           layout_feature_t *io_feature_layout )
     535              : {
     536            0 :     U8_TRACE_BEGIN();
     537            0 :     assert( NULL != classifier_space );
     538            0 :     assert( NULL != font_layout );
     539            0 :     assert( NULL != io_feature_layout );
     540              : 
     541              :     /* feature label sizes are already precalculated */
     542            0 :     assert( (*this_).label_dimensions_initialized );
     543              : 
     544              :     /* define names for input data */
     545              :     const layout_visible_classifier_t * const vis_classfy
     546            0 :         = layout_feature_get_classifier_const( io_feature_layout );
     547            0 :     assert( NULL != vis_classfy );
     548            0 :     const data_row_t diagele_id = layout_visible_classifier_get_diagramelement_id( vis_classfy );
     549            0 :     const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     550            0 :     const data_feature_t *const the_feature = layout_feature_get_data_const( io_feature_layout );
     551              : 
     552              :     /* calculate the feat_top by summing up the heights of the features above */
     553            0 :     double feat_top = geometry_rectangle_get_top( classifier_space );
     554            0 :     const uint32_t num_features = layout_visible_set_get_feature_count( (*this_).layout_data );
     555            0 :     for ( uint32_t f_probe_idx = 0; f_probe_idx < num_features; f_probe_idx ++ )
     556              :     {
     557              :         const layout_feature_t *const f_probe_layout
     558            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_probe_idx );
     559            0 :         assert( NULL != f_probe_layout );
     560              :         const layout_visible_classifier_t *const probe_vis_classfy
     561            0 :             = layout_feature_get_classifier_const( f_probe_layout );
     562            0 :         assert( NULL != probe_vis_classfy );
     563              : 
     564              :         /* check if this f_probe_layout has the same diagram element id as the_feature */
     565            0 :         if ( diagele_id == layout_visible_classifier_get_diagramelement_id( probe_vis_classfy ) )
     566              :         {
     567              :             /* this is a feature of the same visible_classifier_t */
     568              :             /* define names for input data */
     569              :             const data_feature_t *f_probe_data;
     570            0 :             f_probe_data = layout_feature_get_data_const( f_probe_layout );
     571            0 :             assert( NULL != f_probe_data );
     572            0 :             const data_feature_type_t f_probe_type = data_feature_get_main_type ( f_probe_data );
     573            0 :             if ( data_feature_type_inside_compartment( f_probe_type ) )
     574              :             {
     575            0 :                 const bool is_above
     576            0 :                     = (( data_feature_get_list_order( f_probe_data ) < data_feature_get_list_order( the_feature ))
     577            0 :                     || (( data_feature_get_list_order( f_probe_data ) == data_feature_get_list_order( the_feature ) )
     578            0 :                     && ( data_feature_get_row_id( f_probe_data ) < data_feature_get_row_id( the_feature ) )));
     579            0 :                 if ( is_above )
     580              :                 {
     581              :                     const geometry_rectangle_t *const probe_label_box
     582            0 :                         = layout_feature_get_label_box_const( f_probe_layout );
     583            0 :                     feat_top += geometry_rectangle_get_height( probe_label_box );
     584              :                 }
     585              :             }
     586              :         }
     587              :     }
     588              : 
     589              :     /* determine compartments above the current */
     590            0 :     const data_feature_type_t f_type = data_feature_get_main_type (the_feature);
     591            0 :     const uint32_t count_compartments_above
     592              :         = ( DATA_FEATURE_TYPE_PROPERTY == f_type )
     593              :         ? 0
     594            0 :         : ( DATA_FEATURE_TYPE_OPERATION == f_type )
     595              :         ? 1
     596              :         : ( DATA_FEATURE_TYPE_TAGGED_VALUE == f_type )
     597              :         ? 2  /* first compartment for properties, second for operations, third for tagged values */
     598              :         : 2; /* the last compartment is for all unknown feature types. */
     599              :              /* this may happen if a new database file has been read by an old program version */
     600              :              /* note that today, there is no separator line yet - so the number is the same */
     601            0 :     feat_top += ( count_compartments_above * 2 * gap ) + 2.0 * gap;
     602              : 
     603              :     /* determine the bounds of the feature */
     604              :     const geometry_rectangle_t *const feat_label_box
     605            0 :         = layout_feature_get_label_box_const( io_feature_layout );
     606              : 
     607              :     /* layout feature into parent classifier */
     608            0 :     const geometry_rectangle_t label_box = {
     609            0 :         .left = geometry_rectangle_get_left( classifier_space ) + gap,
     610              :         .top = feat_top,
     611            0 :         .width = geometry_rectangle_get_width( feat_label_box ),
     612            0 :         .height = geometry_rectangle_get_height( feat_label_box )
     613              :     };
     614            0 :     const geometry_rectangle_t feat_bounds = {
     615            0 :         .left = geometry_rectangle_get_left( classifier_space ),
     616              :         .top = feat_top,
     617            0 :         .width = geometry_rectangle_get_width( feat_label_box ) + 2.0 * gap,
     618            0 :         .height = geometry_rectangle_get_height( feat_label_box )
     619              :     };
     620              : 
     621            0 :     layout_feature_set_label_box( io_feature_layout, &label_box );
     622            0 :     layout_feature_set_symbol_box( io_feature_layout, &feat_bounds );
     623            0 :     layout_feature_set_icon_direction( io_feature_layout, GEOMETRY_DIRECTION_CENTER );  /* dummy direction */
     624              : 
     625            0 :     U8_TRACE_END();
     626            0 : }
     627              : 
     628              : 
     629              : /*
     630              : Copyright 2017-2025 Andreas Warnke
     631              : 
     632              : Licensed under the Apache License, Version 2.0 (the "License");
     633              : you may not use this file except in compliance with the License.
     634              : You may obtain a copy of the License at
     635              : 
     636              :     http://www.apache.org/licenses/LICENSE-2.0
     637              : 
     638              : Unless required by applicable law or agreed to in writing, software
     639              : distributed under the License is distributed on an "AS IS" BASIS,
     640              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     641              : See the License for the specific language governing permissions and
     642              : limitations under the License.
     643              : */
        

Generated by: LCOV version 2.0-1