LCOV - code coverage report
Current view: top level - gui/source/sketch - gui_sketch_card_painter.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.69.0_covts Lines: 0.0 % 457 0
Test Date: 2026-03-08 20:58:47 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /* File: gui_sketch_card_painter.c; Copyright and License: see below */
       2              : 
       3              : #include "sketch/gui_sketch_card_painter.h"
       4              : #include "u8list/universal_array_index_iterator.h"
       5              : #include "u8list/universal_array_index_sorter.h"
       6              : #include "u8/u8_trace.h"
       7              : #include "gui_gtk.h"
       8              : #include <assert.h>
       9              : 
      10            0 : void gui_sketch_card_painter_init( gui_sketch_card_painter_t *this_,
      11              :                                    const gui_resources_t *resources,
      12              :                                    gui_sketch_texture_t *texture_downloader )
      13              : {
      14            0 :     U8_TRACE_BEGIN();
      15            0 :     assert( resources != NULL );
      16            0 :     assert( texture_downloader != NULL );
      17              : 
      18            0 :     gui_sketch_style_init( &((*this_).sketch_style) );
      19            0 :     (*this_).resources = resources;
      20            0 :     (*this_).texture_downloader = texture_downloader;
      21              : 
      22            0 :     U8_TRACE_END();
      23            0 : }
      24              : 
      25            0 : void gui_sketch_card_painter_destroy( gui_sketch_card_painter_t *this_ )
      26              : {
      27            0 :     U8_TRACE_BEGIN();
      28              : 
      29            0 :     (*this_).resources = NULL;
      30            0 :     (*this_).texture_downloader = NULL;
      31            0 :     gui_sketch_style_destroy( &((*this_).sketch_style) );
      32              : 
      33            0 :     U8_TRACE_END();
      34            0 : }
      35              : 
      36            0 : void gui_sketch_card_painter_draw_overlay( gui_sketch_card_painter_t *this_,
      37              :                                            gui_tool_t selected_tool,
      38              :                                            const gui_sketch_drag_state_t *drag_state,
      39              :                                            const gui_sketch_card_t *card_under_mouse,
      40              :                                            gui_marked_set_t *marked_objects,
      41              :                                            cairo_t *cr )
      42              : {
      43            0 :     U8_TRACE_BEGIN();
      44            0 :     assert( NULL != drag_state );
      45            0 :     assert( NULL != cr );
      46              : 
      47            0 :     switch ( selected_tool )
      48              :     {
      49            0 :         case GUI_TOOL_NAVIGATE:
      50              :         {
      51            0 :             gui_sketch_card_painter_private_draw_nav_mode( this_, drag_state, card_under_mouse, cr );
      52              :         }
      53            0 :         break;
      54              : 
      55            0 :         case GUI_TOOL_EDIT:
      56              :         {
      57            0 :             gui_sketch_card_painter_private_draw_edit_mode( this_, drag_state, card_under_mouse, cr );
      58              :         }
      59            0 :         break;
      60              : 
      61            0 :         case GUI_TOOL_CREATE:
      62              :         {
      63            0 :             const data_id_t highlighted = gui_marked_set_get_highlighted( marked_objects );
      64            0 :             const layout_subelement_kind_t highlighted_kind = gui_marked_set_get_highlighted_kind( marked_objects );
      65            0 :             gui_sketch_card_painter_private_draw_create_mode( this_,
      66              :                                                               drag_state,
      67              :                                                               card_under_mouse,
      68              :                                                               data_id_get_table(&highlighted),
      69              :                                                               highlighted_kind,
      70              :                                                               cr
      71              :                                                             );
      72              :         }
      73            0 :         break;
      74              : 
      75            0 :         case GUI_TOOL_SEARCH:
      76              :         {
      77              :         }
      78            0 :         break;
      79              : 
      80            0 :         default:
      81              :         {
      82            0 :             U8_LOG_ERROR("selected_tool is out of range");
      83              :         }
      84            0 :         break;
      85              :     }
      86              : 
      87            0 :     U8_TRACE_END();
      88            0 : }
      89              : 
      90            0 : void gui_sketch_card_painter_private_draw_nav_mode( gui_sketch_card_painter_t *this_,
      91              :                                                     const gui_sketch_drag_state_t *drag_state,
      92              :                                                     const gui_sketch_card_t *card_under_mouse,
      93              :                                                     cairo_t *cr )
      94              : {
      95            0 :     U8_TRACE_BEGIN();
      96            0 :     assert( NULL != drag_state );
      97            0 :     assert( NULL != cr );
      98              : 
      99            0 :     if ( gui_sketch_drag_state_is_waiting_for_move ( drag_state ) )
     100              :     {
     101            0 :         const data_full_id_t *const dragged_object = gui_sketch_drag_state_get_dragged_object_const( drag_state );
     102            0 :         const data_id_t *const dragged_primary = data_full_id_get_primary_id_const( dragged_object );
     103            0 :         const bool dragging_diagram = ( DATA_TABLE_DIAGRAM == data_id_get_table( dragged_primary ) );
     104            0 :         if ( dragging_diagram )
     105              :         {
     106            0 :             const int32_t to_x = gui_sketch_drag_state_get_to_x ( drag_state );
     107            0 :             const int32_t to_y = gui_sketch_drag_state_get_to_y ( drag_state );
     108            0 :             GdkTexture *icon = gui_resources_get_sketch_move_v( (*this_).resources );
     109            0 :             gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     110              :         }
     111              :     }
     112              : 
     113            0 :     U8_TRACE_END();
     114            0 : }
     115              : 
     116            0 : void gui_sketch_card_painter_private_draw_edit_mode( gui_sketch_card_painter_t *this_,
     117              :                                                      const gui_sketch_drag_state_t *drag_state,
     118              :                                                      const gui_sketch_card_t *card_under_mouse,
     119              :                                                      cairo_t *cr )
     120              : {
     121            0 :     U8_TRACE_BEGIN();
     122            0 :     assert( NULL != drag_state );
     123            0 :     assert( NULL != cr );
     124              : 
     125            0 :     if ( gui_sketch_drag_state_is_dragging ( drag_state ) )
     126              :     {
     127            0 :         const data_full_id_t *const dragged_object = gui_sketch_drag_state_get_dragged_object_const( drag_state );
     128            0 :         const data_id_t *const dragged_primary = data_full_id_get_primary_id_const( dragged_object );
     129            0 :         const bool dragging_classifier = ( DATA_TABLE_DIAGRAMELEMENT == data_id_get_table( dragged_primary ) );
     130              : 
     131            0 :         if ( NULL != card_under_mouse )
     132              :         {
     133            0 :             const data_diagram_t *diag = gui_sketch_card_get_diagram_const ( card_under_mouse );
     134            0 :             const data_diagram_type_t diag_type = data_diagram_get_diagram_type( diag );
     135            0 :             const bool draw_2d_diagram
     136              :                 = (( diag_type != DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM )
     137            0 :                 && ( diag_type != DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM )
     138            0 :                 && ( diag_type != DATA_DIAGRAM_TYPE_LIST ));
     139              : 
     140            0 :             if ( draw_2d_diagram && dragging_classifier )
     141              :             {
     142              :                 /* draw new grid lines that visualize the order of classifiers */
     143            0 :                 const int32_t to_x = gui_sketch_drag_state_get_to_x ( drag_state );
     144            0 :                 const int32_t to_y = gui_sketch_drag_state_get_to_y ( drag_state );
     145            0 :                 gui_sketch_card_painter_private_visualize_order( this_, card_under_mouse, to_x, to_y, cr );
     146              :             }
     147              :         }
     148              :     }
     149              : 
     150            0 :     if ( gui_sketch_drag_state_is_waiting_for_move ( drag_state ) )
     151              :     {
     152            0 :         const data_full_id_t *const dragged_object = gui_sketch_drag_state_get_dragged_object_const( drag_state );
     153            0 :         const data_id_t *const dragged_primary = data_full_id_get_primary_id_const( dragged_object );
     154            0 :         const bool dragging_classifier = ( DATA_TABLE_DIAGRAMELEMENT == data_id_get_table( dragged_primary ) );
     155            0 :         const bool dragging_feature = ( DATA_TABLE_FEATURE == data_id_get_table( dragged_primary ) );
     156            0 :         const bool dragging_relationship = ( DATA_TABLE_RELATIONSHIP == data_id_get_table( dragged_primary ) );
     157            0 :         const int32_t to_x = gui_sketch_drag_state_get_to_x ( drag_state );
     158            0 :         const int32_t to_y = gui_sketch_drag_state_get_to_y ( drag_state );
     159            0 :         if ( dragging_classifier || dragging_feature )
     160            0 :         {
     161            0 :             GdkTexture *icon = gui_resources_get_sketch_move_2d( (*this_).resources );
     162            0 :             gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     163              :         }
     164            0 :         else if ( dragging_relationship )
     165              :         {
     166            0 :             const data_diagram_t *diag = gui_sketch_card_get_diagram_const ( card_under_mouse );
     167            0 :             if ( NULL != card_under_mouse )
     168              :             {
     169            0 :                 const data_diagram_type_t diag_type = data_diagram_get_diagram_type( diag );
     170            0 :                 if ( diag_type == DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM )
     171              :                 {
     172            0 :                     GdkTexture *icon = gui_resources_get_sketch_move_v( (*this_).resources );
     173            0 :                     gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     174              :                 }
     175            0 :                 else if ( diag_type == DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM )
     176              :                 {
     177            0 :                     GdkTexture *icon = gui_resources_get_sketch_move_h( (*this_).resources );
     178            0 :                     gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     179              :                 }
     180              :             }
     181              :         }
     182              :     }
     183              : 
     184            0 :     U8_TRACE_END();
     185            0 : }
     186              : 
     187            0 : void gui_sketch_card_painter_private_draw_create_mode( gui_sketch_card_painter_t *this_,
     188              :                                                        const gui_sketch_drag_state_t *drag_state,
     189              :                                                        const gui_sketch_card_t *card_under_mouse,
     190              :                                                        data_table_t highlighted_table,
     191              :                                                        layout_subelement_kind_t highlighted_kind,
     192              :                                                        cairo_t *cr )
     193              : {
     194            0 :     U8_TRACE_BEGIN();
     195            0 :     assert( NULL != drag_state );
     196            0 :     assert( NULL != cr );
     197              : 
     198            0 :     if ( gui_sketch_drag_state_is_dragging ( drag_state ) )
     199              :     {
     200              :         /* draw a line */
     201            0 :         const int32_t from_x = gui_sketch_drag_state_get_from_x ( drag_state );
     202            0 :         const int32_t from_y = gui_sketch_drag_state_get_from_y ( drag_state );
     203            0 :         const int32_t to_x = gui_sketch_drag_state_get_to_x ( drag_state );
     204            0 :         const int32_t to_y = gui_sketch_drag_state_get_to_y ( drag_state );
     205            0 :         gui_sketch_card_painter_private_draw_arrow( this_, from_x, from_y, to_x, to_y, cr );
     206              :     }
     207              :     else /* ! gui_sketch_drag_state_is_dragging() */
     208              :     {
     209            0 :         if ( NULL != card_under_mouse )
     210              :         {
     211            0 :             const bool draw_new_classifier
     212            0 :                 = (( highlighted_table == DATA_TABLE_CLASSIFIER )&&( highlighted_kind == LAYOUT_SUBELEMENT_KIND_SPACE ))
     213            0 :                 || (( highlighted_table == DATA_TABLE_DIAGRAMELEMENT )&&( highlighted_kind == LAYOUT_SUBELEMENT_KIND_SPACE ))
     214            0 :                 || (( highlighted_table == DATA_TABLE_DIAGRAM )&&( highlighted_kind == LAYOUT_SUBELEMENT_KIND_SPACE ));
     215            0 :             const bool draw_new_feature
     216            0 :                 = (( highlighted_table == DATA_TABLE_CLASSIFIER )&&( highlighted_kind == LAYOUT_SUBELEMENT_KIND_OUTLINE ))
     217            0 :                 || (( highlighted_table == DATA_TABLE_DIAGRAMELEMENT )&&( highlighted_kind == LAYOUT_SUBELEMENT_KIND_OUTLINE ));
     218            0 :             const bool draw_new_relationship
     219            0 :                 = (( highlighted_table == DATA_TABLE_CLASSIFIER )&&( highlighted_kind != LAYOUT_SUBELEMENT_KIND_SPACE ))
     220            0 :                 || (( highlighted_table == DATA_TABLE_DIAGRAMELEMENT )&&( highlighted_kind != LAYOUT_SUBELEMENT_KIND_SPACE ))
     221            0 :                 || ( highlighted_table == DATA_TABLE_FEATURE );
     222              : 
     223            0 :             const data_diagram_t *diag = gui_sketch_card_get_diagram_const ( card_under_mouse );
     224            0 :             const data_diagram_type_t diag_type = data_diagram_get_diagram_type( diag );
     225            0 :             const bool draw_2d_diagram
     226              :                 = (( diag_type != DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM )
     227            0 :                 && ( diag_type != DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM )
     228            0 :                 && ( diag_type != DATA_DIAGRAM_TYPE_LIST ));
     229              : 
     230              :             /* get coordinates */
     231            0 :             const int32_t to_x = gui_sketch_drag_state_get_to_x ( drag_state );
     232            0 :             const int32_t to_y = gui_sketch_drag_state_get_to_y ( drag_state );
     233              : 
     234              :             /* draw grid */
     235            0 :             if (( draw_new_classifier )&&( draw_2d_diagram ))
     236              :             {
     237              :                 /* draw new grid lines that visualize the order of classifiers */
     238            0 :                 gui_sketch_card_painter_private_visualize_order( this_, card_under_mouse, to_x, to_y, cr );
     239              :             }
     240              : 
     241              :             /* draw boxes and arrow icons */
     242            0 :             if ( draw_new_feature )
     243              :             {
     244            0 :                 assert( draw_new_relationship );
     245            0 :                 assert( ! draw_new_classifier );
     246            0 :                 GdkTexture *icon = gui_resources_get_sketch_refine( (*this_).resources );
     247            0 :                 gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     248              :             }
     249            0 :             else if ( draw_new_relationship )
     250              :             {
     251            0 :                 assert( ! draw_new_classifier );
     252            0 :                 GdkTexture *icon = gui_resources_get_sketch_relate( (*this_).resources );
     253            0 :                 gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     254              :             }
     255            0 :             else if ( draw_new_classifier )
     256              :             {
     257            0 :                 GdkTexture *icon = gui_resources_get_sketch_create( (*this_).resources );
     258            0 :                 gui_sketch_texture_draw( (*this_).texture_downloader, icon, to_x-16, to_y-16-2, cr );  /* 2 is extra gap*/
     259              :             }
     260              :             else
     261              :             {
     262              :                 /* draw nothing */
     263              :             }
     264              :         }
     265              :     }
     266              : 
     267            0 :     U8_TRACE_END();
     268            0 : }
     269              : 
     270            0 : void gui_sketch_card_painter_private_draw_arrow( gui_sketch_card_painter_t *this_,
     271              :                                                  int32_t from_x,
     272              :                                                  int32_t from_y,
     273              :                                                  int32_t to_x,
     274              :                                                  int32_t to_y,
     275              :                                                  cairo_t *cr )
     276              : {
     277            0 :     U8_TRACE_BEGIN();
     278            0 :     assert( NULL != cr );
     279              : 
     280            0 :     const GdkRGBA high_color = gui_sketch_style_get_highlight_color( &((*this_).sketch_style) );
     281            0 :     cairo_set_source_rgba( cr, high_color.red, high_color.green, high_color.blue, high_color.alpha );
     282            0 :     cairo_move_to ( cr, from_x, from_y );
     283            0 :     cairo_line_to ( cr, to_x, to_y );
     284            0 :     cairo_stroke (cr);
     285              : 
     286              :     /* draw the arrow tip */
     287              :     int clock_direction;  /* the gdk coordinate system if bottom up - and out clock is also mirrored! */
     288            0 :     const int32_t x_dist = to_x - from_x;
     289            0 :     const int32_t y_dist = to_y - from_y;
     290            0 :     if ( x_dist == 0 )
     291              :     {
     292            0 :         clock_direction = ( y_dist < 0 ) ? 6 : 0;
     293              :     }
     294              :     else
     295              :     {
     296            0 :         int32_t y_x_deci_ratio = ( y_dist * 10 ) / x_dist;
     297            0 :         if ( y_x_deci_ratio < 3 /* = 0.26 = tan(15 deg) */ )
     298              :         {
     299            0 :             if ( y_x_deci_ratio < -10 /* = -1.00 = tan(-45 deg) */ )
     300              :             {
     301            0 :                 if ( y_x_deci_ratio < -37 /* = -3.73 = tan(-75 deg) */ )
     302              :                 {
     303            0 :                     clock_direction = 6;
     304              :                 }
     305              :                 else
     306              :                 {
     307            0 :                     clock_direction = 5;
     308              :                 }
     309              :             }
     310              :             else
     311              :             {
     312            0 :                 if ( y_x_deci_ratio < -2 /* = -0.26 = tan(-15 deg) */ )
     313              :                 {
     314            0 :                     clock_direction = 4;
     315              :                 }
     316              :                 else
     317              :                 {
     318            0 :                     clock_direction = 3;
     319              :                 }
     320              :             }
     321              :         }
     322              :         else
     323              :         {
     324            0 :             if ( y_x_deci_ratio < 10 /* = 1.00 = tan(45 deg) */ )
     325              :             {
     326            0 :                 clock_direction = 2;
     327              :             }
     328              :             else
     329              :             {
     330            0 :                 if ( y_x_deci_ratio < 38 /* = 3.73 = tan(75 deg) */ )
     331              :                 {
     332            0 :                     clock_direction = 1;
     333              :                 }
     334              :                 else
     335              :                 {
     336            0 :                     clock_direction = 0;
     337              :                 }
     338              :             }
     339              :         }
     340            0 :         if ( x_dist < 0 )
     341              :         {
     342            0 :             clock_direction = (clock_direction+6)%12;
     343              :         }
     344              :     }
     345              :     const static int32_t DX[12][2]={{-6,+6},{-9,  0},{-11,-4},{-9,-9},{-4,-11},{  0,-9},{+6,-6},{+9,  0},{+11,+4},{+9,+9},{+4,+11},{  0,+9}};
     346              :     const static int32_t DY[12][2]={{-9,-9},{-4,-11},{  0,-9},{+6,-6},{+9,  0},{+11,+4},{+9,+9},{+4,+11},{  0,+9},{+6,-6},{-9,  0},{-11,-4}};
     347            0 :     cairo_move_to ( cr, to_x + DX[clock_direction][0], to_y + DY[clock_direction][0] );
     348            0 :     cairo_line_to ( cr, to_x, to_y );
     349            0 :     cairo_line_to ( cr, to_x + DX[clock_direction][1], to_y + DY[clock_direction][1] );
     350            0 :     cairo_stroke (cr);
     351              : 
     352            0 :     U8_TRACE_END();
     353            0 : }
     354              : 
     355            0 : void gui_sketch_card_painter_private_visualize_order( gui_sketch_card_painter_t *this_,
     356              :                                                       const gui_sketch_card_t *card_under_mouse,
     357              :                                                       int32_t x,
     358              :                                                       int32_t y,
     359              :                                                       cairo_t *cr )
     360              : {
     361            0 :     U8_TRACE_BEGIN();
     362            0 :     assert( NULL != card_under_mouse );
     363            0 :     assert( NULL != cr );
     364              : 
     365              :     /* fetch input data: subwidget */
     366            0 :     const shape_int_rectangle_t bounds = gui_sketch_card_get_bounds( card_under_mouse );
     367            0 :     const int32_t left = shape_int_rectangle_get_left(&bounds);
     368            0 :     const int32_t top = shape_int_rectangle_get_top(&bounds);
     369            0 :     const int32_t right = shape_int_rectangle_get_right(&bounds);
     370            0 :     const int32_t bottom = shape_int_rectangle_get_bottom(&bounds);
     371              : 
     372              :     /* fetch input data: grid */
     373            0 :     const geometry_grid_t *const grid = gui_sketch_card_get_grid_const( card_under_mouse);
     374            0 :     const geometry_grid_kind_t grid_kind = geometry_grid_get_kind( grid );
     375            0 :     const double snap_interval = gui_sketch_style_get_snap_to_grid( &((*this_).sketch_style) );
     376            0 :     const geometry_non_linear_scale_t *const x_scale = geometry_grid_get_x_scale_const( grid );
     377            0 :     const int32_t order_at_x = geometry_non_linear_scale_get_order( x_scale, (double) x, snap_interval );
     378            0 :     const geometry_non_linear_scale_t *const y_scale = geometry_grid_get_y_scale_const( grid );
     379            0 :     const int32_t order_at_y = geometry_non_linear_scale_get_order( y_scale, (double) y, snap_interval );
     380              : 
     381              :     /* define own distances */
     382            0 :     const double gap = 3.0;
     383            0 :     const double curve_space = 3.0 * gap;
     384              : 
     385              :     /* fetch input data: visible set */
     386            0 :     const layout_visible_set_t *const layout_data = gui_sketch_card_get_visible_set( card_under_mouse );
     387            0 :     const uint32_t classifiers = layout_visible_set_get_visible_classifier_count( layout_data );
     388              : 
     389              :     /* prepare draw */
     390            0 :     const GdkRGBA high_color = gui_sketch_style_get_highlight_color( &((*this_).sketch_style) );
     391            0 :     cairo_set_source_rgba( cr, high_color.red, high_color.green, high_color.blue, high_color.alpha );
     392              : 
     393              :     /* to draw x, follow y from top to bottom */
     394            0 :     if (( grid_kind == GEOMETRY_GRID_KIND_X )||( grid_kind == GEOMETRY_GRID_KIND_XY ))
     395              :     {
     396              :         /* order visible set by top y coordinates of classifiers */
     397              :         universal_array_index_sorter_t sorted;
     398            0 :         universal_array_index_sorter_init( &sorted );
     399            0 :         for ( uint32_t idx = 0; idx < classifiers; idx ++ )
     400              :         {
     401              :             const layout_visible_classifier_t *const classifier
     402            0 :                 = layout_visible_set_get_visible_classifier_const( layout_data, idx );
     403              : 
     404            0 :             const geometry_rectangle_t *const envelope = layout_visible_classifier_get_envelope_box_const( classifier );
     405            0 :             const int64_t weight = geometry_rectangle_get_top( envelope );
     406            0 :             const u8_error_t insert_error = universal_array_index_sorter_insert( &sorted, idx, weight );
     407            0 :             if ( U8_ERROR_NONE != insert_error )
     408              :             {
     409            0 :                 U8_LOG_WARNING( "not all rectangles are considered for the top-to-bottom line" );
     410              :             }
     411              :         }
     412              : 
     413              :         /* process rectangles top to bottom */
     414              :         /* local variables represent 3 points: */
     415              :         /* current_pos_x / current_pos_y : The position where the already drawn line ends */
     416              :         /* planned_pos_x / planned_pos_y : The position that would be the next unless the next loop finds an earlier position */
     417              :         /* draw_to_pos_x / draw_to_pos_y : While drawing, this is a temporary value storing the next current_pos position */
     418            0 :         double current_pos_x = x;
     419            0 :         double current_pos_y = top;
     420            0 :         double planned_pos_x = x;
     421            0 :         double planned_pos_y = top;  /* the planned next y - may be superseded by the next classifier */
     422            0 :         cairo_move_to( cr, x, top );
     423              : 
     424              :         universal_array_index_iterator_t sorted_index_iter;
     425            0 :         universal_array_index_iterator_init( &sorted_index_iter, &sorted );
     426            0 :         while ( universal_array_index_iterator_has_next( &sorted_index_iter ) )
     427              :         {
     428            0 :             const uint32_t idx = universal_array_index_iterator_next( &sorted_index_iter );
     429              :             const layout_visible_classifier_t *const classifier
     430            0 :                 = layout_visible_set_get_visible_classifier_const( layout_data, idx );
     431              : 
     432              :             /* skip classifiers which contain others, these are not positioned according to their order value */
     433            0 :             const uint32_t children = layout_visible_set_count_descendants( layout_data, classifier );
     434            0 :             if ( children == 0 )
     435              :             {
     436            0 :                 const data_visible_classifier_t *const vis_data = layout_visible_classifier_get_data_const( classifier );
     437            0 :                 const data_classifier_t *const c_data = data_visible_classifier_get_classifier_const( vis_data );
     438            0 :                 const int32_t c_x_order = data_classifier_get_x_order( c_data );
     439            0 :                 const geometry_rectangle_t *const envelope = layout_visible_classifier_get_envelope_box_const( classifier );
     440            0 :                 const double envelope_left = geometry_rectangle_get_left( envelope );
     441            0 :                 const double envelope_right = geometry_rectangle_get_right( envelope );
     442            0 :                 const double envelope_top = geometry_rectangle_get_top( envelope );
     443            0 :                 const double envelope_bottom = geometry_rectangle_get_bottom( envelope );
     444              :                 /* if line passes through the classifier, center on symbol, not on envelope */
     445            0 :                 const geometry_rectangle_t *const symbol = layout_visible_classifier_get_symbol_box_const( classifier );
     446            0 :                 const double symbol_center_x = geometry_rectangle_get_center_x( symbol );
     447              : 
     448            0 :                 const bool pass_through_center_x = ( c_x_order == order_at_x );
     449            0 :                 const bool pass_on_left = ( c_x_order > order_at_x ) && ( envelope_left < x );
     450            0 :                 const bool pass_on_right = ( c_x_order < order_at_x ) && ( envelope_right > x );
     451            0 :                 const bool ignored = !( pass_through_center_x || pass_on_left || pass_on_right );
     452            0 :                 const double draw_to_pos_y = envelope_top - gap;
     453            0 :                 double draw_to_pos_x = x;
     454            0 :                 if ( pass_through_center_x )
     455              :                 {
     456            0 :                     draw_to_pos_x = symbol_center_x;
     457              :                 }
     458            0 :                 if ( pass_on_left )
     459              :                 {
     460            0 :                     draw_to_pos_x = envelope_left - gap;
     461              :                 }
     462            0 :                 if ( pass_on_right )
     463              :                 {
     464            0 :                     draw_to_pos_x = envelope_right + gap;
     465              :                 }
     466            0 :                 if ( ! ignored )
     467              :                 {
     468              :                     /* if planned_pos_x not at x and enough space to draw */
     469              :                     /* 1) a return to x and 2) a comeback to new draw_to_pos_x */
     470            0 :                     if ( (( planned_pos_x < ( x - 0.001 ) )||( planned_pos_x > ( x + 0.001 ) ))
     471            0 :                          && ( planned_pos_y + ( 2 * curve_space ) < draw_to_pos_y ) )
     472              :                     {
     473            0 :                         cairo_line_to( cr, current_pos_x, planned_pos_y );
     474            0 :                         cairo_curve_to( cr,
     475              :                                         current_pos_x,
     476              :                                         planned_pos_y + curve_space,
     477              :                                         x,
     478              :                                         planned_pos_y,
     479              :                                         x,
     480              :                                         planned_pos_y + curve_space
     481              :                                       );
     482            0 :                         current_pos_x = x;
     483            0 :                         current_pos_y = planned_pos_y + curve_space;
     484              :                     }
     485              : 
     486              :                     /* if there is enough space to draw a line before drawing a curve to draw_to_pos_x */
     487            0 :                     if ( ( current_pos_y + curve_space ) < draw_to_pos_y )
     488              :                     {
     489            0 :                         cairo_line_to( cr, current_pos_x, draw_to_pos_y - curve_space );
     490            0 :                         current_pos_y = draw_to_pos_y - curve_space;
     491              :                     }
     492              : 
     493              :                     /* draw begin of current pass-by */
     494            0 :                     cairo_curve_to( cr,
     495              :                                     current_pos_x,
     496              :                                     draw_to_pos_y,
     497              :                                     draw_to_pos_x,
     498              :                                     current_pos_y,
     499              :                                     draw_to_pos_x,
     500              :                                     draw_to_pos_y
     501              :                                   );
     502              :                     /* update variables for next loop */
     503            0 :                     current_pos_x = draw_to_pos_x;
     504            0 :                     current_pos_y = draw_to_pos_y;
     505            0 :                     planned_pos_x = current_pos_x;
     506            0 :                     planned_pos_y = envelope_bottom + gap;
     507              :                 }
     508              :             }
     509              :         }
     510            0 :         universal_array_index_iterator_destroy( &sorted_index_iter );
     511              : 
     512              :         /* draw end of last pass-by (if any) */
     513            0 :         if ( (( planned_pos_x < ( x - 0.001 ) )||( planned_pos_x > ( x + 0.001 ) ))
     514            0 :             && ( planned_pos_y + ( 1 * curve_space ) < bottom ) )
     515              :         {
     516            0 :             cairo_line_to( cr, current_pos_x, planned_pos_y );
     517            0 :             cairo_curve_to( cr,
     518              :                             current_pos_x,
     519              :                             planned_pos_y + curve_space,
     520              :                             x,
     521              :                             planned_pos_y,
     522              :                             x,
     523              :                             planned_pos_y + curve_space
     524              :                           );
     525            0 :             current_pos_x = x;
     526            0 :             current_pos_y = planned_pos_y + curve_space;
     527              :         }
     528              :         /* draw to end point and stroke the drawn path */
     529            0 :         cairo_line_to( cr, current_pos_x, bottom );
     530            0 :         if ( ! geometry_non_linear_scale_is_order_on_grid( x_scale, order_at_x ) )
     531              :         {
     532              :             double dashes[2];
     533            0 :             dashes[0] = 2.0 * gap;  /* on segment */
     534            0 :             dashes[1] = 4.0 * gap;  /* off segment */
     535            0 :             cairo_set_dash ( cr, dashes, 2, 0.0 );
     536              :         }
     537            0 :         cairo_stroke( cr );
     538            0 :         cairo_set_dash( cr, NULL, 0, 0.0 );
     539              :     }
     540              : 
     541              :     /* to draw y, follow x from left to right */
     542            0 :     if (( grid_kind == GEOMETRY_GRID_KIND_Y )||( grid_kind == GEOMETRY_GRID_KIND_XY ))
     543              :     {
     544              :         /* order visible set by left x coordinates of classifiers */
     545              :         universal_array_index_sorter_t sorted;
     546            0 :         universal_array_index_sorter_init( &sorted );
     547            0 :         for ( uint32_t idx = 0; idx < classifiers; idx ++ )
     548              :         {
     549              :             const layout_visible_classifier_t *const classifier
     550            0 :                 = layout_visible_set_get_visible_classifier_const( layout_data, idx );
     551              : 
     552            0 :             const geometry_rectangle_t *const envelope = layout_visible_classifier_get_envelope_box_const( classifier );
     553            0 :             const int64_t weight = geometry_rectangle_get_left( envelope );
     554            0 :             const u8_error_t insert_error = universal_array_index_sorter_insert( &sorted, idx, weight );
     555            0 :             if ( U8_ERROR_NONE != insert_error )
     556              :             {
     557            0 :                 U8_LOG_WARNING( "not all rectangles are considered for the left-to-right line" );
     558              :             }
     559              :         }
     560              : 
     561              :         /* process rectangles left to right */
     562              :         /* local variables represent 3 points: */
     563              :         /* current_pos_x / current_pos_y : The position where the already drawn line ends */
     564              :         /* planned_pos_x / planned_pos_y : The position that would be the next unless the next loop finds an earlier position */
     565              :         /* draw_to_pos_x / draw_to_pos_y : While drawing, this is a temporary value storing the next current_pos position */
     566            0 :         double current_pos_x = left;
     567            0 :         double current_pos_y = y;
     568            0 :         double planned_pos_x = left;  /* the planned next x - may be superseded by the next classifier */
     569            0 :         double planned_pos_y = y;
     570            0 :         cairo_move_to( cr, left, y );
     571              : 
     572              :         universal_array_index_iterator_t sorted_index_iter;
     573            0 :         universal_array_index_iterator_init( &sorted_index_iter, &sorted );
     574            0 :         while ( universal_array_index_iterator_has_next( &sorted_index_iter ) )
     575              :         {
     576            0 :             const uint32_t idx = universal_array_index_iterator_next( &sorted_index_iter );
     577              :             const layout_visible_classifier_t *const classifier
     578            0 :                 = layout_visible_set_get_visible_classifier_const( layout_data, idx );
     579              : 
     580              :             /* skip classifiers which contain others, these are not positioned according to their order value */
     581            0 :             const uint32_t children = layout_visible_set_count_descendants( layout_data, classifier );
     582            0 :             if ( children == 0 )
     583              :             {
     584            0 :                 const data_visible_classifier_t *const vis_data = layout_visible_classifier_get_data_const( classifier );
     585            0 :                 const data_classifier_t *const c_data = data_visible_classifier_get_classifier_const( vis_data );
     586            0 :                 const int32_t c_y_order = data_classifier_get_y_order( c_data );
     587            0 :                 const geometry_rectangle_t *const envelope = layout_visible_classifier_get_envelope_box_const( classifier );
     588            0 :                 const double envelope_top = geometry_rectangle_get_top( envelope );
     589            0 :                 const double envelope_bottom = geometry_rectangle_get_bottom( envelope );
     590            0 :                 const double envelope_left = geometry_rectangle_get_left( envelope );
     591            0 :                 const double envelope_right = geometry_rectangle_get_right( envelope );
     592              :                 /* if line passes through the classifier, center on symbol, not on envelope */
     593            0 :                 const geometry_rectangle_t *const symbol = layout_visible_classifier_get_symbol_box_const( classifier );
     594            0 :                 const double symbol_center_y = geometry_rectangle_get_center_y( symbol );
     595              : 
     596            0 :                 const bool pass_through_center_y = ( c_y_order == order_at_y );
     597            0 :                 const bool pass_on_top = ( c_y_order > order_at_y ) && ( envelope_top < y );
     598            0 :                 const bool pass_on_bottom = ( c_y_order < order_at_y ) && ( envelope_bottom > y );
     599            0 :                 const bool ignored = !( pass_through_center_y || pass_on_top || pass_on_bottom );
     600            0 :                 const double draw_to_pos_x = envelope_left - gap;
     601            0 :                 double draw_to_pos_y = y;
     602            0 :                 if ( pass_through_center_y )
     603              :                 {
     604            0 :                     draw_to_pos_y = symbol_center_y;
     605              :                 }
     606            0 :                 if ( pass_on_top )
     607              :                 {
     608            0 :                     draw_to_pos_y = envelope_top - gap;
     609              :                 }
     610            0 :                 if ( pass_on_bottom )
     611              :                 {
     612            0 :                     draw_to_pos_y = envelope_bottom + gap;
     613              :                 }
     614            0 :                 if ( ! ignored )
     615              :                 {
     616              :                     /* if planned_pos_y not at y and enough space to draw */
     617              :                     /* 1) a return to y and 2) a comeback to new draw_to_pos_y */
     618            0 :                     if ( (( planned_pos_y < ( y - 0.001 ) )||( planned_pos_y > ( y + 0.001 ) ))
     619            0 :                          && ( planned_pos_x + ( 2 * curve_space ) < draw_to_pos_x ) )
     620              :                     {
     621            0 :                         cairo_line_to( cr, planned_pos_x, current_pos_y );
     622            0 :                         cairo_curve_to( cr,
     623              :                                         planned_pos_x + curve_space,
     624              :                                         current_pos_y,
     625              :                                         planned_pos_x,
     626              :                                         y,
     627              :                                         planned_pos_x + curve_space,
     628              :                                         y
     629              :                                       );
     630            0 :                         current_pos_x = planned_pos_x + curve_space;
     631            0 :                         current_pos_y = y;
     632              :                     }
     633              : 
     634              :                     /* if there is enough space to draw a line before drawing a curve to draw_to_pos_x */
     635            0 :                     if ( ( current_pos_x + curve_space ) < draw_to_pos_x )
     636              :                     {
     637            0 :                         cairo_line_to( cr, draw_to_pos_x - curve_space, current_pos_y );
     638            0 :                         current_pos_x = draw_to_pos_x - curve_space;
     639              :                     }
     640              : 
     641              :                     /* draw begin of current pass-by */
     642            0 :                     cairo_curve_to( cr,
     643              :                                     draw_to_pos_x,
     644              :                                     current_pos_y,
     645              :                                     current_pos_x,
     646              :                                     draw_to_pos_y,
     647              :                                     draw_to_pos_x,
     648              :                                     draw_to_pos_y
     649              :                                   );
     650              :                     /* update variables for next loop */
     651            0 :                     current_pos_x = draw_to_pos_x;
     652            0 :                     current_pos_y = draw_to_pos_y;
     653            0 :                     planned_pos_x = envelope_right + gap;
     654            0 :                     planned_pos_y = current_pos_y;
     655              :                 }
     656              :             }
     657              :         }
     658            0 :         universal_array_index_iterator_destroy( &sorted_index_iter );
     659              : 
     660              :         /* draw end of last pass-by (if any) */
     661            0 :         if ( (( planned_pos_y < ( y - 0.001 ) )||( planned_pos_y > ( y + 0.001 ) ))
     662            0 :             && ( planned_pos_x + ( 1 * curve_space ) < right ) )
     663              :         {
     664            0 :             cairo_line_to( cr, planned_pos_x, current_pos_y );
     665            0 :             cairo_curve_to( cr,
     666              :                             planned_pos_x + curve_space,
     667              :                             current_pos_y,
     668              :                             planned_pos_x,
     669              :                             y,
     670              :                             planned_pos_x + curve_space,
     671              :                             y
     672              :                           );
     673            0 :             current_pos_x = planned_pos_x + curve_space;
     674            0 :             current_pos_y = y;
     675              :         }
     676              :         /* draw to end point and stroke the drawn path */
     677            0 :         cairo_line_to( cr, right, current_pos_y );
     678            0 :         if ( ! geometry_non_linear_scale_is_order_on_grid( y_scale, order_at_y ) )
     679              :         {
     680              :             double dashes[2];
     681            0 :             dashes[0] = 2.0 * gap;  /* on segment */
     682            0 :             dashes[1] = 4.0 * gap;  /* off segment */
     683            0 :             cairo_set_dash ( cr, dashes, 2, 0.0 );
     684              :         }
     685            0 :         cairo_stroke( cr );
     686            0 :         cairo_set_dash( cr, NULL, 0, 0.0 );
     687              :     }
     688              : 
     689            0 :     U8_TRACE_END();
     690            0 : }
     691              : 
     692            0 : void gui_sketch_card_painter_private_draw_element_space( const gui_sketch_card_painter_t *this_,
     693              :                                                          const layout_subelement_id_t *subelement,
     694              :                                                          const layout_visible_set_t *layouted_set,
     695              :                                                          cairo_t *cr )
     696              : {
     697            0 :     assert( NULL != subelement );
     698            0 :     assert( NULL != layouted_set );
     699            0 :     assert( NULL != cr );
     700            0 :     const layout_diagram_t *const layout_diag = layout_visible_set_get_diagram_const( layouted_set );
     701            0 :     const double label_border = 2.0;  /* additional visible border that just draws a box nicely, without effect for selecting */
     702            0 :     const double connector_border = (double) gui_sketch_style_get_snap_to_relationship( &((*this_).sketch_style) );
     703              : 
     704              :     geometry_rectangle_t highlight;
     705            0 :     geometry_rectangle_init_empty( &highlight );
     706              :     data_id_t search_id;
     707            0 :     data_id_copy( &search_id, data_full_id_get_primary_id_const( layout_subelement_id_get_id_const( subelement ) ) );
     708            0 :     const layout_subelement_kind_t kind = layout_subelement_id_get_kind( subelement );
     709              : 
     710              :     /* check diagram */
     711            0 :     const data_diagram_t *const diag_data = layout_diagram_get_data_const( layout_diag );
     712            0 :     const data_id_t diag_id = data_diagram_get_data_id( diag_data );
     713            0 :     if ( data_id_equals( &search_id, &diag_id ) )
     714              :     {
     715            0 :         switch ( kind )
     716              :         {
     717            0 :             case LAYOUT_SUBELEMENT_KIND_LABEL:
     718              :             {
     719            0 :                 geometry_rectangle_replace( &highlight, layout_diagram_get_label_box_const( layout_diag ) );
     720            0 :                 geometry_rectangle_expand_4dir( &highlight, 4.0 /* delta_width */, 4.0 /* delta_height */ );
     721            0 :                 gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     722              :             }
     723            0 :             break;
     724              : 
     725            0 :             case LAYOUT_SUBELEMENT_KIND_OUTLINE:
     726              :             {
     727              :                 geometry_rectangle_t empty_space;
     728            0 :                 geometry_rectangle_replace( &highlight, layout_diagram_get_bounds_const( layout_diag ) );
     729            0 :                 geometry_rectangle_copy( &empty_space, layout_diagram_get_draw_area_const( layout_diag ) );  /* no highlight in space */
     730            0 :                 gui_sketch_card_painter_private_draw_border( this_, &highlight, &empty_space, cr );
     731              :             }
     732            0 :             break;
     733              : 
     734            0 :             default:
     735              :             case LAYOUT_SUBELEMENT_KIND_SPACE:
     736              :             {
     737            0 :                 geometry_rectangle_replace( &highlight, layout_diagram_get_draw_area_const( layout_diag ) );
     738            0 :                 gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     739              :             }
     740            0 :             break;
     741              :         }
     742              :     }
     743              : 
     744              :     /* iterate over all classifiers */
     745            0 :     const uint32_t c_count = layout_visible_set_get_visible_classifier_count( layouted_set );
     746            0 :     for ( uint32_t c_index = 0; c_index < c_count; c_index ++ )
     747              :     {
     748              :         const layout_visible_classifier_t *const visible_classifier
     749            0 :             = layout_visible_set_get_visible_classifier_const ( layouted_set, c_index );
     750            0 :         const data_diagramelement_t *diagele = layout_visible_classifier_get_diagramelement_const( visible_classifier );
     751            0 :         const data_id_t diagele_id = data_diagramelement_get_data_id( diagele );
     752            0 :         if ( data_id_equals( &search_id, &diagele_id ) )
     753              :         {
     754            0 :             switch ( kind )
     755              :             {
     756            0 :                 case LAYOUT_SUBELEMENT_KIND_LABEL:
     757              :                 {
     758            0 :                     geometry_rectangle_replace( &highlight, layout_visible_classifier_get_label_box_const( visible_classifier ) );
     759            0 :                     geometry_rectangle_expand_4dir( &highlight, 4.0 /* delta_width */, 4.0 /* delta_height */ );
     760            0 :                     gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     761              :                 }
     762            0 :                 break;
     763              : 
     764            0 :                 case LAYOUT_SUBELEMENT_KIND_OUTLINE:
     765              :                 {
     766              :                     geometry_rectangle_t empty_space;
     767            0 :                     geometry_rectangle_replace( &highlight, layout_visible_classifier_get_symbol_box_const( visible_classifier ) );
     768            0 :                     geometry_rectangle_copy( &empty_space, layout_visible_classifier_get_space_const( visible_classifier ) );  /* no highlight in space */
     769            0 :                     gui_sketch_card_painter_private_draw_border( this_, &highlight, &empty_space, cr );
     770              :                 }
     771            0 :                 break;
     772              : 
     773            0 :                 default:
     774              :                 case LAYOUT_SUBELEMENT_KIND_SPACE:
     775              :                 {
     776            0 :                     geometry_rectangle_replace( &highlight, layout_visible_classifier_get_space_const( visible_classifier ) );
     777            0 :                     gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     778              :                 }
     779            0 :                 break;
     780              :             }
     781              :         }
     782              :     }
     783              : 
     784              :     /* check all contained features */
     785            0 :     const uint32_t f_count = layout_visible_set_get_feature_count( layouted_set );
     786            0 :     for ( uint32_t f_index = 0; f_index < f_count; f_index ++ )
     787              :     {
     788              :         const layout_feature_t *const the_feature
     789            0 :             = layout_visible_set_get_feature_const ( layouted_set, f_index );
     790            0 :         const data_feature_t *feature = layout_feature_get_data_const( the_feature );
     791            0 :         const data_id_t feature_id = data_feature_get_data_id( feature );
     792            0 :         if ( data_id_equals( &search_id, &feature_id ) )
     793              :         {
     794            0 :             switch ( kind )
     795              :             {
     796            0 :                 case LAYOUT_SUBELEMENT_KIND_LABEL:
     797              :                 {
     798            0 :                     geometry_rectangle_replace( &highlight, layout_feature_get_label_box_const( the_feature ) );
     799            0 :                     geometry_rectangle_expand_4dir( &highlight, 2.0 * label_border, 2.0 * label_border );
     800            0 :                     gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     801              :                 }
     802            0 :                 break;
     803              : 
     804            0 :                 default:
     805              :                 case LAYOUT_SUBELEMENT_KIND_OUTLINE:
     806              :                 {
     807            0 :                     geometry_rectangle_replace( &highlight, layout_feature_get_symbol_box_const( the_feature ) );
     808            0 :                     geometry_rectangle_expand_4dir( &highlight, 2.0 * label_border, 2.0 * label_border );
     809            0 :                     gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     810              :                 }
     811            0 :                 break;
     812              :             }
     813              :         }
     814              :     }
     815              : 
     816            0 :     const uint32_t count_relations = layout_visible_set_get_relationship_count ( layouted_set );
     817            0 :     for ( uint32_t rel_index = 0; rel_index < count_relations; rel_index ++ )
     818              :     {
     819              :         const layout_relationship_t *const the_relationship
     820            0 :             = layout_visible_set_get_relationship_const( layouted_set, rel_index );
     821            0 :         const data_relationship_t *const relationship = layout_relationship_get_data_const( the_relationship );
     822            0 :         const data_id_t relationship_id = data_relationship_get_data_id( relationship );
     823            0 :         if ( data_id_equals( &search_id, &relationship_id ) )
     824              :         {
     825            0 :             switch ( kind )
     826              :             {
     827            0 :                 case LAYOUT_SUBELEMENT_KIND_LABEL:
     828              :                 {
     829            0 :                     geometry_rectangle_replace( &highlight, layout_relationship_get_label_box_const( the_relationship ) );
     830            0 :                     geometry_rectangle_expand_4dir( &highlight, 2.0 * label_border, 2.0 * label_border );
     831            0 :                     gui_sketch_card_painter_private_draw_rect( this_, &highlight, cr );
     832              :                 }
     833            0 :                 break;
     834              : 
     835            0 :                 default:
     836              :                 case LAYOUT_SUBELEMENT_KIND_OUTLINE:
     837              :                 {
     838              :                     const geometry_connector_t *const relationship_shape
     839            0 :                         = layout_relationship_get_shape_const( the_relationship );
     840              :                     {
     841              :                         geometry_rectangle_t segment_src;
     842            0 :                         segment_src = geometry_connector_get_segment_bounds( relationship_shape,
     843              :                                                                              GEOMETRY_CONNECTOR_SEGMENT_SOURCE
     844              :                                                                            );
     845            0 :                         geometry_rectangle_expand_4dir( &segment_src, 2.0 * connector_border, 2.0 * connector_border );
     846            0 :                         gui_sketch_card_painter_private_draw_rect( this_, &segment_src, cr );
     847              :                     }
     848              :                     {
     849              :                         geometry_rectangle_t segment_dst;
     850            0 :                         segment_dst = geometry_connector_get_segment_bounds( relationship_shape,
     851              :                                                                              GEOMETRY_CONNECTOR_SEGMENT_DESTINATION
     852              :                                                                            );
     853            0 :                         geometry_rectangle_expand_4dir( &segment_dst, 2.0 * connector_border, 2.0 * connector_border );
     854            0 :                         gui_sketch_card_painter_private_draw_rect( this_, &segment_dst, cr );
     855              :                     }
     856              :                     {
     857              :                         geometry_rectangle_t segment_main;
     858            0 :                         segment_main = geometry_connector_get_segment_bounds( relationship_shape,
     859              :                                                                               GEOMETRY_CONNECTOR_SEGMENT_MAIN
     860              :                                                                             );
     861            0 :                         geometry_rectangle_expand_4dir( &segment_main, 2.0 * connector_border, 2.0 * connector_border );
     862            0 :                         gui_sketch_card_painter_private_draw_rect( this_, &segment_main, cr );
     863              :                     }
     864              :                 }
     865            0 :                 break;
     866              :             }
     867              :         }
     868              :     }
     869            0 : }
     870              : 
     871            0 : void gui_sketch_card_painter_draw_paper( gui_sketch_card_painter_t *this_,
     872              :                                          gui_tool_t selected_tool,
     873              :                                          const gui_sketch_drag_state_t *drag_state,
     874              :                                          const gui_sketch_card_t *card,
     875              :                                          cairo_t *cr )
     876              : {
     877            0 :     U8_TRACE_BEGIN();
     878            0 :     assert( NULL != drag_state );
     879            0 :     assert( NULL != card );
     880            0 :     assert( NULL != cr );
     881              : 
     882            0 :     if ( gui_sketch_card_is_visible(card) )
     883              :     {
     884            0 :         const bool create_tool = ( selected_tool == GUI_TOOL_CREATE );
     885              : 
     886            0 :         shape_int_rectangle_t bounds = gui_sketch_card_get_bounds( card );
     887            0 :         const int32_t left = shape_int_rectangle_get_left( &bounds );
     888            0 :         const int32_t top = shape_int_rectangle_get_top( &bounds );
     889            0 :         const uint32_t width = shape_int_rectangle_get_width( &bounds );
     890            0 :         const uint32_t height = shape_int_rectangle_get_height( &bounds );
     891              : 
     892              :         /* draw paper */
     893            0 :         if ( create_tool )
     894              :         {
     895              :             static const double GRAY_R = 0.875;
     896              :             static const double GRAY_G = 0.875;
     897              :             static const double GRAY_B = 0.875;
     898              :             static const double GRAY_A = 1.0;
     899            0 :             cairo_set_source_rgba( cr, GRAY_R, GRAY_G, GRAY_B, GRAY_A );
     900              :         }
     901              :         else
     902              :         {
     903              :             static const double WHITE_R = 1.0;
     904              :             static const double WHITE_G = 1.0;
     905              :             static const double WHITE_B = 1.0;
     906              :             static const double WHITE_A = 1.0;
     907            0 :             cairo_set_source_rgba( cr, WHITE_R, WHITE_G, WHITE_B, WHITE_A );
     908              :         }
     909            0 :         cairo_rectangle ( cr, left, top, width, height );
     910            0 :         cairo_fill (cr);
     911              : 
     912            0 :         const layout_visible_set_t *const layout = gui_sketch_card_get_visible_set( card );
     913            0 :         if ( layout_visible_set_is_valid( layout ) && create_tool )
     914              :         {
     915            0 :             const int32_t mouse_x = gui_sketch_drag_state_get_to_x( drag_state );
     916            0 :             const int32_t mouse_y = gui_sketch_drag_state_get_to_y( drag_state );
     917              : 
     918              :             const layout_subelement_id_t subelement_to_highlight
     919            0 :                 = gui_sketch_card_get_element_at_pos( card, mouse_x, mouse_y, !create_tool /* filter_lifelines */ );
     920              : 
     921            0 :             gui_sketch_card_painter_private_draw_element_space( this_, &subelement_to_highlight, layout, cr );
     922              :         }
     923              :     }
     924              : 
     925            0 :     U8_TRACE_END();
     926            0 : }
     927              : 
     928              : 
     929              : /*
     930              : Copyright 2017-2026 Andreas Warnke
     931              : 
     932              : Licensed under the Apache License, Version 2.0 (the "License");
     933              : you may not use this file except in compliance with the License.
     934              : You may obtain a copy of the License at
     935              : 
     936              :     http://www.apache.org/licenses/LICENSE-2.0
     937              : 
     938              : Unless required by applicable law or agreed to in writing, software
     939              : distributed under the License is distributed on an "AS IS" BASIS,
     940              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     941              : See the License for the specific language governing permissions and
     942              : limitations under the License.
     943              : */
        

Generated by: LCOV version 2.0-1