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/grid/gridcontrol.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 "gridcontrol.hxx"
22
#include "grideventforwarder.hxx"
23
24
#include <com/sun/star/uno/XComponentContext.hpp>
25
#include <com/sun/star/view/SelectionType.hpp>
26
#include <com/sun/star/awt/grid/XGridControl.hpp>
27
#include <com/sun/star/awt/grid/XGridDataModel.hpp>
28
#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
29
#include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
30
#include <com/sun/star/awt/grid/DefaultGridDataModel.hpp>
31
#include <com/sun/star/awt/grid/SortableGridDataModel.hpp>
32
#include <com/sun/star/awt/grid/DefaultGridColumnModel.hpp>
33
#include <helper/property.hxx>
34
#include <comphelper/diagnose_ex.hxx>
35
#include <rtl/ref.hxx>
36
#include <toolkit/controls/unocontrolbase.hxx>
37
#include <toolkit/controls/unocontrolmodel.hxx>
38
#include <toolkit/helper/listenermultiplexer.hxx>
39
40
#include <memory>
41
42
#include <helper/unopropertyarrayhelper.hxx>
43
44
using namespace ::com::sun::star;
45
using namespace ::com::sun::star::uno;
46
using namespace ::com::sun::star::awt;
47
using namespace ::com::sun::star::awt::grid;
48
using namespace ::com::sun::star::lang;
49
using namespace ::com::sun::star::beans;
50
using namespace ::com::sun::star::container;
51
using namespace ::com::sun::star::view;
52
using namespace ::com::sun::star::util;
53
54
namespace toolkit {
55
56
namespace
57
{
58
    Reference< XGridDataModel > lcl_getDefaultDataModel_throw( const Reference<XComponentContext> & i_context )
59
0
    {
60
0
        Reference< XMutableGridDataModel > const xDelegatorModel( DefaultGridDataModel::create( i_context ), UNO_SET_THROW );
61
0
        Reference< XGridDataModel > const xDataModel( SortableGridDataModel::create( i_context, xDelegatorModel ), UNO_QUERY_THROW );
62
0
        return xDataModel;
63
0
    }
64
65
    Reference< XGridColumnModel > lcl_getDefaultColumnModel_throw( const Reference<XComponentContext> & i_context )
66
0
    {
67
0
        Reference< XGridColumnModel > const xColumnModel = DefaultGridColumnModel::create( i_context );
68
0
        return xColumnModel;
69
0
    }
70
}
71
72
73
UnoGridModel::UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext )
74
0
        :UnoControlModel( rxContext )
75
0
{
76
0
    ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
77
0
    ImplRegisterProperty( BASEPROPERTY_BORDER );
78
0
    ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
79
0
    ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
80
0
    ImplRegisterProperty( BASEPROPERTY_ENABLED );
81
0
    ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
82
0
    ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
83
0
    ImplRegisterProperty( BASEPROPERTY_HELPURL );
84
0
    ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
85
0
    ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); // resizable
86
0
    ImplRegisterProperty( BASEPROPERTY_HSCROLL );
87
0
    ImplRegisterProperty( BASEPROPERTY_VSCROLL );
88
0
    ImplRegisterProperty( BASEPROPERTY_TABSTOP );
89
0
    ImplRegisterProperty( BASEPROPERTY_GRID_SHOWROWHEADER );
90
0
    ImplRegisterProperty( BASEPROPERTY_ROW_HEADER_WIDTH );
91
0
    ImplRegisterProperty( BASEPROPERTY_GRID_SHOWCOLUMNHEADER );
92
0
    ImplRegisterProperty( BASEPROPERTY_COLUMN_HEADER_HEIGHT );
93
0
    ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
94
0
    ImplRegisterProperty( BASEPROPERTY_GRID_DATAMODEL, Any( lcl_getDefaultDataModel_throw( m_xContext ) ) );
95
0
    ImplRegisterProperty( BASEPROPERTY_GRID_COLUMNMODEL, Any( lcl_getDefaultColumnModel_throw( m_xContext ) ) );
96
0
    ImplRegisterProperty( BASEPROPERTY_GRID_SELECTIONMODE );
97
0
    ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
98
0
    ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
99
0
    ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
100
0
    ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
101
0
    ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
102
0
    ImplRegisterProperty( BASEPROPERTY_USE_GRID_LINES );
103
0
    ImplRegisterProperty( BASEPROPERTY_GRID_LINE_COLOR );
104
0
    ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_BACKGROUND );
105
0
    ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_TEXT_COLOR );
106
0
    ImplRegisterProperty( BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS );
107
0
    ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR );
108
0
    ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR );
109
0
    ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR );
110
0
    ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR );
111
0
    ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
112
0
}
Unexecuted instantiation: toolkit::UnoGridModel::UnoGridModel(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&)
Unexecuted instantiation: toolkit::UnoGridModel::UnoGridModel(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&)
113
114
115
UnoGridModel::UnoGridModel( const UnoGridModel& rModel )
116
0
    :UnoControlModel( rModel )
117
0
{
118
0
    osl_atomic_increment( &m_refCount );
119
0
    {
120
0
        Reference< XGridDataModel > xDataModel;
121
        // clone the data model
122
0
        const Reference< XFastPropertySet > xCloneSource( &const_cast< UnoGridModel& >( rModel ) );
123
0
        try
124
0
        {
125
0
            const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ), UNO_QUERY_THROW );
126
0
            xDataModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
127
0
        }
128
0
        catch( const Exception& )
129
0
        {
130
0
            DBG_UNHANDLED_EXCEPTION("toolkit.controls");
131
0
        }
132
0
        if ( !xDataModel.is() )
133
0
            xDataModel = lcl_getDefaultDataModel_throw( m_xContext );
134
0
        std::unique_lock aGuard(m_aMutex);
135
0
        UnoControlModel::setFastPropertyValue_NoBroadcast( aGuard, BASEPROPERTY_GRID_DATAMODEL, Any( xDataModel ) );
136
            // do *not* use setFastPropertyValue here: The UnoControlModel ctor made a simple copy of all property values,
137
            // so before this call here, we share our data model with the owner of the clone source. setFastPropertyValue,
138
            // then, disposes the old data model - which means the data model which in fact belongs to the clone source.
139
            // so, call the UnoControlModel's impl-method for setting the value.
140
141
        // clone the column model
142
0
        Reference< XGridColumnModel > xColumnModel;
143
0
        try
144
0
        {
145
0
            const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ), UNO_QUERY_THROW );
146
0
            xColumnModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
147
0
        }
148
0
        catch( const Exception& )
149
0
        {
150
0
            DBG_UNHANDLED_EXCEPTION("toolkit.controls");
151
0
        }
152
0
        if ( !xColumnModel.is() )
153
0
            xColumnModel = lcl_getDefaultColumnModel_throw( m_xContext );
154
0
        UnoControlModel::setFastPropertyValue_NoBroadcast( aGuard, BASEPROPERTY_GRID_COLUMNMODEL, Any( xColumnModel ) );
155
            // same comment as above: do not use our own setPropertyValue here.
156
0
    }
157
0
    osl_atomic_decrement( &m_refCount );
158
0
}
Unexecuted instantiation: toolkit::UnoGridModel::UnoGridModel(toolkit::UnoGridModel const&)
Unexecuted instantiation: toolkit::UnoGridModel::UnoGridModel(toolkit::UnoGridModel const&)
159
160
161
rtl::Reference<UnoControlModel> UnoGridModel::Clone() const
162
0
{
163
0
    return new UnoGridModel( *this );
164
0
}
165
166
167
namespace
168
{
169
    void lcl_dispose_nothrow( const Any& i_component )
170
0
    {
171
0
        try
172
0
        {
173
0
            const Reference< XComponent > xComponent( i_component, UNO_QUERY );
174
0
            if (xComponent)
175
0
                xComponent->dispose();
176
0
        }
177
0
        catch( const Exception& )
178
0
        {
179
0
            DBG_UNHANDLED_EXCEPTION("toolkit.controls");
180
0
        }
181
0
    }
182
}
183
184
185
void SAL_CALL UnoGridModel::dispose(  )
186
0
{
187
0
    lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ) );
188
0
    lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ) );
189
190
0
    UnoControlModel::dispose();
191
0
}
192
193
194
void UnoGridModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const Any& rValue )
195
0
{
196
0
    Any aOldSubModel;
197
0
    if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
198
0
    {
199
0
        getFastPropertyValue( rGuard, aOldSubModel, nHandle );
200
0
        if ( aOldSubModel == rValue )
201
0
        {
202
0
            OSL_ENSURE( false, "UnoGridModel::setFastPropertyValue_NoBroadcast: setting the same value, again!" );
203
                // shouldn't this have been caught by convertFastPropertyValue?
204
0
            aOldSubModel.clear();
205
0
        }
206
0
    }
207
208
0
    UnoControlModel::setFastPropertyValue_NoBroadcast( rGuard, nHandle, rValue );
209
210
0
    if ( aOldSubModel.hasValue() )
211
0
        lcl_dispose_nothrow( aOldSubModel );
212
0
}
213
214
215
OUString UnoGridModel::getServiceName()
216
0
{
217
0
    return u"com.sun.star.awt.grid.UnoControlGridModel"_ustr;
218
0
}
219
220
221
Any UnoGridModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
222
0
{
223
0
    switch( nPropId )
224
0
    {
225
0
        case BASEPROPERTY_DEFAULTCONTROL:
226
0
            return uno::Any( u"com.sun.star.awt.grid.UnoControlGrid"_ustr );
227
0
        case BASEPROPERTY_GRID_SELECTIONMODE:
228
0
            return uno::Any( SelectionType(1) );
229
0
        case BASEPROPERTY_GRID_SHOWROWHEADER:
230
0
        case BASEPROPERTY_USE_GRID_LINES:
231
0
            return uno::Any( false );
232
0
        case BASEPROPERTY_ROW_HEADER_WIDTH:
233
0
            return uno::Any( sal_Int32( 10 ) );
234
0
        case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
235
0
            return uno::Any( true );
236
0
        case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
237
0
        case BASEPROPERTY_ROW_HEIGHT:
238
0
        case BASEPROPERTY_GRID_HEADER_BACKGROUND:
239
0
        case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
240
0
        case BASEPROPERTY_GRID_LINE_COLOR:
241
0
        case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
242
0
        case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
243
0
        case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
244
0
        case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
245
0
        case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
246
0
            return Any();
247
0
        default:
248
0
            return UnoControlModel::ImplGetDefaultValue( nPropId );
249
0
    }
250
251
0
}
252
253
254
::cppu::IPropertyArrayHelper& UnoGridModel::getInfoHelper()
255
0
{
256
0
    static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
257
0
    return aHelper;
258
0
}
259
260
261
// XMultiPropertySet
262
Reference< XPropertySetInfo > UnoGridModel::getPropertySetInfo(  )
263
0
{
264
0
    static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
265
0
    return xInfo;
266
0
}
267
268
269
//= UnoGridControl
270
271
UnoGridControl::UnoGridControl()
272
0
    :m_aSelectionListeners( *this )
273
0
    ,m_pEventForwarder( new toolkit::GridEventForwarder( *this ) )
274
0
{
275
0
}
276
277
278
UnoGridControl::~UnoGridControl()
279
0
{
280
0
}
281
282
283
OUString UnoGridControl::GetComponentServiceName() const
284
0
{
285
0
    return u"Grid"_ustr;
286
0
}
287
288
289
void SAL_CALL UnoGridControl::dispose(  )
290
0
{
291
0
    lang::EventObject aEvt;
292
0
    aEvt.Source = getXWeak();
293
0
    m_aSelectionListeners.disposeAndClear( aEvt );
294
0
    UnoControl::dispose();
295
0
}
296
297
298
void SAL_CALL UnoGridControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer )
299
0
{
300
0
    UnoControlBase::createPeer( rxToolkit, rParentPeer );
301
302
0
    const Reference< XGridRowSelection > xGrid( getPeer(), UNO_QUERY_THROW );
303
0
    xGrid->addSelectionListener( &m_aSelectionListeners );
304
0
}
305
306
307
namespace
308
{
309
    void lcl_setEventForwarding( const Reference< XControlModel >& i_gridControlModel, const std::unique_ptr< toolkit::GridEventForwarder >& i_listener,
310
        bool const i_add )
311
0
    {
312
0
        const Reference< XPropertySet > xModelProps( i_gridControlModel, UNO_QUERY );
313
0
        if ( !xModelProps.is() )
314
0
            return;
315
316
0
        try
317
0
        {
318
0
            Reference< XContainer > const xColModel(
319
0
                xModelProps->getPropertyValue(u"ColumnModel"_ustr),
320
0
                UNO_QUERY_THROW );
321
0
            if ( i_add )
322
0
                xColModel->addContainerListener( i_listener.get() );
323
0
            else
324
0
                xColModel->removeContainerListener( i_listener.get() );
325
326
0
            Reference< XGridDataModel > const xDataModel(
327
0
                xModelProps->getPropertyValue(u"GridDataModel"_ustr),
328
0
                UNO_QUERY_THROW
329
0
            );
330
0
            Reference< XMutableGridDataModel > const xMutableDataModel( xDataModel, UNO_QUERY );
331
0
            if ( xMutableDataModel.is() )
332
0
            {
333
0
                if ( i_add )
334
0
                    xMutableDataModel->addGridDataListener( i_listener.get() );
335
0
                else
336
0
                    xMutableDataModel->removeGridDataListener( i_listener.get() );
337
0
            }
338
0
        }
339
0
        catch( const Exception& )
340
0
        {
341
0
            DBG_UNHANDLED_EXCEPTION("toolkit.controls");
342
0
        }
343
0
    }
344
}
345
346
347
sal_Bool SAL_CALL UnoGridControl::setModel( const Reference< XControlModel >& i_model )
348
0
{
349
0
    lcl_setEventForwarding( getModel(), m_pEventForwarder, false );
350
0
    if ( !UnoGridControl_Base::setModel( i_model ) )
351
0
        return false;
352
0
    lcl_setEventForwarding( getModel(), m_pEventForwarder, true );
353
0
    return true;
354
0
}
355
356
357
::sal_Int32 UnoGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
358
0
{
359
0
    Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
360
0
    return xGrid->getRowAtPoint( x, y );
361
0
}
362
363
364
::sal_Int32 UnoGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
365
0
{
366
0
    Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
367
0
    return xGrid->getColumnAtPoint( x, y );
368
0
}
369
370
371
::sal_Int32 SAL_CALL UnoGridControl::getCurrentColumn(  )
372
0
{
373
0
    Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
374
0
    return xGrid->getCurrentColumn();
375
0
}
376
377
378
::sal_Int32 SAL_CALL UnoGridControl::getCurrentRow(  )
379
0
{
380
0
    Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
381
0
    return xGrid->getCurrentRow();
382
0
}
383
384
385
void SAL_CALL UnoGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
386
0
{
387
0
    Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
388
0
    xGrid->goToCell( i_columnIndex, i_rowIndex );
389
0
}
390
391
392
void SAL_CALL UnoGridControl::selectRow( ::sal_Int32 i_rowIndex )
393
0
{
394
0
    Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectRow( i_rowIndex );
395
0
}
396
397
398
void SAL_CALL UnoGridControl::selectAllRows()
399
0
{
400
0
    Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectAllRows();
401
0
}
402
403
404
void SAL_CALL UnoGridControl::deselectRow( ::sal_Int32 i_rowIndex )
405
0
{
406
0
    Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectRow( i_rowIndex );
407
0
}
408
409
410
void SAL_CALL UnoGridControl::deselectAllRows()
411
0
{
412
0
    Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectAllRows();
413
0
}
414
415
416
css::uno::Sequence< ::sal_Int32 > SAL_CALL UnoGridControl::getSelectedRows()
417
0
{
418
0
    return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->getSelectedRows();
419
0
}
420
421
422
sal_Bool SAL_CALL UnoGridControl::hasSelectedRows()
423
0
{
424
0
    return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->hasSelectedRows();
425
0
}
426
427
428
sal_Bool SAL_CALL UnoGridControl::isRowSelected(::sal_Int32 index)
429
0
{
430
0
    return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->isRowSelected( index );
431
0
}
432
433
434
void SAL_CALL UnoGridControl::addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
435
0
{
436
0
    m_aSelectionListeners.addInterface( listener );
437
0
}
438
439
440
void SAL_CALL UnoGridControl::removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
441
0
{
442
0
    m_aSelectionListeners.removeInterface( listener );
443
0
}
444
445
}
446
447
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
448
stardiv_Toolkit_GridControl_get_implementation(
449
    css::uno::XComponentContext *,
450
    css::uno::Sequence<css::uno::Any> const &)
451
0
{
452
0
    return cppu::acquire(new toolkit::UnoGridControl());
453
0
}
454
455
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
456
stardiv_Toolkit_GridControlModel_get_implementation(
457
    css::uno::XComponentContext *context,
458
    css::uno::Sequence<css::uno::Any> const &)
459
0
{
460
0
    return cppu::acquire(new toolkit::UnoGridModel(context));
461
0
}
462
463
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */