LCOV - code coverage report
Current view: top level - gui/source/sketch - gui_sketch_card_painter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 0 455 0.0 %
Date: 2025-09-25 21:07:53 Functions: 0 10 0.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             :                                    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 1.16