Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/controls/table/gridtablerenderer.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
21
#include "cellvalueconversion.hxx"
22
#include <controls/table/gridtablerenderer.hxx>
23
#include <controls/table/tablesort.hxx>
24
25
#include <com/sun/star/graphic/XGraphic.hpp>
26
27
#include <tools/debug.hxx>
28
#include <comphelper/diagnose_ex.hxx>
29
#include <vcl/window.hxx>
30
#include <vcl/image.hxx>
31
#include <vcl/virdev.hxx>
32
#include <vcl/decoview.hxx>
33
#include <vcl/settings.hxx>
34
35
36
namespace svt::table
37
{
38
    using ::css::uno::Any;
39
    using ::css::uno::Reference;
40
    using ::css::uno::UNO_QUERY;
41
    using ::css::uno::XInterface;
42
    using ::css::uno::TypeClass_INTERFACE;
43
    using ::css::graphic::XGraphic;
44
    using ::css::style::HorizontalAlignment;
45
    using ::css::style::HorizontalAlignment_CENTER;
46
    using ::css::style::HorizontalAlignment_RIGHT;
47
    using ::css::style::VerticalAlignment;
48
    using ::css::style::VerticalAlignment_MIDDLE;
49
    using ::css::style::VerticalAlignment_BOTTOM;
50
51
52
    //= CachedSortIndicator
53
54
    namespace {
55
56
    class CachedSortIndicator
57
    {
58
    public:
59
        CachedSortIndicator()
60
0
            : m_lastHeaderHeight( 0 )
61
0
            , m_lastArrowColor( COL_TRANSPARENT )
62
0
        {
63
0
        }
64
65
        Bitmap const & getBitmapFor(vcl::RenderContext const & i_device, tools::Long const i_headerHeight,
66
                                      StyleSettings const & i_style, bool const i_sortAscending);
67
68
    private:
69
        tools::Long m_lastHeaderHeight;
70
        Color m_lastArrowColor;
71
        Bitmap m_sortAscending;
72
        Bitmap m_sortDescending;
73
    };
74
75
    }
76
77
    Bitmap const & CachedSortIndicator::getBitmapFor(vcl::RenderContext const& i_device, tools::Long const i_headerHeight,
78
        StyleSettings const & i_style, bool const i_sortAscending )
79
0
    {
80
0
        Bitmap& rBitmap(i_sortAscending ? m_sortAscending : m_sortDescending);
81
0
        if (rBitmap.IsEmpty() || (i_headerHeight != m_lastHeaderHeight) || (i_style.GetActiveColor() != m_lastArrowColor))
82
0
        {
83
0
            tools::Long const nSortIndicatorWidth = 2 * i_headerHeight / 3;
84
0
            tools::Long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3;
85
86
0
            Point const aBitmapPos( 0, 0 );
87
0
            Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight );
88
0
            ScopedVclPtrInstance< VirtualDevice > aDevice(i_device, DeviceFormat::WITH_ALPHA);
89
0
            aDevice->SetOutputSizePixel( aBitmapSize );
90
91
0
            DecorationView aDecoView(aDevice.get());
92
0
            aDecoView.DrawSymbol(tools::Rectangle(aBitmapPos, aBitmapSize),
93
0
                                 i_sortAscending ? SymbolType::SPIN_UP : SymbolType::SPIN_DOWN,
94
0
                                 i_style.GetActiveColor());
95
96
0
            rBitmap = aDevice->GetBitmap(aBitmapPos, aBitmapSize);
97
0
            m_lastHeaderHeight = i_headerHeight;
98
0
            m_lastArrowColor = i_style.GetActiveColor();
99
0
        }
100
0
        return rBitmap;
101
0
    }
102
103
104
    //= GridTableRenderer_Impl
105
106
    struct GridTableRenderer_Impl
107
    {
108
        ITableModel&        rModel;
109
        RowPos              nCurrentRow;
110
        bool                bUseGridLines;
111
        CachedSortIndicator aSortIndicator;
112
        CellValueConversion aStringConverter;
113
114
        explicit GridTableRenderer_Impl( ITableModel& _rModel )
115
0
            : rModel( _rModel )
116
0
            , nCurrentRow( ROW_INVALID )
117
0
            , bUseGridLines( true )
118
0
            , aSortIndicator( )
119
0
            , aStringConverter()
120
0
        {
121
0
        }
122
    };
123
124
125
    //= helper
126
127
    namespace
128
    {
129
        tools::Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, tools::Rectangle const & i_cellArea )
130
0
        {
131
0
            tools::Rectangle aContentArea( i_cellArea );
132
0
            if ( i_impl.bUseGridLines )
133
0
            {
134
0
                aContentArea.AdjustRight( -1 );
135
0
                aContentArea.AdjustBottom( -1 );
136
0
            }
137
0
            return aContentArea;
138
0
        }
139
        tools::Rectangle lcl_getTextRenderingArea( tools::Rectangle const & i_contentArea )
140
0
        {
141
0
            tools::Rectangle aTextArea( i_contentArea );
142
0
            aTextArea.AdjustLeft(2 ); aTextArea.AdjustRight( -2 );
143
0
            aTextArea.AdjustTop( 1 ); aTextArea.AdjustBottom( -1 );
144
0
            return aTextArea;
145
0
        }
146
147
        DrawTextFlags lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos )
148
0
        {
149
0
            DrawTextFlags nVertFlag = DrawTextFlags::Top;
150
0
            VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign();
151
0
            switch ( eVertAlign )
152
0
            {
153
0
            case VerticalAlignment_MIDDLE:  nVertFlag = DrawTextFlags::VCenter;  break;
154
0
            case VerticalAlignment_BOTTOM:  nVertFlag = DrawTextFlags::Bottom;   break;
155
0
            default:
156
0
                break;
157
0
            }
158
159
0
            DrawTextFlags nHorzFlag = DrawTextFlags::Left;
160
0
            HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnCount() > 0
161
0
                                                ?  i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign()
162
0
                                                :  HorizontalAlignment_CENTER;
163
0
            switch ( eHorzAlign )
164
0
            {
165
0
            case HorizontalAlignment_CENTER:    nHorzFlag = DrawTextFlags::Center;   break;
166
0
            case HorizontalAlignment_RIGHT:     nHorzFlag = DrawTextFlags::Right;    break;
167
0
            default:
168
0
                break;
169
0
            }
170
171
0
            return nVertFlag | nHorzFlag;
172
0
        }
173
174
    }
175
176
177
    //= GridTableRenderer
178
179
180
    GridTableRenderer::GridTableRenderer( ITableModel& _rModel )
181
0
        :m_pImpl( new GridTableRenderer_Impl( _rModel ) )
182
0
    {
183
0
    }
184
185
186
    GridTableRenderer::~GridTableRenderer()
187
0
    {
188
0
    }
189
190
191
    bool GridTableRenderer::useGridLines() const
192
0
    {
193
0
        return m_pImpl->bUseGridLines;
194
0
    }
195
196
197
    void GridTableRenderer::useGridLines( bool const i_use )
198
0
    {
199
0
        m_pImpl->bUseGridLines = i_use;
200
0
    }
201
202
203
    namespace
204
    {
205
        Color lcl_getEffectiveColor(std::optional<Color> const& i_modelColor,
206
                                    StyleSettings const& i_styleSettings,
207
                                    Color const& (StyleSettings::*i_getDefaultColor) () const)
208
0
        {
209
0
            if (!!i_modelColor)
210
0
                return *i_modelColor;
211
0
            return (i_styleSettings.*i_getDefaultColor)();
212
0
        }
213
    }
214
215
216
    void GridTableRenderer::PaintHeaderArea(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rArea,
217
                                            bool _bIsColHeaderArea, bool _bIsRowHeaderArea, const StyleSettings& _rStyle)
218
0
    {
219
0
        OSL_PRECOND(_bIsColHeaderArea || _bIsRowHeaderArea, "GridTableRenderer::PaintHeaderArea: invalid area flags!");
220
221
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
222
223
0
        Color const background = lcl_getEffectiveColor(m_pImpl->rModel.getHeaderBackgroundColor(),
224
0
                                                       _rStyle, &StyleSettings::GetDialogColor);
225
0
        rRenderContext.SetFillColor(background);
226
227
0
        rRenderContext.SetLineColor();
228
0
        rRenderContext.DrawRect(_rArea);
229
230
        // delimiter lines at bottom/right
231
0
        std::optional<Color> aLineColor(m_pImpl->rModel.getLineColor());
232
0
        Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
233
0
        rRenderContext.SetLineColor(lineColor);
234
0
        rRenderContext.DrawLine(_rArea.BottomLeft(), _rArea.BottomRight());
235
0
        rRenderContext.DrawLine(_rArea.BottomRight(), _rArea.TopRight());
236
0
    }
237
238
239
    void GridTableRenderer::PaintColumnHeader(
240
        ColPos _nCol,
241
        vcl::RenderContext& rRenderContext,
242
        const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
243
0
    {
244
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::LINECOLOR);
245
246
0
        OUString sHeaderText;
247
0
        PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol );
248
0
        DBG_ASSERT( pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" );
249
0
        if ( pColumn )
250
0
            sHeaderText = pColumn->getName();
251
252
0
        Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
253
0
        rRenderContext.SetTextColor(textColor);
254
255
0
        tools::Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
256
0
        DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | DrawTextFlags::Clip;
257
0
        if (!m_pImpl->rModel.isEnabled())
258
0
            nDrawTextFlags |= DrawTextFlags::Disable;
259
0
        rRenderContext.DrawText( aTextRect, sHeaderText, nDrawTextFlags );
260
261
0
        std::optional<Color> const aLineColor( m_pImpl->rModel.getLineColor() );
262
0
        Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
263
0
        rRenderContext.SetLineColor( lineColor );
264
0
        rRenderContext.DrawLine( _rArea.BottomRight(), _rArea.TopRight());
265
0
        rRenderContext.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
266
267
        // draw sort indicator if the model data is sorted by the given column
268
0
        ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter();
269
0
        ColumnSort aCurrentSortOrder;
270
0
        if ( pSortAdapter != nullptr )
271
0
            aCurrentSortOrder = pSortAdapter->getCurrentSortOrder();
272
0
        if ( aCurrentSortOrder.nColumnPos == _nCol )
273
0
        {
274
0
            tools::Long const nHeaderHeight( _rArea.GetHeight() );
275
0
            Bitmap const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor(rRenderContext, nHeaderHeight, _rStyle,
276
0
                                                                                   aCurrentSortOrder.eSortDirection == ColumnSortAscending);
277
0
            Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() );
278
0
            tools::Long const nSortIndicatorPaddingX = 2;
279
0
            tools::Long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2;
280
281
0
            if ( nDrawTextFlags & DrawTextFlags::Right )
282
0
            {
283
                // text is right aligned => draw the sort indicator at the left hand side
284
0
                rRenderContext.DrawBitmap(Point(_rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY),
285
0
                                            aIndicatorBitmap);
286
0
            }
287
0
            else
288
0
            {
289
                // text is left-aligned or centered => draw the sort indicator at the right hand side
290
0
                rRenderContext.DrawBitmap(Point(_rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY),
291
0
                                            aIndicatorBitmap);
292
0
            }
293
0
        }
294
0
    }
295
296
297
    void GridTableRenderer::PrepareRow(RowPos _nRow, bool i_hasControlFocus, bool _bSelected, vcl::RenderContext& rRenderContext,
298
                                       const tools::Rectangle& _rRowArea, const StyleSettings& _rStyle)
299
0
    {
300
        // remember the row for subsequent calls to the other ->ITableRenderer methods
301
0
        m_pImpl->nCurrentRow = _nRow;
302
303
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
304
305
0
        Color backgroundColor = _rStyle.GetFieldColor();
306
307
0
        Color const activeSelectionBackColor = lcl_getEffectiveColor(m_pImpl->rModel.getActiveSelectionBackColor(),
308
0
                                                                     _rStyle, &StyleSettings::GetHighlightColor);
309
0
        if (_bSelected)
310
0
        {
311
            // selected rows use the background color from the style
312
0
            backgroundColor = i_hasControlFocus
313
0
                ? activeSelectionBackColor
314
0
                : lcl_getEffectiveColor(m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor);
315
0
        }
316
0
        else
317
0
        {
318
0
            std::optional< std::vector<Color> > aRowColors = m_pImpl->rModel.getRowBackgroundColors();
319
0
            if (!aRowColors)
320
0
            {
321
                // use alternating default colors
322
0
                Color const fieldColor = _rStyle.GetFieldColor();
323
0
                if (_rStyle.GetHighContrastMode() || ((m_pImpl->nCurrentRow % 2) == 0))
324
0
                {
325
0
                    backgroundColor = fieldColor;
326
0
                }
327
0
                else
328
0
                {
329
0
                    Color hilightColor = activeSelectionBackColor;
330
0
                    hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() );
331
0
                    hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() );
332
0
                    hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() );
333
0
                    backgroundColor = hilightColor;
334
0
                }
335
0
            }
336
0
            else
337
0
            {
338
0
                if (aRowColors->empty())
339
0
                {
340
                    // all colors have the same background color
341
0
                    backgroundColor = _rStyle.GetFieldColor();
342
0
                }
343
0
                else
344
0
                {
345
0
                    backgroundColor = aRowColors->at(m_pImpl->nCurrentRow % aRowColors->size());
346
0
                }
347
0
            }
348
0
        }
349
350
0
        rRenderContext.SetLineColor();
351
0
        rRenderContext.SetFillColor(backgroundColor);
352
0
        rRenderContext.DrawRect(_rRowArea);
353
0
    }
354
355
356
    void GridTableRenderer::PaintRowHeader(vcl::RenderContext& rRenderContext,
357
                                           const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
358
0
    {
359
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::TEXTCOLOR);
360
361
0
        std::optional<Color> const aLineColor( m_pImpl->rModel.getLineColor() );
362
0
        Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
363
0
        rRenderContext.SetLineColor(lineColor);
364
0
        rRenderContext.DrawLine(_rArea.BottomLeft(), _rArea.BottomRight());
365
366
0
        Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) );
367
0
        OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) );
368
0
        if (!rowTitle.isEmpty())
369
0
        {
370
0
            Color const textColor = lcl_getEffectiveColor(m_pImpl->rModel.getHeaderTextColor(),
371
0
                                                          _rStyle, &StyleSettings::GetFieldTextColor);
372
0
            rRenderContext.SetTextColor(textColor);
373
374
0
            tools::Rectangle const aTextRect(lcl_getTextRenderingArea(lcl_getContentArea(*m_pImpl, _rArea)));
375
0
            DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags(*m_pImpl, 0) | DrawTextFlags::Clip;
376
0
            if (!m_pImpl->rModel.isEnabled())
377
0
                nDrawTextFlags |= DrawTextFlags::Disable;
378
                // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitrary ..
379
0
            rRenderContext.DrawText(aTextRect, rowTitle, nDrawTextFlags);
380
0
        }
381
0
    }
382
383
384
    struct GridTableRenderer::CellRenderContext
385
    {
386
        OutputDevice&           rDevice;
387
        tools::Rectangle const         aContentArea;
388
        StyleSettings const &   rStyle;
389
        ColPos const            nColumn;
390
        bool const              bSelected;
391
        bool const              bHasControlFocus;
392
393
        CellRenderContext( OutputDevice& i_device, tools::Rectangle const & i_contentArea,
394
            StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus )
395
0
            :rDevice( i_device )
396
0
            ,aContentArea( i_contentArea )
397
0
            ,rStyle( i_style )
398
0
            ,nColumn( i_column )
399
0
            ,bSelected( i_selected )
400
0
            ,bHasControlFocus( i_hasControlFocus )
401
0
        {
402
0
        }
403
    };
404
405
406
    void GridTableRenderer::PaintCell(ColPos const i_column, bool _bSelected, bool i_hasControlFocus,
407
                                      vcl::RenderContext& rRenderContext, const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
408
0
    {
409
0
        auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
410
411
0
        tools::Rectangle const aContentArea(lcl_getContentArea(*m_pImpl, _rArea));
412
0
        CellRenderContext const aCellRenderContext(rRenderContext, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus);
413
0
        impl_paintCellContent(aCellRenderContext);
414
415
0
        if ( m_pImpl->bUseGridLines )
416
0
        {
417
0
            ::std::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
418
0
            ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
419
420
0
            if ( _bSelected && !aLineColor )
421
0
            {
422
                // if no line color is specified by the model, use the usual selection color for lines in selected cells
423
0
                lineColor = i_hasControlFocus
424
0
                    ?   lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor )
425
0
                    :   lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
426
0
            }
427
428
0
            rRenderContext.SetLineColor( lineColor );
429
0
            rRenderContext.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
430
0
            rRenderContext.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
431
0
        }
432
0
    }
433
434
435
    void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image )
436
0
    {
437
0
        Point imagePos( i_context.aContentArea.Left(), i_context.aContentArea.Top() );
438
0
        Size imageSize = i_image.GetSizePixel();
439
0
        if ( i_context.aContentArea.GetWidth() > imageSize.Width() )
440
0
        {
441
0
            const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign();
442
0
            switch ( eHorzAlign )
443
0
            {
444
0
            case HorizontalAlignment_CENTER:
445
0
                imagePos.AdjustX(( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2 );
446
0
                break;
447
0
            case HorizontalAlignment_RIGHT:
448
0
                imagePos.setX( i_context.aContentArea.Right() - imageSize.Width() );
449
0
                break;
450
0
            default:
451
0
                break;
452
0
            }
453
454
0
        }
455
0
        else
456
0
            imageSize.setWidth( i_context.aContentArea.GetWidth() );
457
458
0
        if ( i_context.aContentArea.GetHeight() > imageSize.Height() )
459
0
        {
460
0
            const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign();
461
0
            switch ( eVertAlign )
462
0
            {
463
0
            case VerticalAlignment_MIDDLE:
464
0
                imagePos.AdjustY(( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2 );
465
0
                break;
466
0
            case VerticalAlignment_BOTTOM:
467
0
                imagePos.setY( i_context.aContentArea.Bottom() - imageSize.Height() );
468
0
                break;
469
0
            default:
470
0
                break;
471
0
            }
472
0
        }
473
0
        else
474
0
            imageSize.setHeight( i_context.aContentArea.GetHeight() - 1 );
475
0
        DrawImageFlags const nStyle = m_pImpl->rModel.isEnabled() ? DrawImageFlags::NONE : DrawImageFlags::Disable;
476
0
        i_context.rDevice.DrawImage( imagePos, imageSize, i_image, nStyle );
477
0
    }
478
479
480
    void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context )
481
0
    {
482
0
        Any aCellContent;
483
0
        m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent );
484
485
0
        if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE )
486
0
        {
487
0
            Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY );
488
0
            if ( !xContentInterface.is() )
489
                // allowed. kind of.
490
0
                return;
491
492
0
            Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY );
493
0
            ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." );
494
495
0
            const Image aImage( xGraphic );
496
0
            impl_paintCellImage( i_context, aImage );
497
0
            return;
498
0
        }
499
500
0
        const OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) );
501
0
        impl_paintCellText( i_context, sText );
502
0
    }
503
504
505
    void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, OUString const & i_text )
506
0
    {
507
0
        if ( i_context.bSelected )
508
0
        {
509
0
            ::Color const textColor = i_context.bHasControlFocus
510
0
                ?   lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor )
511
0
                :   lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor );
512
0
            i_context.rDevice.SetTextColor( textColor );
513
0
        }
514
0
        else
515
0
        {
516
0
            ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor );
517
0
            i_context.rDevice.SetTextColor( textColor );
518
0
        }
519
520
0
        tools::Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) );
521
0
        DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | DrawTextFlags::Clip;
522
0
        if ( !m_pImpl->rModel.isEnabled() )
523
0
            nDrawTextFlags |= DrawTextFlags::Disable;
524
0
        i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags );
525
0
    }
526
527
528
    void GridTableRenderer::ShowCellCursor( vcl::Window& _rView, const tools::Rectangle& _rCursorRect)
529
0
    {
530
0
        _rView.ShowFocus( _rCursorRect );
531
0
    }
532
533
534
    void GridTableRenderer::HideCellCursor( vcl::Window& _rView )
535
0
    {
536
0
        _rView.HideFocus();
537
0
    }
538
539
540
    bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent,
541
        OutputDevice& i_targetDevice, tools::Rectangle const & i_targetArea ) const
542
0
    {
543
0
        if ( !i_cellContent.hasValue() )
544
0
            return true;
545
546
0
        if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE )
547
0
        {
548
0
            Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY );
549
0
            if ( !xContentInterface.is() )
550
0
                return true;
551
552
0
            Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY );
553
0
            if ( xGraphic.is() )
554
                // for the moment, assume it fits. We can always scale it down during painting ...
555
0
                return true;
556
557
0
            OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." );
558
0
            return true;
559
0
        }
560
561
0
        OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) );
562
0
        if ( sText.isEmpty() )
563
0
            return true;
564
565
0
        tools::Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) );
566
567
0
        tools::Long const nTextHeight = i_targetDevice.GetTextHeight();
568
0
        if ( nTextHeight > aTargetArea.GetHeight() )
569
0
            return false;
570
571
0
        tools::Long const nTextWidth = i_targetDevice.GetTextWidth( sText );
572
0
        return nTextWidth <= aTargetArea.GetWidth();
573
0
    }
574
575
576
    bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, OUString & o_cellString ) const
577
0
    {
578
0
        o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue );
579
580
0
        return true;
581
0
    }
582
583
584
} // namespace svt::table
585
586
587
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */