Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/controls/svtxgridcontrol.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 <awt/vclxwindows.hxx>
21
#include <cppuhelper/implbase.hxx>
22
#include <toolkit/helper/listenermultiplexer.hxx>
23
#include <com/sun/star/view/SelectionType.hpp>
24
#include <controls/table/TableControl.hxx>
25
#include <controls/table/tablecontrolinterface.hxx>
26
#include <controls/table/gridtablerenderer.hxx>
27
#include "unocontroltablemodel.hxx"
28
#include <sal/log.hxx>
29
#include <tools/mapunit.hxx>
30
#include <comphelper/diagnose_ex.hxx>
31
#include <helper/property.hxx>
32
#include <com/sun/star/awt/grid/XGridColumn.hpp>
33
#include <com/sun/star/awt/grid/GridInvalidDataException.hpp>
34
#include <com/sun/star/awt/grid/GridInvalidModelException.hpp>
35
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
36
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
37
#include <com/sun/star/util/Color.hpp>
38
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
39
40
#include <vcl/svapp.hxx>
41
#include <vcl/vclevent.hxx>
42
43
#include <algorithm>
44
45
using css::uno::Reference;
46
using css::uno::Exception;
47
using css::uno::UNO_QUERY;
48
using css::uno::UNO_QUERY_THROW;
49
using css::uno::Any;
50
using css::uno::Sequence;
51
using css::awt::grid::XGridSelectionListener;
52
using css::style::VerticalAlignment;
53
using css::style::VerticalAlignment_TOP;
54
using css::view::SelectionType;
55
using css::view::SelectionType_NONE;
56
using css::view::SelectionType_RANGE;
57
using css::view::SelectionType_SINGLE;
58
using css::view::SelectionType_MULTI;
59
using css::awt::grid::XGridDataModel;
60
using css::awt::grid::GridInvalidDataException;
61
using css::lang::EventObject;
62
using css::lang::IndexOutOfBoundsException;
63
using css::awt::grid::XGridColumnModel;
64
using css::awt::grid::GridSelectionEvent;
65
using css::awt::grid::XGridColumn;
66
using css::container::ContainerEvent;
67
using css::awt::grid::GridDataEvent;
68
using css::awt::grid::GridInvalidModelException;
69
70
namespace AccessibleEventId = css::accessibility::AccessibleEventId;
71
namespace AccessibleStateType = css::accessibility::AccessibleStateType;
72
73
using namespace ::svt::table;
74
75
76
SVTXGridControl::SVTXGridControl()
77
0
    :m_xTableModel( std::make_shared<UnoControlTableModel>() )
78
0
    ,m_bTableModelInitCompleted( false )
79
0
    ,m_aSelectionListeners( *this )
80
0
{
81
0
}
82
83
84
SVTXGridControl::~SVTXGridControl()
85
0
{
86
0
}
87
88
89
void SVTXGridControl::SetWindow( const VclPtr< vcl::Window > &pWindow )
90
0
{
91
0
    SVTXGridControl_Base::SetWindow( pWindow );
92
0
    impl_checkTableModelInit();
93
0
}
94
95
void SVTXGridControl::impl_checkColumnIndex_throw(svt::table::TableControl const& i_table,
96
                                                  sal_Int32 const i_columnIndex) const
97
0
{
98
0
    if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= i_table.GetColumnCount() ) )
99
0
        throw IndexOutOfBoundsException( OUString(), *const_cast< SVTXGridControl* >( this ) );
100
0
}
101
102
void SVTXGridControl::impl_checkRowIndex_throw(svt::table::TableControl const& i_table,
103
                                               sal_Int32 const i_rowIndex) const
104
0
{
105
0
    if ( ( i_rowIndex < 0 ) || ( i_rowIndex >= i_table.GetRowCount() ) )
106
0
        throw IndexOutOfBoundsException( OUString(), *const_cast< SVTXGridControl* >( this ) );
107
0
}
108
109
110
sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
111
0
{
112
0
    SolarMutexGuard aGuard;
113
114
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
115
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getRowAtPoint: no control (anymore)!", -1 );
116
117
0
    TableCell const tableCell = pTable->hitTest(Point(x, y));
118
0
    return ( tableCell.nRow >= 0 ) ? tableCell.nRow : -1;
119
0
}
120
121
122
sal_Int32 SAL_CALL SVTXGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
123
0
{
124
0
    SolarMutexGuard aGuard;
125
126
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
127
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getColumnAtPoint: no control (anymore)!", -1 );
128
129
0
    TableCell const tableCell = pTable->hitTest(Point(x, y));
130
0
    return ( tableCell.nColumn >= 0 ) ? tableCell.nColumn : -1;
131
0
}
132
133
134
sal_Int32 SAL_CALL SVTXGridControl::getCurrentColumn(  )
135
0
{
136
0
    SolarMutexGuard aGuard;
137
138
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
139
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getCurrentColumn: no control (anymore)!", -1 );
140
141
0
    sal_Int32 const nColumn = pTable->GetCurrentColumn();
142
0
    return ( nColumn >= 0 ) ? nColumn : -1;
143
0
}
144
145
146
sal_Int32 SAL_CALL SVTXGridControl::getCurrentRow(  )
147
0
{
148
0
    SolarMutexGuard aGuard;
149
150
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
151
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getCurrentRow: no control (anymore)!", -1 );
152
153
0
    sal_Int32 const nRow = pTable->GetCurrentRow();
154
0
    return ( nRow >= 0 ) ? nRow : -1;
155
0
}
156
157
158
void SAL_CALL SVTXGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
159
0
{
160
0
    SolarMutexGuard aGuard;
161
162
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
163
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::getCurrentRow: no control (anymore)!" );
164
165
0
    impl_checkColumnIndex_throw( *pTable, i_columnIndex );
166
0
    impl_checkRowIndex_throw( *pTable, i_rowIndex );
167
168
0
    pTable->GoToCell(i_columnIndex, i_rowIndex);
169
0
}
170
171
172
void SAL_CALL SVTXGridControl::addSelectionListener(const Reference< XGridSelectionListener > & listener)
173
0
{
174
0
    m_aSelectionListeners.addInterface(listener);
175
0
}
176
177
178
void SAL_CALL SVTXGridControl::removeSelectionListener(const Reference< XGridSelectionListener > & listener)
179
0
{
180
0
    m_aSelectionListeners.removeInterface(listener);
181
0
}
182
183
184
void SVTXGridControl::setProperty( const OUString& PropertyName, const Any& aValue)
185
0
{
186
0
    SolarMutexGuard aGuard;
187
188
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
189
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::setProperty: no control (anymore)!" );
190
191
0
    switch( GetPropertyId( PropertyName ) )
192
0
    {
193
0
        case BASEPROPERTY_ROW_HEADER_WIDTH:
194
0
        {
195
0
            sal_Int32 rowHeaderWidth( -1 );
196
0
            aValue >>= rowHeaderWidth;
197
0
            if ( rowHeaderWidth <= 0 )
198
0
            {
199
0
                SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal row header width!" );
200
0
                break;
201
0
            }
202
203
0
            m_xTableModel->setRowHeaderWidth( rowHeaderWidth );
204
            // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
205
0
            pTable->Invalidate();
206
0
        }
207
0
        break;
208
209
0
        case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
210
0
        {
211
0
            sal_Int32 columnHeaderHeight = 0;
212
0
            if ( !aValue.hasValue() )
213
0
            {
214
0
                columnHeaderHeight = pTable->PixelToLogic(Size(0, pTable->GetTextHeight() + 3), MapMode(MapUnit::MapAppFont)).Height();
215
0
            }
216
0
            else
217
0
            {
218
0
                aValue >>= columnHeaderHeight;
219
0
            }
220
0
            if ( columnHeaderHeight <= 0 )
221
0
            {
222
0
                SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal column header width!" );
223
0
                break;
224
0
            }
225
226
0
            m_xTableModel->setColumnHeaderHeight( columnHeaderHeight );
227
            // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
228
0
            pTable->Invalidate();
229
0
        }
230
0
        break;
231
232
0
        case BASEPROPERTY_USE_GRID_LINES:
233
0
        {
234
0
            GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
235
0
                m_xTableModel->getRenderer().get() );
236
0
            if ( !pGridRenderer )
237
0
            {
238
0
                SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty(UseGridLines): invalid renderer!" );
239
0
                break;
240
0
            }
241
242
0
            bool bUseGridLines = false;
243
0
            OSL_VERIFY( aValue >>= bUseGridLines );
244
0
            pGridRenderer->useGridLines( bUseGridLines );
245
0
            pTable->Invalidate();
246
0
        }
247
0
        break;
248
249
0
        case BASEPROPERTY_ROW_HEIGHT:
250
0
        {
251
0
            sal_Int32 rowHeight = 0;
252
0
            if ( !aValue.hasValue() )
253
0
            {
254
0
                rowHeight = pTable->PixelToLogic(Size(0, pTable->GetTextHeight() + 3), MapMode(MapUnit::MapAppFont)).Height();
255
0
            }
256
0
            else
257
0
            {
258
0
                aValue >>= rowHeight;
259
0
            }
260
0
            m_xTableModel->setRowHeight( rowHeight );
261
0
            if ( rowHeight <= 0 )
262
0
            {
263
0
                SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal row height!" );
264
0
                break;
265
0
            }
266
267
            // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
268
0
            pTable->Invalidate();
269
0
        }
270
0
        break;
271
272
0
        case BASEPROPERTY_BACKGROUNDCOLOR:
273
0
        {
274
            // let the base class handle this for the TableControl
275
0
            VCLXWindow::setProperty( PropertyName, aValue );
276
            // and forward to the grid control's data window
277
0
            if ( pTable->IsBackground() )
278
0
                pTable->getDataWindow().SetBackground( pTable->GetBackground() );
279
0
            else
280
0
                pTable->getDataWindow().SetBackground();
281
0
        }
282
0
        break;
283
284
0
        case BASEPROPERTY_GRID_SELECTIONMODE:
285
0
        {
286
0
            SelectionType eSelectionType;
287
0
            if( aValue >>= eSelectionType )
288
0
            {
289
0
                SelectionMode eSelMode;
290
0
                switch( eSelectionType )
291
0
                {
292
0
                case SelectionType_SINGLE:  eSelMode = SelectionMode::Single; break;
293
0
                case SelectionType_RANGE:   eSelMode = SelectionMode::Range; break;
294
0
                case SelectionType_MULTI:   eSelMode = SelectionMode::Multiple; break;
295
0
                default:                    eSelMode = SelectionMode::NONE; break;
296
0
                }
297
0
                if( pTable->getSelEngine()->GetSelectionMode() != eSelMode )
298
0
                    pTable->getSelEngine()->SetSelectionMode( eSelMode );
299
0
            }
300
0
            break;
301
0
        }
302
0
        case BASEPROPERTY_HSCROLL:
303
0
        {
304
0
            bool bHScroll = true;
305
0
            if( aValue >>= bHScroll )
306
0
                m_xTableModel->setHorizontalScrollbarVisibility( bHScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
307
0
            break;
308
0
        }
309
310
0
        case BASEPROPERTY_VSCROLL:
311
0
        {
312
0
            bool bVScroll = true;
313
0
            if( aValue >>= bVScroll )
314
0
            {
315
0
                m_xTableModel->setVerticalScrollbarVisibility( bVScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
316
0
            }
317
0
            break;
318
0
        }
319
320
0
        case BASEPROPERTY_GRID_SHOWROWHEADER:
321
0
        {
322
0
            bool rowHeader = true;
323
0
            if( aValue >>= rowHeader )
324
0
            {
325
0
                m_xTableModel->setRowHeaders(rowHeader);
326
0
            }
327
0
            break;
328
0
        }
329
330
0
        case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
331
0
            m_xTableModel->setRowBackgroundColors( aValue );
332
0
            pTable->Invalidate();
333
0
            break;
334
335
0
        case BASEPROPERTY_GRID_LINE_COLOR:
336
0
            m_xTableModel->setLineColor( aValue );
337
0
            pTable->Invalidate();
338
0
            break;
339
340
0
        case BASEPROPERTY_GRID_HEADER_BACKGROUND:
341
0
            m_xTableModel->setHeaderBackgroundColor( aValue );
342
0
            pTable->Invalidate();
343
0
            break;
344
345
0
        case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
346
0
            m_xTableModel->setHeaderTextColor( aValue );
347
0
            pTable->Invalidate();
348
0
            break;
349
350
0
        case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
351
0
            m_xTableModel->setActiveSelectionBackColor( aValue );
352
0
            pTable->Invalidate();
353
0
            break;
354
355
0
        case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
356
0
            m_xTableModel->setInactiveSelectionBackColor( aValue );
357
0
            pTable->Invalidate();
358
0
            break;
359
360
0
        case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
361
0
            m_xTableModel->setActiveSelectionTextColor( aValue );
362
0
            pTable->Invalidate();
363
0
            break;
364
365
0
        case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
366
0
            m_xTableModel->setInactiveSelectionTextColor( aValue );
367
0
            pTable->Invalidate();
368
0
            break;
369
370
371
0
        case BASEPROPERTY_TEXTCOLOR:
372
0
            m_xTableModel->setTextColor( aValue );
373
0
            pTable->Invalidate();
374
0
            break;
375
376
0
        case BASEPROPERTY_TEXTLINECOLOR:
377
0
            m_xTableModel->setTextLineColor( aValue );
378
0
            pTable->Invalidate();
379
0
            break;
380
381
0
        case BASEPROPERTY_VERTICALALIGN:
382
0
        {
383
0
            VerticalAlignment eAlign( VerticalAlignment_TOP );
384
0
            if ( aValue >>= eAlign )
385
0
                m_xTableModel->setVerticalAlign( eAlign );
386
0
            break;
387
0
        }
388
389
0
        case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
390
0
        {
391
0
            bool colHeader = true;
392
0
            if( aValue >>= colHeader )
393
0
            {
394
0
                m_xTableModel->setColumnHeaders(colHeader);
395
0
            }
396
0
            break;
397
0
        }
398
0
        case BASEPROPERTY_GRID_DATAMODEL:
399
0
        {
400
0
            Reference< XGridDataModel > const xDataModel( aValue, UNO_QUERY );
401
0
            if ( !xDataModel.is() )
402
0
                throw GridInvalidDataException(u"Invalid data model."_ustr, *this );
403
404
0
            m_xTableModel->setDataModel( xDataModel );
405
0
            impl_checkTableModelInit();
406
0
        }
407
0
        break;
408
409
0
        case BASEPROPERTY_GRID_COLUMNMODEL:
410
0
        {
411
            // obtain new col model
412
0
            Reference< XGridColumnModel > const xColumnModel( aValue, UNO_QUERY );
413
0
            if ( !xColumnModel.is() )
414
0
                throw GridInvalidModelException(u"Invalid column model."_ustr, *this );
415
416
            // remove all old columns
417
0
            m_xTableModel->removeAllColumns();
418
419
            // announce to the TableModel
420
0
            m_xTableModel->setColumnModel( xColumnModel );
421
0
            impl_checkTableModelInit();
422
423
            // add new columns
424
0
            impl_updateColumnsFromModel_nothrow();
425
0
            break;
426
0
        }
427
0
        default:
428
0
            VCLXWindow::setProperty( PropertyName, aValue );
429
0
        break;
430
0
    }
431
0
}
432
433
434
void SVTXGridControl::impl_checkTableModelInit()
435
0
{
436
0
    if ( !(!m_bTableModelInitCompleted && m_xTableModel->hasColumnModel() && m_xTableModel->hasDataModel()) )
437
0
        return;
438
439
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
440
0
    if ( !pTable )
441
0
        return;
442
443
0
    pTable->SetModel(m_xTableModel);
444
445
0
    m_bTableModelInitCompleted = true;
446
447
    // ensure default columns exist, if they have not previously been added
448
0
    Reference< XGridDataModel > const xDataModel( m_xTableModel->getDataModel(), css::uno::UNO_SET_THROW );
449
0
    Reference< XGridColumnModel > const xColumnModel( m_xTableModel->getColumnModel(), css::uno::UNO_SET_THROW );
450
451
0
    sal_Int32 const nDataColumnCount = xDataModel->getColumnCount();
452
0
    if ( ( nDataColumnCount > 0 ) && ( xColumnModel->getColumnCount() == 0 ) )
453
0
        xColumnModel->setDefaultColumns( nDataColumnCount );
454
        // this will trigger notifications, which in turn will let us update our m_xTableModel
455
0
}
456
457
namespace
458
{
459
    void lcl_convertColor( ::std::optional< ::Color > const & i_color, Any & o_colorValue )
460
0
    {
461
0
        if ( !i_color )
462
0
            o_colorValue.clear();
463
0
        else
464
0
            o_colorValue <<= sal_Int32(*i_color);
465
0
    }
466
}
467
468
Any SVTXGridControl::getProperty( const OUString& PropertyName )
469
0
{
470
0
    SolarMutexGuard aGuard;
471
472
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
473
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getProperty: no control (anymore)!", Any() );
474
475
0
    Any aPropertyValue;
476
477
0
    const sal_uInt16 nPropId = GetPropertyId( PropertyName );
478
0
    switch(nPropId)
479
0
    {
480
0
    case BASEPROPERTY_GRID_SELECTIONMODE:
481
0
    {
482
0
        SelectionType eSelectionType;
483
484
0
        SelectionMode eSelMode = pTable->getSelEngine()->GetSelectionMode();
485
0
        switch( eSelMode )
486
0
        {
487
0
            case SelectionMode::Single:  eSelectionType = SelectionType_SINGLE; break;
488
0
            case SelectionMode::Range:   eSelectionType = SelectionType_RANGE; break;
489
0
            case SelectionMode::Multiple:eSelectionType = SelectionType_MULTI; break;
490
0
            default:                eSelectionType = SelectionType_NONE; break;
491
0
        }
492
0
        aPropertyValue <<= eSelectionType;
493
0
        break;
494
0
    }
495
496
0
    case BASEPROPERTY_GRID_SHOWROWHEADER:
497
0
        aPropertyValue <<= m_xTableModel->hasRowHeaders();
498
0
        break;
499
500
0
    case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
501
0
        aPropertyValue <<= m_xTableModel->hasColumnHeaders();
502
0
        break;
503
504
0
    case BASEPROPERTY_GRID_DATAMODEL:
505
0
        aPropertyValue <<= m_xTableModel->getDataModel();
506
0
        break;
507
508
0
    case BASEPROPERTY_GRID_COLUMNMODEL:
509
0
        aPropertyValue <<= m_xTableModel->getColumnModel();
510
0
        break;
511
512
0
    case BASEPROPERTY_HSCROLL:
513
0
        {
514
0
            bool const bHasScrollbar = ( m_xTableModel->getHorizontalScrollbarVisibility() != ScrollbarShowNever );
515
0
            aPropertyValue <<= bHasScrollbar;
516
0
            break;
517
0
        }
518
519
0
    case BASEPROPERTY_VSCROLL:
520
0
        {
521
0
            bool const bHasScrollbar = ( m_xTableModel->getVerticalScrollbarVisibility() != ScrollbarShowNever );
522
0
            aPropertyValue <<= bHasScrollbar;
523
0
            break;
524
0
        }
525
526
0
    case BASEPROPERTY_USE_GRID_LINES:
527
0
    {
528
0
        GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
529
0
            m_xTableModel->getRenderer().get() );
530
0
        if ( !pGridRenderer )
531
0
        {
532
0
            SAL_WARN( "svtools.uno", "SVTXGridControl::getProperty(UseGridLines): invalid renderer!" );
533
0
            break;
534
0
        }
535
536
0
        aPropertyValue <<= pGridRenderer->useGridLines();
537
0
    }
538
0
    break;
539
540
0
    case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
541
0
    {
542
0
        ::std::optional< ::std::vector< ::Color > > aColors( m_xTableModel->getRowBackgroundColors() );
543
0
        if ( !aColors )
544
0
            aPropertyValue.clear();
545
0
        else
546
0
        {
547
0
            Sequence< css::util::Color > aAPIColors( aColors->size() );
548
0
            std::transform(aColors->begin(), aColors->end(), aAPIColors.getArray(),
549
0
                           [](const auto& color) { return sal_Int32(color); });
550
0
            aPropertyValue <<= aAPIColors;
551
0
        }
552
0
    }
553
0
    break;
554
555
0
    case BASEPROPERTY_GRID_LINE_COLOR:
556
0
        lcl_convertColor( m_xTableModel->getLineColor(), aPropertyValue );
557
0
        break;
558
559
0
    case BASEPROPERTY_GRID_HEADER_BACKGROUND:
560
0
        lcl_convertColor( m_xTableModel->getHeaderBackgroundColor(), aPropertyValue );
561
0
        break;
562
563
0
    case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
564
0
        lcl_convertColor( m_xTableModel->getHeaderTextColor(), aPropertyValue );
565
0
        break;
566
567
0
    case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
568
0
        lcl_convertColor( m_xTableModel->getActiveSelectionBackColor(), aPropertyValue );
569
0
        break;
570
571
0
    case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
572
0
        lcl_convertColor( m_xTableModel->getInactiveSelectionBackColor(), aPropertyValue );
573
0
        break;
574
575
0
    case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
576
0
        lcl_convertColor( m_xTableModel->getActiveSelectionTextColor(), aPropertyValue );
577
0
        break;
578
579
0
    case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
580
0
        lcl_convertColor( m_xTableModel->getInactiveSelectionTextColor(), aPropertyValue );
581
0
        break;
582
583
0
    case BASEPROPERTY_TEXTCOLOR:
584
0
        lcl_convertColor( m_xTableModel->getTextColor(), aPropertyValue );
585
0
        break;
586
587
0
    case BASEPROPERTY_TEXTLINECOLOR:
588
0
        lcl_convertColor( m_xTableModel->getTextLineColor(), aPropertyValue );
589
0
        break;
590
591
0
    default:
592
0
        aPropertyValue = VCLXWindow::getProperty( PropertyName );
593
0
        break;
594
0
    }
595
596
0
    return aPropertyValue;
597
0
}
598
599
600
void SAL_CALL SVTXGridControl::rowsInserted( const GridDataEvent& i_event )
601
0
{
602
0
    SolarMutexGuard aGuard;
603
0
    m_xTableModel->notifyRowsInserted( i_event );
604
0
}
605
606
607
void SAL_CALL
608
 SVTXGridControl::rowsRemoved( const GridDataEvent& i_event )
609
0
{
610
0
    SolarMutexGuard aGuard;
611
0
    m_xTableModel->notifyRowsRemoved( i_event );
612
0
}
613
614
615
void SAL_CALL SVTXGridControl::dataChanged( const GridDataEvent& i_event )
616
0
{
617
0
    SolarMutexGuard aGuard;
618
619
0
    m_xTableModel->notifyDataChanged( i_event );
620
621
    // if the data model is sortable, a dataChanged event is also fired in case the sort order changed.
622
    // So, just in case, invalidate the column header area, too.
623
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
624
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::dataChanged: no control (anymore)!" );
625
0
    pTable->invalidate(TableArea::ColumnHeaders);
626
0
}
627
628
629
void SAL_CALL SVTXGridControl::rowHeadingChanged( const GridDataEvent& )
630
0
{
631
0
    SolarMutexGuard aGuard;
632
633
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
634
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::rowHeadingChanged: no control (anymore)!" );
635
636
0
    pTable->invalidate(TableArea::RowHeaders);
637
0
}
638
639
640
void SAL_CALL SVTXGridControl::elementInserted( const ContainerEvent& i_event )
641
0
{
642
0
    SolarMutexGuard aGuard;
643
644
0
    Reference< XGridColumn > const xGridColumn( i_event.Element, UNO_QUERY_THROW );
645
646
0
    sal_Int32 nIndex( m_xTableModel->getColumnCount() );
647
0
    OSL_VERIFY( i_event.Accessor >>= nIndex );
648
0
    m_xTableModel->insertColumn( nIndex, xGridColumn );
649
0
}
650
651
652
void SAL_CALL SVTXGridControl::elementRemoved( const ContainerEvent& i_event )
653
0
{
654
0
    SolarMutexGuard aGuard;
655
656
0
    sal_Int32 nIndex( -1 );
657
0
    OSL_VERIFY( i_event.Accessor >>= nIndex );
658
0
    m_xTableModel->removeColumn( nIndex );
659
0
}
660
661
662
void SAL_CALL SVTXGridControl::elementReplaced( const ContainerEvent& )
663
0
{
664
0
    OSL_ENSURE( false, "SVTXGridControl::elementReplaced: not implemented!" );
665
        // at the moment, the XGridColumnModel API does not allow replacing columns
666
    // TODO: replace the respective column in our table model
667
0
}
668
669
670
void SAL_CALL SVTXGridControl::disposing(const EventObject&)
671
0
{
672
0
}
673
674
675
void SAL_CALL SVTXGridControl::selectRow( ::sal_Int32 i_rowIndex )
676
0
{
677
0
    SolarMutexGuard aGuard;
678
679
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
680
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectRow: no control (anymore)!" );
681
682
0
    impl_checkRowIndex_throw( *pTable, i_rowIndex );
683
684
0
    pTable->SelectRow( i_rowIndex, true );
685
0
}
686
687
688
void SAL_CALL SVTXGridControl::selectAllRows()
689
0
{
690
0
    SolarMutexGuard aGuard;
691
692
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
693
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectAllRows: no control (anymore)!" );
694
695
0
    pTable->SelectAllRows( true );
696
0
}
697
698
699
void SAL_CALL SVTXGridControl::deselectRow( ::sal_Int32 i_rowIndex )
700
0
{
701
0
    SolarMutexGuard aGuard;
702
703
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
704
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectRow: no control (anymore)!" );
705
706
0
    impl_checkRowIndex_throw( *pTable, i_rowIndex );
707
708
0
    pTable->SelectRow( i_rowIndex, false );
709
0
}
710
711
712
void SAL_CALL SVTXGridControl::deselectAllRows()
713
0
{
714
0
    SolarMutexGuard aGuard;
715
716
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
717
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectAllRows: no control (anymore)!" );
718
719
0
    pTable->SelectAllRows( false );
720
0
}
721
722
723
Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelectedRows()
724
0
{
725
0
    SolarMutexGuard aGuard;
726
727
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
728
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelectedRows: no control (anymore)!", Sequence< sal_Int32 >() );
729
730
0
    sal_Int32 selectionCount = pTable->GetSelectedRowCount();
731
0
    Sequence< sal_Int32 > selectedRows( selectionCount );
732
0
    auto selectedRowsRange = asNonConstRange(selectedRows);
733
0
    for ( sal_Int32 i=0; i<selectionCount; ++i )
734
0
        selectedRowsRange[i] = pTable->GetSelectedRowIndex(i);
735
0
    return selectedRows;
736
0
}
737
738
739
sal_Bool SAL_CALL SVTXGridControl::hasSelectedRows()
740
0
{
741
0
    SolarMutexGuard aGuard;
742
743
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
744
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::hasSelectedRows: no control (anymore)!", true );
745
746
0
    return pTable->GetSelectedRowCount() > 0;
747
0
}
748
749
750
sal_Bool SAL_CALL SVTXGridControl::isRowSelected( ::sal_Int32 index )
751
0
{
752
0
    SolarMutexGuard aGuard;
753
754
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
755
0
    ENSURE_OR_RETURN( pTable, "SVTXGridControl::isRowSelected: no control (anymore)!", false );
756
757
0
    return pTable->IsRowSelected( index );
758
0
}
759
760
761
void SVTXGridControl::dispose()
762
0
{
763
0
    EventObject aObj;
764
0
    aObj.Source = getXWeak();
765
0
    m_aSelectionListeners.disposeAndClear( aObj );
766
0
    VCLXWindow::dispose();
767
0
}
768
769
770
void SVTXGridControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
771
0
{
772
0
    SolarMutexGuard aGuard;
773
774
0
    Reference< XWindow > xKeepAlive( this );
775
776
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
777
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ProcessWindowEvent: no control (anymore)!" );
778
779
0
    bool handled = false;
780
0
    switch ( rVclWindowEvent.GetId() )
781
0
    {
782
0
        case VclEventId::TableRowSelect:
783
0
        {
784
0
            if ( m_aSelectionListeners.getLength() )
785
0
                ImplCallItemListeners();
786
0
            handled = true;
787
0
        }
788
0
        break;
789
790
0
        case VclEventId::ControlGetFocus:
791
0
        {
792
            // TODO: this doesn't belong here. It belongs into the TableControl, so A11Y also
793
            // works when the control is used outside the UNO context
794
0
            if (pTable->GetCurrentRow() !=  ROW_INVALID && pTable->GetCurrentColumn() != COL_INVALID)
795
0
            {
796
0
                pTable->commitCellEvent(
797
0
                    AccessibleEventId::STATE_CHANGED,
798
0
                    Any( AccessibleStateType::FOCUSED ),
799
0
                    Any()
800
0
                );
801
0
                pTable->commitTableEvent(
802
0
                    AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
803
0
                    Any(),
804
0
                    Any()
805
0
                );
806
0
            }
807
0
            else
808
0
            {
809
0
                pTable->commitTableEvent(
810
0
                    AccessibleEventId::STATE_CHANGED,
811
0
                    Any( AccessibleStateType::FOCUSED ),
812
0
                    Any()
813
0
                );
814
0
            }
815
0
        }
816
0
        break;
817
818
0
        case VclEventId::ControlLoseFocus:
819
0
        {
820
            // TODO: this doesn't belong here. It belongs into the TableControl, so A11Y also
821
            // works when the control is used outside the UNO context
822
0
            if (pTable->GetCurrentRow() !=  ROW_INVALID && pTable->GetCurrentColumn() != COL_INVALID)
823
0
            {
824
0
                pTable->commitCellEvent(
825
0
                    AccessibleEventId::STATE_CHANGED,
826
0
                    Any(),
827
0
                    Any( AccessibleStateType::FOCUSED )
828
0
                );
829
0
            }
830
0
            else
831
0
            {
832
0
                pTable->commitTableEvent(
833
0
                    AccessibleEventId::STATE_CHANGED,
834
0
                    Any(),
835
0
                    Any( AccessibleStateType::FOCUSED )
836
0
                );
837
0
            }
838
0
        }
839
0
        break;
840
841
0
        default: break;
842
0
    }
843
844
0
    if ( !handled )
845
0
        VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
846
0
}
847
848
849
void SVTXGridControl::setEnable( sal_Bool bEnable )
850
0
{
851
0
    SolarMutexGuard aGuard;
852
853
0
    m_xTableModel->setEnabled( bEnable );
854
0
    VclPtr<vcl::Window> pWindow = GetWindow();
855
0
    if ( pWindow )
856
0
    {
857
0
        pWindow->Enable( bEnable );
858
0
        pWindow->EnableInput( bEnable );
859
0
        pWindow->Invalidate();
860
0
    }
861
0
}
862
863
864
void SVTXGridControl::ImplCallItemListeners()
865
0
{
866
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
867
0
    ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ImplCallItemListeners: no control (anymore)!" );
868
869
0
    if ( m_aSelectionListeners.getLength() )
870
0
    {
871
0
        GridSelectionEvent aEvent;
872
0
        aEvent.Source = getXWeak();
873
874
0
        sal_Int32 const nSelectedRowCount( pTable->GetSelectedRowCount() );
875
0
        aEvent.SelectedRowIndexes.realloc( nSelectedRowCount );
876
0
        auto pSelectedRowIndexes = aEvent.SelectedRowIndexes.getArray();
877
0
        for ( sal_Int32 i=0; i<nSelectedRowCount; ++i )
878
0
            pSelectedRowIndexes[i] = pTable->GetSelectedRowIndex( i );
879
0
        m_aSelectionListeners.selectionChanged( aEvent );
880
0
    }
881
0
}
882
883
884
void SVTXGridControl::impl_updateColumnsFromModel_nothrow()
885
0
{
886
0
    Reference< XGridColumnModel > const xColumnModel( m_xTableModel->getColumnModel() );
887
0
    ENSURE_OR_RETURN_VOID( xColumnModel.is(), "no model!" );
888
0
    VclPtr<TableControl> pTable = GetAsDynamic<TableControl>();
889
0
    ENSURE_OR_RETURN_VOID( pTable, "no table!" );
890
891
0
    try
892
0
    {
893
0
        const Sequence< Reference< XGridColumn > > columns = xColumnModel->getColumns();
894
0
        for ( auto const & colRef : columns )
895
0
        {
896
0
            if ( !colRef.is() )
897
0
            {
898
0
                SAL_WARN( "svtools.uno", "illegal column!" );
899
0
                continue;
900
0
            }
901
902
0
            m_xTableModel->appendColumn( colRef );
903
0
        }
904
0
    }
905
0
    catch( const Exception& )
906
0
    {
907
0
        DBG_UNHANDLED_EXCEPTION("svtools.uno");
908
0
    }
909
0
}
910
911
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */