Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/controls/unocontrolcontainer.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 <com/sun/star/awt/XVclContainerPeer.hpp>
21
#include <com/sun/star/beans/XPropertySet.hpp>
22
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
23
#include <com/sun/star/container/NoSuchElementException.hpp>
24
#include <com/sun/star/uno/XComponentContext.hpp>
25
26
#include <cppuhelper/implbase.hxx>
27
28
#include <toolkit/controls/unocontrolcontainer.hxx>
29
#include <comphelper/sequence.hxx>
30
31
#include <tools/debug.hxx>
32
33
#include <limits>
34
#include <map>
35
#include <memory>
36
#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
37
#include <utility>
38
39
using namespace ::com::sun::star;
40
41
42
43
namespace {
44
45
struct UnoControlHolder
46
{
47
    uno::Reference< awt::XControl > mxControl;
48
    OUString                        msName;
49
50
public:
51
    UnoControlHolder( OUString aName, uno::Reference< awt::XControl > xControl )
52
0
    :   mxControl(std::move( xControl )),
53
0
        msName(std::move( aName ))
54
0
    {
55
0
    }
56
57
0
    const OUString&                   getName() const { return msName; }
58
0
    const uno::Reference< awt::XControl >&   getControl() const { return mxControl; }
59
};
60
61
}
62
63
class UnoControlHolderList
64
{
65
public:
66
    typedef sal_Int32                                       ControlIdentifier;
67
private:
68
    typedef std::shared_ptr< UnoControlHolder >         ControlInfo;
69
    typedef ::std::map< ControlIdentifier, ControlInfo >    ControlMap;
70
71
private:
72
    ControlMap  maControls;
73
74
public:
75
    UnoControlHolderList();
76
77
    /** adds a control with the given name to the list
78
        @param _rxControl
79
            the control to add. Must not be <NULL/>
80
        @param _pBName
81
            the name of the control, or <NULL/> if an automatic name should be generated
82
        @return
83
            the identifier of the newly added control
84
    */
85
    ControlIdentifier   addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName );
86
87
    /** determines whether or not the list is empty
88
    */
89
0
    bool         empty() const { return maControls.empty(); }
90
91
    /** retrieves all controls currently in the list
92
    */
93
    void  getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const;
94
95
    /** retrieves all identifiers of all controls currently in the list
96
    */
97
    void  getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const;
98
99
    /** returns the first control which is registered under the given name
100
    */
101
    uno::Reference< awt::XControl >
102
            getControlForName( const OUString& _rName ) const;
103
104
    /** returns the identifier which a control is registered for, or -1 if the control
105
            isn't registered
106
    */
107
    ControlIdentifier
108
            getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl );
109
110
    /** retrieves the control for a given id
111
        @param _nIdentifier
112
            the identifier for the control
113
        @param _out_rxControl
114
            takes the XControl upon successful return
115
        @return
116
            <TRUE/> if and only if a control with the given id is part of the list
117
    */
118
    bool    getControlForIdentifier( ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const;
119
120
    /** removes a control from the list, given by id
121
        @param _nId
122
            The identifier of the control to remove.
123
    */
124
    void    removeControlById( ControlIdentifier _nId );
125
126
    /** replaces a control from the list with another one
127
        @param _nId
128
            The identifier of the control to replace
129
        @param _rxNewControl
130
            the new control to put into the list
131
    */
132
    void    replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl );
133
134
private:
135
    /** adds a control
136
    @param _rxControl
137
        the control to add to the container
138
    @param _pName
139
        pointer to the name of the control. Might be <NULL/>, in this case, a name is generated.
140
    @return
141
        the identifier of the newly inserted control
142
    */
143
    ControlIdentifier impl_addControl(
144
        const uno::Reference< awt::XControl >& _rxControl,
145
        const OUString*  _pName
146
    );
147
148
    /** finds a free identifier
149
        @throw uno::RuntimeException
150
            if no free identifier can be found
151
    */
152
    ControlIdentifier impl_getFreeIdentifier_throw();
153
154
    /** finds a free name
155
        @throw uno::RuntimeException
156
            if no free name can be found
157
    */
158
    OUString impl_getFreeName_throw();
159
};
160
161
162
UnoControlHolderList::UnoControlHolderList()
163
124
{
164
124
}
165
166
167
UnoControlHolderList::ControlIdentifier UnoControlHolderList::addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
168
0
{
169
0
    return impl_addControl( _rxControl, _pName );
170
0
}
171
172
173
void UnoControlHolderList::getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const
174
62
{
175
62
    _out_rControls.realloc( maControls.size() );
176
62
    uno::Reference< awt::XControl >* pControls = _out_rControls.getArray();
177
62
    for (const auto& rEntry : maControls)
178
0
    {
179
0
        *pControls = rEntry.second->getControl();
180
0
        ++pControls;
181
0
    }
182
62
}
183
184
185
void UnoControlHolderList::getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const
186
0
{
187
0
    _out_rIdentifiers.realloc( maControls.size() );
188
0
    sal_Int32* pIdentifiers = _out_rIdentifiers.getArray();
189
0
    for (const auto& rEntry : maControls)
190
0
    {
191
0
        *pIdentifiers = rEntry.first;
192
0
        ++pIdentifiers;
193
0
    }
194
0
}
195
196
197
uno::Reference< awt::XControl > UnoControlHolderList::getControlForName( const OUString& _rName ) const
198
0
{
199
0
    auto loop = std::find_if(maControls.begin(), maControls.end(),
200
0
        [&_rName](const ControlMap::value_type& rEntry) { return rEntry.second->getName() == _rName; });
201
0
    if (loop != maControls.end())
202
0
        return loop->second->getControl();
203
0
    return uno::Reference< awt::XControl >();
204
0
}
205
206
207
UnoControlHolderList::ControlIdentifier UnoControlHolderList::getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl )
208
0
{
209
0
    auto loop = std::find_if(maControls.begin(), maControls.end(),
210
0
        [&_rxControl](const ControlMap::value_type& rEntry) { return rEntry.second->getControl().get() == _rxControl.get(); });
211
0
    if (loop != maControls.end())
212
0
        return loop->first;
213
0
    return -1;
214
0
}
215
216
217
bool UnoControlHolderList::getControlForIdentifier( UnoControlHolderList::ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const
218
0
{
219
0
    ControlMap::const_iterator pos = maControls.find( _nIdentifier );
220
0
    if ( pos == maControls.end() )
221
0
        return false;
222
0
    _out_rxControl = pos->second->getControl();
223
0
    return true;
224
0
}
225
226
227
void UnoControlHolderList::removeControlById( UnoControlHolderList::ControlIdentifier _nId )
228
0
{
229
0
    ControlMap::iterator pos = maControls.find( _nId );
230
0
    DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::removeControlById: invalid id!" );
231
0
    if ( pos == maControls.end() )
232
0
        return;
233
234
0
    maControls.erase( pos );
235
0
}
236
237
238
void UnoControlHolderList::replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl )
239
0
{
240
0
    DBG_ASSERT( _rxNewControl.is(), "UnoControlHolderList::replaceControlById: invalid new control!" );
241
242
0
    ControlMap::iterator pos = maControls.find( _nId );
243
0
    DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::replaceControlById: invalid id!" );
244
0
    if ( pos == maControls.end() )
245
0
        return;
246
247
0
    pos->second = std::make_shared<UnoControlHolder>( pos->second->getName(), _rxNewControl );
248
0
}
249
250
251
UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
252
0
{
253
0
    DBG_ASSERT( _rxControl.is(), "UnoControlHolderList::impl_addControl: invalid control!" );
254
255
0
    OUString sName = _pName ? *_pName : impl_getFreeName_throw();
256
0
    sal_Int32 nId = impl_getFreeIdentifier_throw();
257
258
0
    maControls[ nId ] = std::make_shared<UnoControlHolder>( sName, _rxControl );
259
0
    return nId;
260
0
}
261
262
263
UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_getFreeIdentifier_throw()
264
0
{
265
0
    for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
266
0
    {
267
0
        ControlMap::const_iterator existent = maControls.find( candidateId );
268
0
        if ( existent == maControls.end() )
269
0
            return candidateId;
270
0
    }
271
0
    throw uno::RuntimeException(u"out of identifiers"_ustr );
272
0
}
273
274
275
OUString UnoControlHolderList::impl_getFreeName_throw()
276
0
{
277
0
    for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
278
0
    {
279
0
        OUString candidateName( "control_" + OUString::number( candidateId ) );
280
0
        if ( std::none_of(maControls.begin(), maControls.end(),
281
0
                [&candidateName](const ControlMap::value_type& rEntry) { return rEntry.second->getName() == candidateName; }) )
282
0
            return candidateName;
283
0
    }
284
0
    throw uno::RuntimeException(u"out of identifiers"_ustr );
285
0
}
286
287
//  Function to set the controls' visibility according
288
//  to the dialog's "Step" property
289
290
static void implUpdateVisibility
291
(
292
    sal_Int32 nDialogStep,
293
    const uno::Reference< awt::XControlContainer >& xControlContainer
294
)
295
0
{
296
0
    const uno::Sequence< uno::Reference< awt::XControl > >
297
0
        aCtrls = xControlContainer->getControls();
298
0
    bool bCompleteVisible = (nDialogStep == 0);
299
0
    for( const uno::Reference< awt::XControl >& xControl : aCtrls )
300
0
    {
301
0
        bool bVisible = bCompleteVisible;
302
0
        if( !bVisible )
303
0
        {
304
0
            uno::Reference< awt::XControlModel > xModel( xControl->getModel() );
305
0
            uno::Reference< beans::XPropertySet > xPSet
306
0
                ( xModel, uno::UNO_QUERY );
307
0
            uno::Reference< beans::XPropertySetInfo >
308
0
                xInfo = xPSet->getPropertySetInfo();
309
0
            OUString aPropName( u"Step"_ustr );
310
0
            sal_Int32 nControlStep = 0;
311
0
            if ( xInfo->hasPropertyByName( aPropName ) )
312
0
            {
313
0
                uno::Any aVal = xPSet->getPropertyValue( aPropName );
314
0
                aVal >>= nControlStep;
315
0
            }
316
0
            bVisible = (nControlStep == 0) || (nControlStep == nDialogStep);
317
0
        }
318
319
0
        uno::Reference< awt::XWindow> xWindow
320
0
            ( xControl, uno::UNO_QUERY );
321
0
        if( xWindow.is() )
322
0
            xWindow->setVisible( bVisible );
323
0
    }
324
0
}
325
326
327
328
typedef ::cppu::WeakImplHelper< beans::XPropertyChangeListener > PropertyChangeListenerHelper;
329
330
namespace {
331
332
class DialogStepChangedListener: public PropertyChangeListenerHelper
333
{
334
private:
335
    uno::Reference< awt::XControlContainer > mxControlContainer;
336
337
public:
338
    explicit DialogStepChangedListener( uno::Reference< awt::XControlContainer > xControlContainer )
339
0
        : mxControlContainer(std::move( xControlContainer )) {}
340
341
    // XEventListener
342
    virtual void SAL_CALL disposing( const  lang::EventObject& Source ) override;
343
344
    // XPropertyChangeListener
345
    virtual void SAL_CALL propertyChange( const  beans::PropertyChangeEvent& evt ) override;
346
347
};
348
349
}
350
351
void SAL_CALL DialogStepChangedListener::disposing( const  lang::EventObject& /*_rSource*/)
352
0
{
353
0
    mxControlContainer.clear();
354
0
}
355
356
void SAL_CALL DialogStepChangedListener::propertyChange( const  beans::PropertyChangeEvent& evt )
357
0
{
358
    // evt.PropertyName HAS to be "Step" because we only use the listener for that
359
0
    sal_Int32 nDialogStep = 0;
360
0
    evt.NewValue >>= nDialogStep;
361
0
    implUpdateVisibility( nDialogStep, mxControlContainer );
362
0
}
363
364
365
366
UnoControlContainer::UnoControlContainer()
367
36
    :maCListeners( *this )
368
36
{
369
36
    mpControls.reset(new UnoControlHolderList);
370
36
}
371
372
UnoControlContainer::UnoControlContainer(const uno::Reference< awt::XVclWindowPeer >& xP )
373
26
    :maCListeners( *this )
374
26
{
375
26
    setPeer( xP );
376
26
    mbDisposePeer = false;
377
26
    mpControls.reset(new UnoControlHolderList);
378
26
}
379
380
UnoControlContainer::~UnoControlContainer()
381
62
{
382
62
}
383
384
void UnoControlContainer::ImplActivateTabControllers()
385
0
{
386
0
    for ( auto& rTabController : asNonConstRange(maTabControllers) )
387
0
    {
388
0
        rTabController->setContainer( this );
389
0
        rTabController->activateTabOrder();
390
0
    }
391
0
}
392
393
// lang::XComponent
394
void UnoControlContainer::dispose(  )
395
62
{
396
62
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
397
398
62
    lang::EventObject aDisposeEvent;
399
62
    aDisposeEvent.Source = static_cast< uno::XAggregation* >( this );
400
401
    // Notify listeners about disposal of this Container (This is much faster if they
402
    // listen on the controls and the container).
403
62
    maDisposeListeners.disposeAndClear( aDisposeEvent );
404
62
    maCListeners.disposeAndClear( aDisposeEvent );
405
406
407
62
    const uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
408
409
62
    for( uno::Reference< awt::XControl > const & control : aCtrls )
410
0
    {
411
0
        removingControl( control );
412
        // Delete control
413
0
        control->dispose();
414
0
    }
415
416
417
    // Delete all structures
418
62
    mpControls.reset(new UnoControlHolderList);
419
420
62
    UnoControlBase::dispose();
421
62
}
422
423
// lang::XEventListener
424
void UnoControlContainer::disposing( const lang::EventObject& _rEvt )
425
0
{
426
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
427
428
0
    uno::Reference< awt::XControl >  xControl( _rEvt.Source, uno::UNO_QUERY );
429
0
    if ( xControl.is() )
430
0
        removeControl( xControl );
431
432
0
    UnoControlBase::disposing( _rEvt );
433
0
}
434
435
// container::XContainer
436
void UnoControlContainer::addContainerListener( const uno::Reference< container::XContainerListener >& rxListener )
437
62
{
438
62
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
439
440
62
    maCListeners.addInterface( rxListener );
441
62
}
442
443
void UnoControlContainer::removeContainerListener( const uno::Reference< container::XContainerListener >& rxListener )
444
62
{
445
62
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
446
447
62
    maCListeners.removeInterface( rxListener );
448
62
}
449
450
451
::sal_Int32 SAL_CALL UnoControlContainer::insert( const uno::Any& _rElement )
452
0
{
453
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
454
455
0
    uno::Reference< awt::XControl > xControl;
456
0
    if ( !( _rElement >>= xControl ) || !xControl.is() )
457
0
        throw lang::IllegalArgumentException(
458
0
            u"Elements must support the XControl interface."_ustr,
459
0
            *this,
460
0
            1
461
0
        );
462
463
0
    return impl_addControl( xControl );
464
0
}
465
466
void SAL_CALL UnoControlContainer::removeByIdentifier( ::sal_Int32 _nIdentifier )
467
0
{
468
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
469
470
0
    uno::Reference< awt::XControl > xControl;
471
0
    if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
472
0
        throw container::NoSuchElementException(
473
0
            u"There is no element with the given identifier."_ustr,
474
0
            *this
475
0
        );
476
477
0
    impl_removeControl( _nIdentifier, xControl );
478
0
}
479
480
void SAL_CALL UnoControlContainer::replaceByIdentifer( ::sal_Int32 _nIdentifier, const uno::Any& _rElement )
481
0
{
482
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
483
484
0
    uno::Reference< awt::XControl > xExistentControl;
485
0
    if ( !mpControls->getControlForIdentifier( _nIdentifier, xExistentControl ) )
486
0
        throw container::NoSuchElementException(
487
0
            u"There is no element with the given identifier."_ustr,
488
0
            *this
489
0
        );
490
491
0
    uno::Reference< awt::XControl > xNewControl;
492
0
    if ( !( _rElement >>= xNewControl ) )
493
0
        throw lang::IllegalArgumentException(
494
0
            u"Elements must support the XControl interface."_ustr,
495
0
            *this,
496
0
            1
497
0
        );
498
499
0
    removingControl( xExistentControl );
500
501
0
    mpControls->replaceControlById( _nIdentifier, xNewControl );
502
503
0
    addingControl( xNewControl );
504
505
0
    impl_createControlPeerIfNecessary( xNewControl );
506
507
0
    if ( maCListeners.getLength() )
508
0
    {
509
0
        container::ContainerEvent aEvent;
510
0
        aEvent.Source = *this;
511
0
        aEvent.Accessor <<= _nIdentifier;
512
0
        aEvent.Element <<= xNewControl;
513
0
        aEvent.ReplacedElement <<= xExistentControl;
514
0
        maCListeners.elementReplaced( aEvent );
515
0
    }
516
0
}
517
518
uno::Any SAL_CALL UnoControlContainer::getByIdentifier( ::sal_Int32 _nIdentifier )
519
0
{
520
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
521
522
0
    uno::Reference< awt::XControl > xControl;
523
0
    if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
524
0
        throw container::NoSuchElementException();
525
0
    return uno::Any( xControl );
526
0
}
527
528
uno::Sequence< ::sal_Int32 > SAL_CALL UnoControlContainer::getIdentifiers(  )
529
0
{
530
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
531
532
0
    uno::Sequence< ::sal_Int32 > aIdentifiers;
533
0
    mpControls->getIdentifiers( aIdentifiers );
534
0
    return aIdentifiers;
535
0
}
536
537
// container::XElementAccess
538
uno::Type SAL_CALL UnoControlContainer::getElementType(  )
539
0
{
540
0
    return cppu::UnoType<awt::XControlModel>::get();
541
0
}
542
543
sal_Bool SAL_CALL UnoControlContainer::hasElements(  )
544
0
{
545
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
546
0
    return !mpControls->empty();
547
0
}
548
549
// awt::XControlContainer
550
void UnoControlContainer::setStatusText( const OUString& rStatusText )
551
0
{
552
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
553
554
    // Descend the parent hierarchy
555
0
    uno::Reference< awt::XControlContainer >  xContainer( mxContext, uno::UNO_QUERY );
556
0
    if( xContainer.is() )
557
0
        xContainer->setStatusText( rStatusText );
558
0
}
559
560
uno::Sequence< uno::Reference< awt::XControl > > UnoControlContainer::getControls(  )
561
62
{
562
62
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
563
62
    uno::Sequence< uno::Reference< awt::XControl > > aControls;
564
62
    mpControls->getControls( aControls );
565
62
    return aControls;
566
62
}
567
568
uno::Reference< awt::XControl > UnoControlContainer::getControl( const OUString& rName )
569
0
{
570
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
571
0
    return mpControls->getControlForName( rName );
572
0
}
573
574
void UnoControlContainer::addingControl( const uno::Reference< awt::XControl >& _rxControl )
575
0
{
576
0
    if ( _rxControl.is() )
577
0
    {
578
0
        uno::Reference< uno::XInterface > xThis;
579
0
        OWeakAggObject::queryInterface( cppu::UnoType<uno::XInterface>::get() ) >>= xThis;
580
581
0
        _rxControl->setContext( xThis );
582
0
        _rxControl->addEventListener( this );
583
0
    }
584
0
}
585
586
void UnoControlContainer::impl_createControlPeerIfNecessary( const uno::Reference< awt::XControl >& _rxControl )
587
0
{
588
0
    OSL_PRECOND( _rxControl.is(), "UnoControlContainer::impl_createControlPeerIfNecessary: invalid control, this will crash!" );
589
590
    // if the container already has a peer, then also create a peer for the control
591
0
    uno::Reference< awt::XWindowPeer > xMyPeer( getPeer() );
592
593
0
    if( xMyPeer.is() )
594
0
    {
595
0
        _rxControl->createPeer( nullptr, xMyPeer );
596
0
        ImplActivateTabControllers();
597
0
    }
598
599
0
}
600
601
sal_Int32 UnoControlContainer::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
602
0
{
603
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
604
0
    UnoControlHolderList::ControlIdentifier id = mpControls->addControl( _rxControl, _pName );
605
606
0
    addingControl( _rxControl );
607
608
0
    impl_createControlPeerIfNecessary( _rxControl );
609
610
0
    if ( maCListeners.getLength() )
611
0
    {
612
0
        container::ContainerEvent aEvent;
613
0
        aEvent.Source = *this;
614
0
        if (_pName)
615
0
            aEvent.Accessor <<= *_pName;
616
0
        else
617
0
            aEvent.Accessor <<= static_cast<sal_Int32>(id);
618
0
        aEvent.Element <<= _rxControl;
619
0
        maCListeners.elementInserted( aEvent );
620
0
    }
621
622
0
    return id;
623
0
}
624
625
void UnoControlContainer::addControl( const OUString& rName, const uno::Reference< awt::XControl >& rControl )
626
0
{
627
0
    if ( rControl.is() )
628
0
        impl_addControl( rControl, &rName );
629
0
}
630
631
void UnoControlContainer::removingControl( const uno::Reference< awt::XControl >& _rxControl )
632
0
{
633
0
    if ( _rxControl.is() )
634
0
    {
635
0
        _rxControl->removeEventListener( this );
636
0
        _rxControl->setContext( nullptr );
637
0
    }
638
0
}
639
640
void UnoControlContainer::impl_removeControl( sal_Int32 _nId, const uno::Reference< awt::XControl >& _rxControl )
641
0
{
642
#ifdef DBG_UTIL
643
    {
644
        uno::Reference< awt::XControl > xControl;
645
        bool bHas = mpControls->getControlForIdentifier( _nId, xControl );
646
        DBG_ASSERT( bHas && xControl == _rxControl, "UnoControlContainer::impl_removeControl: inconsistency in the parameters!" );
647
    }
648
#endif
649
0
    removingControl( _rxControl );
650
651
0
    mpControls->removeControlById( _nId );
652
653
0
    if ( maCListeners.getLength() )
654
0
    {
655
0
        container::ContainerEvent aEvent;
656
0
        aEvent.Source = *this;
657
0
        aEvent.Accessor <<= _nId;
658
0
        aEvent.Element <<= _rxControl;
659
0
        maCListeners.elementRemoved( aEvent );
660
0
    }
661
0
}
662
663
void UnoControlContainer::removeControl( const uno::Reference< awt::XControl >& _rxControl )
664
0
{
665
0
    if ( _rxControl.is() )
666
0
    {
667
0
        ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
668
669
0
        UnoControlHolderList::ControlIdentifier id = mpControls->getControlIdentifier( _rxControl );
670
0
        if ( id != -1 )
671
0
            impl_removeControl( id, _rxControl );
672
0
    }
673
0
}
674
675
676
// awt::XUnoControlContainer
677
void UnoControlContainer::setTabControllers( const uno::Sequence< uno::Reference< awt::XTabController > >& TabControllers )
678
0
{
679
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
680
681
0
    maTabControllers = TabControllers;
682
0
}
683
684
uno::Sequence< uno::Reference< awt::XTabController > > UnoControlContainer::getTabControllers(  )
685
0
{
686
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
687
688
0
    return maTabControllers;
689
0
}
690
691
void UnoControlContainer::addTabController( const uno::Reference< awt::XTabController >& TabController )
692
0
{
693
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
694
695
0
    sal_uInt32 nCount = maTabControllers.getLength();
696
0
    maTabControllers.realloc( nCount + 1 );
697
0
    maTabControllers.getArray()[ nCount ] = TabController;
698
0
}
699
700
void UnoControlContainer::removeTabController( const uno::Reference< awt::XTabController >& TabController )
701
0
{
702
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
703
704
0
    auto pTabController = std::find_if(std::cbegin(maTabControllers), std::cend(maTabControllers),
705
0
        [&TabController](const uno::Reference< awt::XTabController >& rTabController) {
706
0
            return rTabController.get() == TabController.get(); });
707
0
    if (pTabController != std::cend(maTabControllers))
708
0
    {
709
0
        auto n = static_cast<sal_Int32>(std::distance(std::cbegin(maTabControllers), pTabController));
710
0
        ::comphelper::removeElementAt( maTabControllers, n );
711
0
    }
712
0
}
713
714
// awt::XControl
715
void UnoControlContainer::createPeer( const uno::Reference< awt::XToolkit >& rxToolkit, const uno::Reference< awt::XWindowPeer >& rParent )
716
26
{
717
26
    osl::ResettableMutexGuard aGuard(GetMutex());
718
719
26
    if( getPeer().is() )
720
26
        return;
721
722
0
    bool bVis = maComponentInfos.bVisible;
723
0
    if( bVis )
724
0
        UnoControl::setVisible( false );
725
726
    // Create a new peer
727
    // tdf#170961: release mutex around inherited createPeer, which may call to the main thread,
728
    // while the main thread may need this mutex
729
0
    {
730
0
        osl::ResettableMutexGuardScopedReleaser aRelease(aGuard);
731
0
        UnoControl::createPeer(rxToolkit, rParent);
732
0
    }
733
734
    // Create all children's peers
735
0
    if ( !mbCreatingCompatiblePeer )
736
0
    {
737
        // Evaluate "Step" property
738
0
        uno::Reference< awt::XControlModel > xModel( getModel() );
739
0
        uno::Reference< beans::XPropertySet > xPSet
740
0
            ( xModel, uno::UNO_QUERY );
741
0
        uno::Reference< beans::XPropertySetInfo >
742
0
            xInfo = xPSet->getPropertySetInfo();
743
0
        OUString aPropName( u"Step"_ustr );
744
0
        if ( xInfo->hasPropertyByName( aPropName ) )
745
0
        {
746
0
            css::uno::Any aVal = xPSet->getPropertyValue( aPropName );
747
0
            sal_Int32 nDialogStep = 0;
748
0
            aVal >>= nDialogStep;
749
0
            uno::Reference< awt::XControlContainer > xContainer =
750
0
                static_cast< awt::XControlContainer* >(this);
751
0
            implUpdateVisibility( nDialogStep, xContainer );
752
753
0
            uno::Reference< beans::XPropertyChangeListener > xListener =
754
0
                new DialogStepChangedListener(xContainer);
755
0
            xPSet->addPropertyChangeListener( aPropName, xListener );
756
0
        }
757
758
0
        uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
759
0
        for( auto& rCtrl : asNonConstRange(aCtrls) )
760
0
            rCtrl->createPeer( rxToolkit, getPeer() );
761
762
0
        uno::Reference< awt::XVclContainerPeer >  xC( getPeer(), uno::UNO_QUERY );
763
0
        if ( xC.is() )
764
0
            xC->enableDialogControl( true );
765
0
        ImplActivateTabControllers();
766
0
    }
767
768
0
    if( bVis && !isDesignMode() )
769
0
        UnoControl::setVisible( true );
770
0
}
771
772
773
// awt::XWindow
774
void UnoControlContainer::setVisible( sal_Bool bVisible )
775
0
{
776
0
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
777
778
0
    UnoControl::setVisible( bVisible );
779
0
    if( !mxContext.is() && bVisible )
780
        // This is a Topwindow, thus show it automatically
781
0
        createPeer( uno::Reference< awt::XToolkit > (), uno::Reference< awt::XWindowPeer > () );
782
0
}
783
784
OUString UnoControlContainer::getImplementationName()
785
0
{
786
0
    return u"stardiv.Toolkit.UnoControlContainer"_ustr;
787
0
}
788
789
css::uno::Sequence<OUString> UnoControlContainer::getSupportedServiceNames()
790
0
{
791
0
    auto s(UnoControlBase::getSupportedServiceNames());
792
0
    s.realloc(s.getLength() + 2);
793
0
    auto ps = s.getArray();
794
0
    ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlContainer";
795
0
    ps[s.getLength() - 1] = "stardiv.vcl.control.ControlContainer";
796
0
    return s;
797
0
}
798
799
void UnoControlContainer::PrepareWindowDescriptor( css::awt::WindowDescriptor& rDesc )
800
0
{
801
    // HACK due to the fact that we can't really use VSCROLL & HSCROLL
802
    // for Dialog  ( css::awt::VclWindowPeerAttribute::VSCROLL
803
    // has the same value as
804
    // css::awt::WindowAttribute::NODECORATION )
805
    // For convenience in the PropBrowse using HSCROLL and VSCROLL ensures
806
    // the Correct text. We exchange them here and the control knows
807
    // about this hack ( it sucks badly I know )
808
0
    if ( rDesc.WindowAttributes & css::awt::VclWindowPeerAttribute::VSCROLL )
809
0
    {
810
0
       rDesc.WindowAttributes &= ~css::awt::VclWindowPeerAttribute::VSCROLL;
811
0
       rDesc.WindowAttributes |= css::awt::VclWindowPeerAttribute::AUTOVSCROLL;
812
0
    }
813
0
    if ( rDesc.WindowAttributes & css::awt::VclWindowPeerAttribute::HSCROLL )
814
0
    {
815
0
       rDesc.WindowAttributes &= ~css::awt::VclWindowPeerAttribute::HSCROLL;
816
0
       rDesc.WindowAttributes |= css::awt::VclWindowPeerAttribute::AUTOHSCROLL;
817
0
    }
818
0
}
819
820
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
821
stardiv_Toolkit_UnoControlContainer_get_implementation(
822
    css::uno::XComponentContext *,
823
    css::uno::Sequence<css::uno::Any> const &)
824
0
{
825
0
    return cppu::acquire(new UnoControlContainer());
826
0
}
827
828
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */