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

Generated by: LCOV version 1.16