Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/controls/table/tablecontrol.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
#include <controls/table/tablecontrol.hxx>
21
22
#include "tablecontrol_impl.hxx"
23
#include "tabledatawindow.hxx"
24
25
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
26
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
27
28
#include <sal/log.hxx>
29
#include <comphelper/diagnose_ex.hxx>
30
#include <vcl/settings.hxx>
31
#include <vcl/vclevent.hxx>
32
33
using namespace ::com::sun::star::uno;
34
using ::com::sun::star::accessibility::XAccessible;
35
using namespace ::com::sun::star::accessibility;
36
37
namespace svt::table
38
{
39
40
41
    namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
42
43
44
    //= TableControl
45
46
47
    TableControl::TableControl( vcl::Window* _pParent, WinBits _nStyle )
48
0
        :Control( _pParent, _nStyle )
49
0
        ,m_pImpl( std::make_shared<TableControl_Impl>( *this ) )
50
0
    {
51
0
        TableDataWindow& rDataWindow = m_pImpl->getDataWindow();
52
0
        rDataWindow.SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) );
53
54
        // by default, use the background as determined by the style settings
55
0
        const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
56
0
        SetBackground( Wallpaper( aWindowColor ) );
57
0
        GetOutDev()->SetFillColor( aWindowColor );
58
59
0
        SetCompoundControl( true );
60
0
    }
Unexecuted instantiation: svt::table::TableControl::TableControl(vcl::Window*, long)
Unexecuted instantiation: svt::table::TableControl::TableControl(vcl::Window*, long)
61
62
63
    TableControl::~TableControl()
64
0
    {
65
0
        disposeOnce();
66
0
    }
67
68
    void TableControl::dispose()
69
0
    {
70
0
        CallEventListeners( VclEventId::ObjectDying );
71
72
0
        m_pImpl->setModel( PTableModel() );
73
0
        m_pImpl->disposeAccessible();
74
0
        m_pImpl.reset();
75
0
        Control::dispose();
76
0
    }
77
78
79
    void TableControl::GetFocus()
80
0
    {
81
0
        if (m_pImpl)
82
0
            m_pImpl->showCursor();
83
84
0
        Control::GetFocus();
85
0
    }
86
87
88
    void TableControl::LoseFocus()
89
0
    {
90
0
        if (m_pImpl)
91
0
            m_pImpl->hideCursor();
92
93
0
        Control::LoseFocus();
94
0
    }
95
96
97
    void TableControl::KeyInput( const KeyEvent& rKEvt )
98
0
    {
99
0
        bool bHandled = false;
100
0
        if (m_pImpl)
101
0
        {
102
0
            const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
103
0
            sal_uInt16 nKeyCode = rKeyCode.GetCode();
104
105
0
            struct ActionMapEntry
106
0
            {
107
0
                sal_uInt16 nKeyCode;
108
0
                sal_uInt16 nKeyModifier;
109
0
                TableControlAction eAction;
110
0
            }
111
0
            static const aKnownActions[] = {
112
0
                      { KEY_DOWN,     0,          TableControlAction::cursorDown },
113
0
                      { KEY_UP,       0,          TableControlAction::cursorUp },
114
0
                      { KEY_LEFT,     0,          TableControlAction::cursorLeft },
115
0
                      { KEY_RIGHT,    0,          TableControlAction::cursorRight },
116
0
                      { KEY_HOME,     0,          TableControlAction::cursorToLineStart },
117
0
                      { KEY_END,      0,          TableControlAction::cursorToLineEnd },
118
0
                      { KEY_PAGEUP,   0,          TableControlAction::cursorPageUp },
119
0
                      { KEY_PAGEDOWN, 0,          TableControlAction::cursorPageDown },
120
0
                      { KEY_PAGEUP,   KEY_MOD1,   TableControlAction::cursorToFirstLine },
121
0
                      { KEY_PAGEDOWN, KEY_MOD1,   TableControlAction::cursorToLastLine },
122
0
                      { KEY_HOME,     KEY_MOD1,   TableControlAction::cursorTopLeft },
123
0
                      { KEY_END,      KEY_MOD1,   TableControlAction::cursorBottomRight },
124
0
                      { KEY_SPACE,    KEY_MOD1,   TableControlAction::cursorSelectRow },
125
0
                      { KEY_UP,       KEY_SHIFT,  TableControlAction::cursorSelectRowUp },
126
0
                      { KEY_DOWN,     KEY_SHIFT,  TableControlAction::cursorSelectRowDown },
127
0
                      { KEY_END,      KEY_SHIFT,  TableControlAction::cursorSelectRowAreaBottom },
128
0
                      { KEY_HOME,     KEY_SHIFT,  TableControlAction::cursorSelectRowAreaTop }
129
0
                  };
130
0
            for (const ActionMapEntry& rAction : aKnownActions)
131
0
            {
132
0
                if ((rAction.nKeyCode == nKeyCode) && (rAction.nKeyModifier == rKeyCode.GetModifier()))
133
0
                {
134
0
                    bHandled = m_pImpl->dispatchAction(rAction.eAction);
135
0
                    break;
136
0
                }
137
0
            }
138
0
        }
139
140
0
        if (!bHandled)
141
0
            Control::KeyInput( rKEvt );
142
0
        else
143
0
        {
144
0
            m_pImpl->commitCellEvent( AccessibleEventId::STATE_CHANGED,
145
0
                                      Any( AccessibleStateType::FOCUSED ),
146
0
                                      Any()
147
0
                                    );
148
                // Huh? What the heck? Why do we unconditionally notify a STATE_CHANGE/FOCUSED after each and every
149
                // (handled) key stroke?
150
151
0
            m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
152
0
                                       Any(),
153
0
                                       Any()
154
0
                                     );
155
                // ditto: Why do we notify this unconditionally? We should find the right place to notify the
156
                // ACTIVE_DESCENDANT_CHANGED event.
157
                // Also, we should check if STATE_CHANGED/FOCUSED is really necessary: finally, the children are
158
                // transient, aren't they?
159
0
        }
160
0
    }
161
162
163
    void TableControl::StateChanged( StateChangedType i_nStateChange )
164
0
    {
165
0
        Control::StateChanged( i_nStateChange );
166
167
        // forward certain settings to the data window
168
0
        switch ( i_nStateChange )
169
0
        {
170
0
        case StateChangedType::ControlFocus:
171
0
            m_pImpl->invalidateSelectedRows();
172
0
            break;
173
174
0
        case StateChangedType::ControlBackground:
175
0
            if ( IsControlBackground() )
176
0
                getDataWindow().SetControlBackground( GetControlBackground() );
177
0
            else
178
0
                getDataWindow().SetControlBackground();
179
0
            break;
180
181
0
        case StateChangedType::ControlForeground:
182
0
            if ( IsControlForeground() )
183
0
                getDataWindow().SetControlForeground( GetControlForeground() );
184
0
            else
185
0
                getDataWindow().SetControlForeground();
186
0
            break;
187
188
0
        case StateChangedType::ControlFont:
189
0
            if ( IsControlFont() )
190
0
                getDataWindow().SetControlFont( GetControlFont() );
191
0
            else
192
0
                getDataWindow().SetControlFont();
193
0
            break;
194
0
        default:;
195
0
        }
196
0
    }
197
198
199
    void TableControl::Resize()
200
0
    {
201
0
        Control::Resize();
202
0
        m_pImpl->onResize();
203
0
    }
204
205
206
    void TableControl::SetModel( const PTableModel& _pModel )
207
0
    {
208
0
        m_pImpl->setModel( _pModel );
209
0
    }
210
211
212
    PTableModel TableControl::GetModel() const
213
0
    {
214
0
        return m_pImpl->getModel();
215
0
    }
216
217
218
    sal_Int32 TableControl::GetCurrentRow() const
219
0
    {
220
0
        return m_pImpl->getCurrentRow();
221
0
    }
222
223
224
    sal_Int32 TableControl::GetCurrentColumn() const
225
0
    {
226
0
        return m_pImpl->getCurrentColumn();
227
0
    }
228
229
230
    void TableControl::GoTo( ColPos _nColumn, RowPos _nRow )
231
0
    {
232
0
        m_pImpl->goTo( _nColumn, _nRow );
233
0
    }
234
235
236
    void TableControl::GoToCell(sal_Int32 _nColPos, sal_Int32 _nRowPos)
237
0
    {
238
0
        m_pImpl->goTo( _nColPos, _nRowPos );
239
0
    }
240
241
242
    sal_Int32 TableControl::GetSelectedRowCount() const
243
0
    {
244
0
        return sal_Int32( m_pImpl->getSelectedRowCount() );
245
0
    }
246
247
248
    sal_Int32 TableControl::GetSelectedRowIndex( sal_Int32 const i_selectionIndex ) const
249
0
    {
250
0
        return m_pImpl->getSelectedRowIndex( i_selectionIndex );
251
0
    }
252
253
254
    bool TableControl::IsRowSelected( sal_Int32 const i_rowIndex ) const
255
0
    {
256
0
        return m_pImpl->isRowSelected( i_rowIndex );
257
0
    }
258
259
260
    void TableControl::SelectRow( sal_Int32 const i_rowIndex, bool const i_select )
261
0
    {
262
0
        ENSURE_OR_RETURN_VOID( ( i_rowIndex >= 0 ) && ( i_rowIndex < m_pImpl->getModel()->getRowCount() ),
263
0
            "TableControl::SelectRow: invalid row index!" );
264
265
0
        if ( i_select )
266
0
        {
267
0
            if ( !m_pImpl->markRowAsSelected( i_rowIndex ) )
268
                // nothing to do
269
0
                return;
270
0
        }
271
0
        else
272
0
        {
273
0
            m_pImpl->markRowAsDeselected( i_rowIndex );
274
0
        }
275
276
0
        m_pImpl->invalidateRowRange( i_rowIndex, i_rowIndex );
277
0
        Select();
278
0
    }
279
280
281
    void TableControl::SelectAllRows( bool const i_select )
282
0
    {
283
0
        if ( i_select )
284
0
        {
285
0
            if ( !m_pImpl->markAllRowsAsSelected() )
286
                // nothing to do
287
0
                return;
288
0
        }
289
0
        else
290
0
        {
291
0
            if ( !m_pImpl->markAllRowsAsDeselected() )
292
                // nothing to do
293
0
                return;
294
0
        }
295
296
297
0
        Invalidate();
298
            // TODO: can't we do better than this, and invalidate only the rows which changed?
299
0
        Select();
300
0
    }
301
302
    SelectionEngine* TableControl::getSelEngine()
303
0
    {
304
0
        return m_pImpl->getSelEngine();
305
0
    }
306
307
308
    vcl::Window& TableControl::getDataWindow()
309
0
    {
310
0
        return m_pImpl->getDataWindow();
311
0
    }
312
313
314
    rtl::Reference<comphelper::OAccessible> TableControl::CreateAccessible()
315
0
    {
316
0
        css::uno::Reference<css::accessibility::XAccessible> xParent = GetAccessibleParent();
317
0
        return m_pImpl->getAccessible(xParent);
318
0
    }
319
320
    OUString TableControl::GetAccessibleObjectName( AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const
321
0
    {
322
0
        OUString aRetText;
323
        //Window* pWin;
324
0
        switch( eObjType )
325
0
        {
326
0
            case AccessibleTableControlObjType::GRIDCONTROL:
327
0
                aRetText = "Grid control";
328
0
                break;
329
0
            case AccessibleTableControlObjType::TABLE:
330
0
                aRetText = "Grid control";
331
0
                break;
332
0
            case AccessibleTableControlObjType::ROWHEADERBAR:
333
0
                aRetText = "RowHeaderBar";
334
0
                break;
335
0
            case AccessibleTableControlObjType::COLUMNHEADERBAR:
336
0
                aRetText = "ColumnHeaderBar";
337
0
                break;
338
0
            case AccessibleTableControlObjType::TABLECELL:
339
                //the name of the cell consists of column name and row name if defined
340
                //if the name is equal to cell content, it'll be read twice
341
0
                if(GetModel()->hasColumnHeaders())
342
0
                {
343
0
                    aRetText = GetColumnName(_nCol) + " , ";
344
0
                }
345
0
                if(GetModel()->hasRowHeaders())
346
0
                {
347
0
                    aRetText += GetRowName(_nRow) + " , ";
348
0
                }
349
                //aRetText = GetAccessibleCellText(_nRow, _nCol);
350
0
                break;
351
0
            case AccessibleTableControlObjType::ROWHEADERCELL:
352
0
                aRetText = GetRowName(_nRow);
353
0
                break;
354
0
            case AccessibleTableControlObjType::COLUMNHEADERCELL:
355
0
                aRetText = GetColumnName(_nCol);
356
0
                break;
357
0
            default:
358
0
                OSL_FAIL("GridControl::GetAccessibleName: invalid enum!");
359
0
        }
360
0
        return aRetText;
361
0
    }
362
363
364
    OUString TableControl::GetAccessibleObjectDescription( AccessibleTableControlObjType eObjType ) const
365
0
    {
366
0
        OUString aRetText;
367
0
        switch( eObjType )
368
0
        {
369
0
            case AccessibleTableControlObjType::GRIDCONTROL:
370
0
                aRetText = "Grid control description";
371
0
                break;
372
0
            case AccessibleTableControlObjType::TABLE:
373
0
                    aRetText = "TABLE description";
374
0
                break;
375
0
            case AccessibleTableControlObjType::ROWHEADERBAR:
376
0
                    aRetText = "ROWHEADERBAR description";
377
0
                break;
378
0
            case AccessibleTableControlObjType::COLUMNHEADERBAR:
379
0
                    aRetText = "COLUMNHEADERBAR description";
380
0
                break;
381
0
            case AccessibleTableControlObjType::TABLECELL:
382
                // the description of the cell consists of column name and row name if defined
383
                // if the name is equal to cell content, it'll be read twice
384
0
                if ( GetModel()->hasColumnHeaders() )
385
0
                {
386
0
                    aRetText = GetColumnName( GetCurrentColumn() ) + " , ";
387
0
                }
388
0
                if ( GetModel()->hasRowHeaders() )
389
0
                {
390
0
                    aRetText += GetRowName( GetCurrentRow() );
391
0
                }
392
0
                break;
393
0
            case AccessibleTableControlObjType::ROWHEADERCELL:
394
0
                    aRetText = "ROWHEADERCELL description";
395
0
                break;
396
0
            case AccessibleTableControlObjType::COLUMNHEADERCELL:
397
0
                    aRetText = "COLUMNHEADERCELL description";
398
0
                break;
399
0
        }
400
0
        return aRetText;
401
0
    }
402
403
404
    OUString TableControl::GetRowName( sal_Int32 _nIndex) const
405
0
    {
406
0
        OUString sRowName;
407
0
        GetModel()->getRowHeading( _nIndex ) >>= sRowName;
408
0
        return sRowName;
409
0
    }
410
411
412
    OUString TableControl::GetColumnName( sal_Int32 _nIndex) const
413
0
    {
414
0
        return GetModel()->getColumnModel(_nIndex)->getName();
415
0
    }
416
417
418
    OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
419
0
    {
420
0
        return m_pImpl->getCellContentAsString( _nRowPos, _nColPos );
421
0
    }
422
423
424
    void TableControl::FillAccessibleStateSet(
425
            sal_Int64& rStateSet,
426
            AccessibleTableControlObjType eObjType ) const
427
0
    {
428
0
        switch( eObjType )
429
0
        {
430
0
            case AccessibleTableControlObjType::GRIDCONTROL:
431
0
            case AccessibleTableControlObjType::TABLE:
432
433
0
                rStateSet |= AccessibleStateType::FOCUSABLE;
434
435
0
                if ( m_pImpl->getSelEngine()->GetSelectionMode() == SelectionMode::Multiple )
436
0
                    rStateSet |= AccessibleStateType::MULTI_SELECTABLE;
437
438
0
                if ( HasChildPathFocus() )
439
0
                    rStateSet |= AccessibleStateType::FOCUSED;
440
441
0
                if ( IsActive() )
442
0
                    rStateSet |= AccessibleStateType::ACTIVE;
443
444
0
                if ( m_pImpl->getDataWindow().IsEnabled() )
445
0
                {
446
0
                    rStateSet |= AccessibleStateType::ENABLED;
447
0
                    rStateSet |= AccessibleStateType::SENSITIVE;
448
0
                }
449
450
0
                if ( IsReallyVisible() )
451
0
                    rStateSet |= AccessibleStateType::VISIBLE;
452
453
0
                if ( eObjType == AccessibleTableControlObjType::TABLE )
454
0
                    rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
455
0
                break;
456
457
0
            case AccessibleTableControlObjType::COLUMNHEADERBAR:
458
0
            case AccessibleTableControlObjType::ROWHEADERBAR:
459
0
                rStateSet |= AccessibleStateType::VISIBLE;
460
0
                rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
461
0
                break;
462
463
0
            case AccessibleTableControlObjType::TABLECELL:
464
0
                {
465
0
                    rStateSet |= AccessibleStateType::FOCUSABLE;
466
0
                    if ( HasChildPathFocus() )
467
0
                        rStateSet |= AccessibleStateType::FOCUSED;
468
0
                    rStateSet |= AccessibleStateType::ACTIVE;
469
0
                    rStateSet |= AccessibleStateType::TRANSIENT;
470
0
                    rStateSet |= AccessibleStateType::SELECTABLE;
471
0
                    rStateSet |= AccessibleStateType::VISIBLE;
472
0
                    rStateSet |= AccessibleStateType::SHOWING;
473
0
                    if ( IsRowSelected( GetCurrentRow() ) )
474
                        // Hmm? Wouldn't we expect the affected row to be a parameter to this function?
475
0
                        rStateSet |= AccessibleStateType::SELECTED;
476
0
                }
477
0
                break;
478
479
0
            case AccessibleTableControlObjType::ROWHEADERCELL:
480
0
                rStateSet |= AccessibleStateType::VISIBLE;
481
0
                rStateSet |= AccessibleStateType::TRANSIENT;
482
0
                break;
483
484
0
            case AccessibleTableControlObjType::COLUMNHEADERCELL:
485
0
                rStateSet |= AccessibleStateType::VISIBLE;
486
0
                break;
487
0
        }
488
0
    }
489
490
    void TableControl::commitCellEvent(sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue)
491
0
    {
492
0
        m_pImpl->commitCellEvent( i_eventID, i_newValue, i_oldValue );
493
0
    }
494
495
    void TableControl::commitTableEvent(sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue)
496
0
    {
497
0
        m_pImpl->commitTableEvent( i_eventID, i_newValue, i_oldValue );
498
0
    }
499
500
    bool TableControl::HasRowHeader()
501
0
    {
502
0
        return GetModel()->hasRowHeaders();
503
0
    }
504
505
506
    bool TableControl::HasColHeader()
507
0
    {
508
0
        return GetModel()->hasColumnHeaders();
509
0
    }
510
511
512
    sal_Int32 TableControl::GetAccessibleControlCount() const
513
0
    {
514
        // TC_TABLE is always defined, no matter whether empty or not
515
0
        sal_Int32 count = 1;
516
0
        if ( GetModel()->hasRowHeaders() )
517
0
            ++count;
518
0
        if ( GetModel()->hasColumnHeaders() )
519
0
            ++count;
520
0
        return count;
521
0
    }
522
523
    sal_Int32 TableControl::GetRowCount() const
524
0
    {
525
0
        return GetModel()->getRowCount();
526
0
    }
527
528
529
    sal_Int32 TableControl::GetColumnCount() const
530
0
    {
531
0
        return GetModel()->getColumnCount();
532
0
    }
533
534
535
    bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )
536
0
    {
537
0
        _rnRow = m_pImpl->getRowAtPoint( _rPoint );
538
0
        _rnColPos = m_pImpl->getColAtPoint( _rPoint );
539
0
        return _rnRow >= 0;
540
0
    }
541
542
543
    void TableControl::FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 ) const
544
0
    {
545
0
        if ( IsRowSelected( _nRow ) )
546
0
            _rStateSet |= AccessibleStateType::SELECTED;
547
0
        if ( HasChildPathFocus() )
548
0
            _rStateSet |= AccessibleStateType::FOCUSED;
549
0
        else // only transient when column is not focused
550
0
            _rStateSet |= AccessibleStateType::TRANSIENT;
551
552
0
        _rStateSet |= AccessibleStateType::VISIBLE;
553
0
        _rStateSet |= AccessibleStateType::SHOWING;
554
0
        _rStateSet |= AccessibleStateType::ENABLED;
555
0
        _rStateSet |= AccessibleStateType::SENSITIVE;
556
0
        _rStateSet |= AccessibleStateType::ACTIVE;
557
0
    }
558
559
560
    tools::Rectangle TableControl::calcHeaderRect(bool _bIsColumnBar )
561
0
    {
562
0
        return m_pImpl->calcHeaderRect(_bIsColumnBar);
563
0
    }
564
565
566
    tools::Rectangle TableControl::calcHeaderCellRect( bool _bIsColumnBar, sal_Int32 nPos )
567
0
    {
568
0
        return m_pImpl->calcHeaderCellRect( _bIsColumnBar, nPos );
569
0
    }
570
571
572
    tools::Rectangle TableControl::calcTableRect()
573
0
    {
574
0
        return m_pImpl->calcTableRect();
575
0
    }
576
577
578
    tools::Rectangle TableControl::calcCellRect( sal_Int32 _nRowPos, sal_Int32 _nColPos )
579
0
    {
580
0
        return m_pImpl->calcCellRect( _nRowPos, _nColPos );
581
0
    }
582
583
584
    IMPL_LINK_NOARG(TableControl, ImplSelectHdl, LinkParamNone*, void)
585
0
    {
586
0
        Select();
587
0
    }
588
589
590
    void TableControl::Select()
591
0
    {
592
0
        ImplCallEventListenersAndHandler( VclEventId::TableRowSelect, nullptr );
593
0
        m_pImpl->commitAccessibleEvent( AccessibleEventId::SELECTION_CHANGED );
594
595
0
        m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), Any() );
596
            // TODO: why do we notify this when the *selection* changed? Shouldn't we find a better place for this,
597
            // actually, when the active descendant, i.e. the current cell, *really* changed?
598
0
    }
599
600
    TableCell TableControl::hitTest(const Point& rPoint) const
601
0
    {
602
0
        return m_pImpl->hitTest(rPoint);
603
0
    }
604
605
    void TableControl::invalidate(const TableArea aArea)
606
0
    {
607
0
        return m_pImpl->invalidate(aArea);
608
0
    }
609
610
} // namespace svt::table
611
612
613
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */