LCOV - code coverage report
Current view: top level - gui/source/sketch - gui_sketch_result_list.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 0 145 0.0 %
Date: 2024-10-26 21:44:38 Functions: 0 6 0.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 <gdk/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-2024 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 1.16