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

Generated by: LCOV version 2.0-1