Coverage Report

Created: 2025-07-07 10:01

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