LCOV - code coverage report
Current view: top level - pencil/source - pencil_feature_layouter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 0 294 0.0 %
Date: 2024-04-07 11:14:42 Functions: 0 10 0.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             :                                    pencil_layout_data_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) PENCIL_LAYOUT_DATA_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 :         = pencil_layout_data_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 :         = pencil_layout_data_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 :             = pencil_layout_data_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_id_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 :         = pencil_layout_data_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 :             = pencil_layout_data_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 :         = pencil_layout_data_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 :             = pencil_layout_data_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_id_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 = pencil_layout_data_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 :             = pencil_layout_data_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-2024 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 1.16