LCOV - code coverage report
Current view: top level - gui/source/sketch - gui_sketch_result_list.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 0.0 % 145 0
Test Date: 2025-05-01 10:10:14 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /* File: gui_sketch_result_list.c; Copyright and License: see below */
       2              : 
       3              : #include "sketch/gui_sketch_result_list.h"
       4              : #include "geometry/geometry_rectangle.h"
       5              : #include "utf8stringbuf/utf8stringbuf.h"
       6              : #include "u8/u8_trace.h"
       7              : #include "u8/u8_log.h"
       8              : #include "u8/u8_i32.h"
       9              : #include "gui_gdk.h"
      10              : 
      11              : static const int GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH = -1;  /*!< pango automatically determines the string length */
      12              : static const int GUI_SKETCH_RESULT_LIST_PANGO_UNLIMITED_WIDTH = -1;
      13              : static const int OBJ_GAP = 4;
      14              : 
      15            0 : void gui_sketch_result_list_init( gui_sketch_result_list_t *this_,
      16              :                                   gui_resources_t *resources,
      17              :                                   gui_sketch_texture_t *texture_downloader )
      18              : {
      19            0 :     U8_TRACE_BEGIN();
      20            0 :     assert( resources != NULL );
      21            0 :     assert( texture_downloader != NULL );
      22              : 
      23            0 :     DATA_SEARCH_RESULT_LIST_INIT( &((*this_).result_list), (*this_).result_list_buf );
      24              : 
      25            0 :     (*this_).visible = false;
      26            0 :     shape_int_rectangle_init( &((*this_).bounds), 0, 0, 0, 0 );
      27              : 
      28            0 :     (*this_).element_count = 0;
      29              : 
      30            0 :     gui_sketch_style_init( &((*this_).sketch_style) );
      31            0 :     gui_sketch_marker_init( &((*this_).sketch_marker), true );
      32            0 :     (*this_).resources = resources;
      33            0 :     gui_type_resource_list_init( &((*this_).selector), resources );
      34            0 :     (*this_).texture_downloader = texture_downloader;
      35              : 
      36            0 :     U8_TRACE_END();
      37            0 : }
      38              : 
      39            0 : void gui_sketch_result_list_destroy( gui_sketch_result_list_t *this_ )
      40              : {
      41            0 :     U8_TRACE_BEGIN();
      42              : 
      43            0 :     (*this_).texture_downloader = NULL;
      44            0 :     gui_type_resource_list_destroy( &((*this_).selector) );
      45            0 :     (*this_).resources = NULL;
      46            0 :     gui_sketch_marker_destroy( &((*this_).sketch_marker) );
      47            0 :     gui_sketch_style_destroy( &((*this_).sketch_style) );
      48              : 
      49            0 :     gui_sketch_result_list_invalidate_data( this_ );
      50              : 
      51            0 :     shape_int_rectangle_destroy( &((*this_).bounds) );
      52              : 
      53            0 :     U8_TRACE_END();
      54            0 : }
      55              : 
      56            0 : void gui_sketch_result_list_do_layout( gui_sketch_result_list_t *this_, cairo_t *cr )
      57              : {
      58            0 :     U8_TRACE_BEGIN();
      59              : 
      60              :     /* create the font_layout */
      61              :     PangoLayout *font_layout;
      62              :     {
      63            0 :         font_layout = pango_cairo_create_layout (cr);
      64              :         const PangoFontDescription *const std_font
      65            0 :             = gui_sketch_style_get_standard_font_description( &((*this_).sketch_style ) );
      66            0 :         pango_layout_set_font_description( font_layout, std_font );
      67              :     }
      68              : 
      69            0 :     int32_t y_pos = shape_int_rectangle_get_top( &((*this_).bounds) );
      70              : 
      71            0 :     const unsigned int count = data_search_result_list_get_length( &((*this_).result_list) );
      72            0 :     assert( count <= GUI_SKETCH_RESULT_LIST_MAX_ELEMENTS );
      73            0 :     (*this_).element_count = count;
      74            0 :     for ( unsigned int idx = 0; idx < count; idx ++ )
      75              :     {
      76            0 :         const data_search_result_t *result = data_search_result_list_get_const( &((*this_).result_list), idx );
      77            0 :         pos_search_result_init( &((*this_).element_pos[idx]), result );
      78            0 :         gui_sketch_result_list_private_layout_element( this_, &((*this_).element_pos[idx]), &y_pos, font_layout );
      79              :     }
      80              : 
      81              :     /* release the font_layout */
      82            0 :     g_object_unref(font_layout);
      83              : 
      84            0 :     U8_TRACE_END();
      85            0 : }
      86              : 
      87            0 : void gui_sketch_result_list_private_layout_element ( gui_sketch_result_list_t *this_,
      88              :                                                      pos_search_result_t *element,
      89              :                                                      int32_t *io_y_pos,
      90              :                                                      PangoLayout *font_layout )
      91              : {
      92            0 :     U8_TRACE_BEGIN();
      93            0 :     assert( NULL != element );
      94            0 :     assert( NULL != io_y_pos );
      95            0 :     assert( NULL != font_layout );
      96              : 
      97            0 :     int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
      98            0 :     uint_fast32_t width = shape_int_rectangle_get_width( &((*this_).bounds) );
      99            0 :     const data_search_result_t *result = pos_search_result_get_data_const( element );
     100              : 
     101              :     /* determine icon dimensions */
     102              :     {
     103            0 :         const data_type_t result_type = data_search_result_get_match_type( result );
     104              :         gui_type_resource_t *const type_data
     105            0 :             = gui_type_resource_list_get_type ( &((*this_).selector), result_type );
     106            0 :         GdkTexture *const icon = gui_type_resource_get_icon( type_data );
     107            0 :         const double icon_width = gdk_texture_get_width( icon );
     108            0 :         const double icon_height = gdk_texture_get_height( icon );
     109              : 
     110            0 :         const shape_int_rectangle_t new_icon_box = (shape_int_rectangle_t) {
     111            0 :             .left=left+OBJ_GAP,
     112            0 :             .top=(*io_y_pos)+OBJ_GAP,
     113            0 :             .width=icon_width+0.999,
     114            0 :             .height=icon_height+0.999 };
     115            0 :         pos_search_result_set_icon_box( element, &new_icon_box );
     116              :     }
     117              : 
     118              :     /* determine label dimensions */
     119            0 :     const shape_int_rectangle_t *const icon_box = pos_search_result_get_icon_box_const( element );
     120              :     {
     121            0 :         int_fast32_t proposed_pango_width = width - shape_int_rectangle_get_width(icon_box) - (4*OBJ_GAP);
     122            0 :         pango_layout_set_text( font_layout,
     123              :                                 data_search_result_get_match_name_const( result ),
     124              :                                 GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH
     125              :                                 );
     126            0 :         pango_layout_set_width(font_layout, proposed_pango_width * PANGO_SCALE );
     127              :         int text_width;
     128              :         int text_height;
     129            0 :         pango_layout_get_pixel_size(font_layout, &text_width, &text_height);
     130              : 
     131            0 :         int_fast32_t x_pos = shape_int_rectangle_get_right(icon_box);
     132              : 
     133            0 :         const shape_int_rectangle_t new_label_box = (shape_int_rectangle_t) {
     134            0 :             .left=x_pos+OBJ_GAP,
     135            0 :             .top=(*io_y_pos)+OBJ_GAP,
     136              :             .width=text_width,
     137              :             .height=text_height };
     138            0 :         pos_search_result_set_label_box( element, &new_label_box );
     139              :     }
     140              : 
     141            0 :     const shape_int_rectangle_t *const label_box = pos_search_result_get_label_box_const( element );
     142              :     *io_y_pos
     143            0 :         = u8_i32_max2( shape_int_rectangle_get_bottom(icon_box), shape_int_rectangle_get_bottom(label_box) )
     144            0 :         + OBJ_GAP;
     145              : 
     146            0 :     U8_TRACE_END();
     147            0 : }
     148              : 
     149              : static const double GREY_R = 0.8;
     150              : static const double GREY_G = 0.8;
     151              : static const double GREY_B = 0.8;
     152              : static const double GREY_A = 1.0;
     153              : 
     154            0 : void gui_sketch_result_list_draw ( gui_sketch_result_list_t *this_, const gui_marked_set_t *marker, cairo_t *cr )
     155              : {
     156            0 :     U8_TRACE_BEGIN();
     157            0 :     assert( NULL != marker );
     158            0 :     assert( NULL != cr );
     159              : 
     160            0 :     if ( (*this_).visible )
     161              :     {
     162            0 :         PangoLayout *font_layout = pango_cairo_create_layout (cr);
     163              :         {
     164              :             const PangoFontDescription *const std_font
     165            0 :                 = gui_sketch_style_get_standard_font_description( &((*this_).sketch_style ) );
     166            0 :             pango_layout_set_font_description ( font_layout, std_font );
     167              :         }
     168              : 
     169              :         /* draw background */
     170              :         {
     171            0 :             const int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
     172            0 :             const int_fast32_t top = shape_int_rectangle_get_top( &((*this_).bounds) );
     173            0 :             const uint_fast32_t width = shape_int_rectangle_get_width( &((*this_).bounds) );
     174            0 :             const uint_fast32_t height = shape_int_rectangle_get_height( &((*this_).bounds) );
     175              : 
     176            0 :             cairo_set_source_rgba( cr, GREY_R, GREY_G, GREY_B, GREY_A );
     177            0 :             cairo_rectangle ( cr, left, top, width, height );
     178            0 :             cairo_fill (cr);
     179              :         }
     180              : 
     181              :         /* draw icons and text */
     182            0 :         const unsigned int count = (*this_).element_count;
     183            0 :         assert( count <= GUI_SKETCH_RESULT_LIST_MAX_ELEMENTS );
     184            0 :         if ( count == 0 )
     185              :         {
     186            0 :             const int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
     187            0 :             const int_fast32_t top = shape_int_rectangle_get_top( &((*this_).bounds) );
     188            0 :             GdkTexture *undef_icon = gui_resources_get_type_undef( (*this_).resources );
     189            0 :             double icon_width = gdk_texture_get_width ( undef_icon );
     190              : 
     191              :             /* draw text first, use the above set color and font */
     192            0 :             const GdkRGBA std_color = gui_sketch_style_get_standard_color( &((*this_).sketch_style) );
     193            0 :             cairo_set_source_rgba( cr, std_color.red, std_color.green, std_color.blue, std_color.alpha );
     194            0 :             cairo_move_to( cr, left+OBJ_GAP+icon_width, top+OBJ_GAP );
     195            0 :             pango_layout_set_text( font_layout, "no results", GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH );
     196            0 :             pango_layout_set_width(font_layout, GUI_SKETCH_RESULT_LIST_PANGO_UNLIMITED_WIDTH );
     197            0 :             pango_cairo_show_layout( cr, font_layout );
     198              : 
     199              :             /* draw the icon */
     200            0 :             const int x = left+OBJ_GAP;
     201            0 :             const int y = top+OBJ_GAP;
     202            0 :             gui_sketch_texture_draw( (*this_).texture_downloader, undef_icon, x, y, cr );
     203              :         }
     204              :         else
     205              :         {
     206            0 :             for ( unsigned int idx = 0; idx < count; idx ++ )
     207              :             {
     208            0 :                 const pos_search_result_t *const element = &((*this_).element_pos[idx]);
     209            0 :                 gui_sketch_result_list_private_draw_element( this_, element, marker, font_layout, cr );
     210              :             }
     211              :         }
     212              : 
     213            0 :         g_object_unref(font_layout);
     214              :     }
     215              : 
     216            0 :     U8_TRACE_END();
     217            0 : }
     218              : 
     219            0 : void gui_sketch_result_list_private_draw_element( gui_sketch_result_list_t *this_,
     220              :                                                   const pos_search_result_t *element,
     221              :                                                   const gui_marked_set_t *marker,
     222              :                                                   PangoLayout *font_layout,
     223              :                                                   cairo_t *cr )
     224              : {
     225            0 :     U8_TRACE_BEGIN();
     226            0 :     assert( NULL != cr );
     227            0 :     assert( NULL != element );
     228            0 :     assert( NULL != marker );
     229            0 :     assert( NULL != font_layout );
     230              : 
     231            0 :     const data_search_result_t *const result = pos_search_result_get_data_const( element );
     232              : 
     233              :     /* draw marker and set color */
     234              :     {
     235              :         shape_int_rectangle_t destination_rect;
     236            0 :         shape_int_rectangle_init_by_bounds( &destination_rect,
     237              :                                             pos_search_result_get_icon_box_const(element),
     238              :                                             pos_search_result_get_label_box_const(element)
     239              :                                           );
     240              : 
     241            0 :         const data_id_t highlighted = gui_marked_set_get_highlighted( marker );
     242            0 :         gui_sketch_marker_prepare_draw( &((*this_).sketch_marker),
     243              :                                         data_search_result_get_match_id( result ),
     244              :                                         marker,
     245              :                                         destination_rect,
     246              :                                         cr
     247              :                                       );
     248            0 :         if ( data_id_equals( &highlighted, data_search_result_get_diagram_id_const( result ) ) )
     249              :         {
     250            0 :             const GdkRGBA high_color = gui_sketch_style_get_highlight_color( &((*this_).sketch_style) );
     251            0 :             cairo_set_source_rgba( cr, high_color.red, high_color.green, high_color.blue, high_color.alpha );
     252              :         }
     253              : 
     254            0 :         shape_int_rectangle_destroy( &destination_rect );
     255              :     }
     256              : 
     257              :     /* draw text first, use the above set color and font */
     258              :     {
     259              :         /* what to draw */
     260            0 :         const char *const label = data_search_result_get_match_name_const( result );
     261              : 
     262              :         /* where to draw to */
     263              :         const shape_int_rectangle_t *const label_box
     264            0 :             = pos_search_result_get_label_box_const( element );
     265              : 
     266              :         /* do draw */
     267            0 :         cairo_move_to( cr, shape_int_rectangle_get_left(label_box), shape_int_rectangle_get_top(label_box) );
     268            0 :         pango_layout_set_text( font_layout, label, GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH );
     269            0 :         const unsigned int text_width
     270            0 :             = shape_int_rectangle_get_width(label_box)
     271            0 :             +(2.0*OBJ_GAP);  /* add gap to avoid line breaks by rounding errors and whitespace character widths */
     272            0 :         pango_layout_set_width(font_layout, text_width * PANGO_SCALE );
     273            0 :         pango_cairo_show_layout( cr, font_layout );
     274              :     }
     275              : 
     276              :     /* draw the icon */
     277              :     {
     278              :         /* what to draw */
     279            0 :         const data_type_t result_type = data_search_result_get_match_type( result );
     280              :         gui_type_resource_t *const type_data
     281            0 :             = gui_type_resource_list_get_type ( &((*this_).selector), result_type );
     282            0 :         GdkTexture *const icon = gui_type_resource_get_icon( type_data );
     283              : 
     284              :         /* where to draw to */
     285              :         const shape_int_rectangle_t *const icon_box
     286            0 :             = pos_search_result_get_icon_box_const( element );
     287            0 :         const int x = shape_int_rectangle_get_left(icon_box);
     288            0 :         const int y = shape_int_rectangle_get_top(icon_box);
     289              :         /* double icon_width = gdk_texture_get_width ( icon ); */
     290              :         /* double icon_height = gdk_texture_get_width ( icon ); */
     291              : 
     292              :         /* do draw */
     293            0 :         gui_sketch_texture_draw( (*this_).texture_downloader, icon, x, y, cr );
     294              :     }
     295              : 
     296            0 :     U8_TRACE_END();
     297            0 : }
     298              : 
     299              : 
     300              : /*
     301              : Copyright 2018-2025 Andreas Warnke
     302              : 
     303              : Licensed under the Apache License, Version 2.0 (the "License");
     304              : you may not use this file except in compliance with the License.
     305              : You may obtain a copy of the License at
     306              : 
     307              :     http://www.apache.org/licenses/LICENSE-2.0
     308              : 
     309              : Unless required by applicable law or agreed to in writing, software
     310              : distributed under the License is distributed on an "AS IS" BASIS,
     311              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     312              : See the License for the specific language governing permissions and
     313              : limitations under the License.
     314              : */
        

Generated by: LCOV version 2.0-1