Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/uno/toolboxcontroller.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 <svtools/toolboxcontroller.hxx>
21
#include <com/sun/star/beans/PropertyAttribute.hpp>
22
#include <com/sun/star/beans/PropertyValue.hpp>
23
#include <com/sun/star/beans/XPropertySet.hpp>
24
#include <com/sun/star/frame/XDispatchProvider.hpp>
25
#include <com/sun/star/lang/DisposedException.hpp>
26
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
27
#include <com/sun/star/frame/XLayoutManager.hpp>
28
#include <com/sun/star/util/URLTransformer.hpp>
29
#include <utility>
30
#include <vcl/commandinfoprovider.hxx>
31
#include <vcl/svapp.hxx>
32
#include <toolkit/helper/vclunohelper.hxx>
33
#include <vcl/toolbox.hxx>
34
#include <vcl/weld/Toolbar.hxx>
35
#include <vcl/weld/weldutils.hxx>
36
#include <comphelper/processfactory.hxx>
37
#include <comphelper/propertyvalue.hxx>
38
39
const int TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIBLE  = 1;
40
constexpr OUString TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIBLE = u"SupportsVisible"_ustr;
41
42
43
using namespace ::cppu;
44
using namespace css::awt;
45
using namespace css::uno;
46
using namespace css::util;
47
using namespace css::beans;
48
using namespace css::lang;
49
using namespace css::frame;
50
51
namespace svt
52
{
53
54
ToolboxController::ToolboxController(
55
    const Reference< XComponentContext >& rxContext,
56
    const Reference< XFrame >& xFrame,
57
    OUString aCommandURL ) :
58
0
    OPropertyContainer( GetBroadcastHelper() )
59
0
    ,   m_bSupportVisible( false )
60
0
    ,   m_bInitialized( false )
61
0
    ,   m_bDisposed( false )
62
0
    ,   m_bSidebar( false )
63
0
    ,   m_nToolBoxId( SAL_MAX_UINT16 )
64
0
    ,   m_xFrame( xFrame )
65
0
    ,   m_xContext( rxContext )
66
0
    ,   m_aCommandURL(std::move( aCommandURL ))
67
0
    ,   m_aListenerContainer( m_aMutex )
68
0
    ,   m_pToolbar(nullptr)
69
0
    ,   m_pBuilder(nullptr)
70
0
{
71
0
    OSL_ASSERT( m_xContext.is() );
72
0
    registerProperty( TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIBLE,
73
0
        TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIBLE,
74
0
        css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY,
75
0
        &m_bSupportVisible, cppu::UnoType<decltype(m_bSupportVisible)>::get());
76
77
0
    try
78
0
    {
79
0
        m_xUrlTransformer = URLTransformer::create( rxContext );
80
0
    }
81
0
    catch(const Exception&)
82
0
    {
83
0
    }
84
0
}
85
86
ToolboxController::ToolboxController() :
87
0
    OPropertyContainer(GetBroadcastHelper())
88
0
    ,   m_bSupportVisible(false)
89
0
    ,   m_bInitialized( false )
90
0
    ,   m_bDisposed( false )
91
0
    ,   m_bSidebar( false )
92
0
    ,   m_nToolBoxId( SAL_MAX_UINT16 )
93
0
    ,   m_aListenerContainer( m_aMutex )
94
0
    ,   m_pToolbar(nullptr)
95
0
    ,   m_pBuilder(nullptr)
96
0
{
97
0
    registerProperty( TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIBLE,
98
0
        TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIBLE,
99
0
        css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY,
100
0
        &m_bSupportVisible, cppu::UnoType<decltype(m_bSupportVisible)>::get());
101
0
}
102
103
ToolboxController::~ToolboxController()
104
0
{
105
0
}
106
107
Reference< XFrame > ToolboxController::getFrameInterface() const
108
0
{
109
0
    SolarMutexGuard aSolarMutexGuard;
110
0
    return m_xFrame;
111
0
}
112
113
const Reference< XComponentContext > & ToolboxController::getContext() const
114
0
{
115
0
    SolarMutexGuard aSolarMutexGuard;
116
0
    return m_xContext;
117
0
}
118
119
Reference< XLayoutManager > ToolboxController::getLayoutManager() const
120
0
{
121
0
    Reference< XLayoutManager > xLayoutManager;
122
0
    Reference< XPropertySet > xPropSet;
123
0
    {
124
0
        SolarMutexGuard aSolarMutexGuard;
125
0
        xPropSet.set( m_xFrame, UNO_QUERY );
126
0
    }
127
128
0
    if ( xPropSet.is() )
129
0
    {
130
0
        try
131
0
        {
132
0
            xLayoutManager.set(xPropSet->getPropertyValue(u"LayoutManager"_ustr),UNO_QUERY);
133
0
        }
134
0
        catch ( Exception& )
135
0
        {
136
0
        }
137
0
    }
138
139
0
    return xLayoutManager;
140
0
}
141
142
// XInterface
143
Any SAL_CALL ToolboxController::queryInterface( const Type& rType )
144
0
{
145
0
    css::uno::Any a(ToolboxController_Base::queryInterface(rType));
146
0
    return a.hasValue() ? a : OPropertyContainer::queryInterface(rType);
147
0
}
148
149
void SAL_CALL ToolboxController::acquire() noexcept
150
0
{
151
0
    ToolboxController_Base::acquire();
152
0
}
153
154
void SAL_CALL ToolboxController::release() noexcept
155
0
{
156
0
    ToolboxController_Base::release();
157
0
}
158
159
css::uno::Sequence<css::uno::Type> ToolboxController::getTypes()
160
0
{
161
0
    return comphelper::concatSequences(ToolboxController_Base::getTypes(),
162
0
                getBaseTypes());
163
0
}
164
165
void SAL_CALL ToolboxController::initialize( const Sequence< Any >& rArguments )
166
0
{
167
0
    SolarMutexGuard aSolarMutexGuard;
168
169
0
    if ( m_bDisposed )
170
0
        throw DisposedException();
171
172
0
    if ( m_bInitialized )
173
0
        return;
174
175
0
    m_bInitialized = true;
176
0
    m_bSupportVisible = false;
177
0
    PropertyValue aPropValue;
178
0
    for ( const auto& rArgument : rArguments )
179
0
    {
180
0
        if ( rArgument >>= aPropValue )
181
0
        {
182
0
            if ( aPropValue.Name == "Frame" )
183
0
                m_xFrame.set(aPropValue.Value,UNO_QUERY);
184
0
            else if ( aPropValue.Name == "CommandURL" )
185
0
                aPropValue.Value >>= m_aCommandURL;
186
0
            else if ( aPropValue.Name == "ServiceManager" )
187
0
            {
188
0
                Reference<XMultiServiceFactory> xMSF(aPropValue.Value, UNO_QUERY);
189
0
                if (xMSF.is())
190
0
                    m_xContext = comphelper::getComponentContext(xMSF);
191
0
            }
192
0
            else if ( aPropValue.Name == "ParentWindow" )
193
0
                m_xParentWindow.set(aPropValue.Value,UNO_QUERY);
194
0
            else if ( aPropValue.Name == "ModuleIdentifier" )
195
0
                aPropValue.Value >>= m_sModuleName;
196
0
            else if ( aPropValue.Name == "Identifier" )
197
0
            {
198
0
                sal_uInt16 nTmp;
199
0
                if (aPropValue.Value >>= nTmp)
200
0
                    m_nToolBoxId = ToolBoxItemId(nTmp);
201
0
            }
202
0
            else if ( aPropValue.Name == "IsSidebar" )
203
0
                aPropValue.Value >>= m_bSidebar;
204
0
        }
205
0
    }
206
207
0
    try
208
0
    {
209
0
        if ( !m_xUrlTransformer.is() && m_xContext.is() )
210
0
            m_xUrlTransformer = URLTransformer::create( m_xContext );
211
0
    }
212
0
    catch(const Exception&)
213
0
    {
214
0
    }
215
216
0
    if ( !m_aCommandURL.isEmpty() )
217
0
        m_aListenerMap.emplace( m_aCommandURL, Reference< XDispatch >() );
218
219
0
    if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(getParent().get()))
220
0
    {
221
0
        m_pToolbar = dynamic_cast<weld::Toolbar*>(pTunnel->getWidget());
222
0
        assert(m_pToolbar && "must be a toolbar");
223
0
        m_pBuilder = pTunnel->getBuilder();
224
0
    }
225
0
}
226
227
void SAL_CALL ToolboxController::update()
228
0
{
229
0
    {
230
0
        SolarMutexGuard aSolarMutexGuard;
231
0
        if ( m_bDisposed )
232
0
            throw DisposedException();
233
0
    }
234
235
    // Bind all registered listeners to their dispatch objects
236
0
    bindListener();
237
0
}
238
239
// XComponent
240
void SAL_CALL ToolboxController::dispose()
241
0
{
242
0
    Reference< XComponent > xThis(this);
243
244
0
    {
245
0
        SolarMutexGuard aSolarMutexGuard;
246
0
        if ( m_bDisposed )
247
0
            return;
248
0
    }
249
250
0
    css::lang::EventObject aEvent( xThis );
251
0
    m_aListenerContainer.disposeAndClear( aEvent );
252
253
0
    SolarMutexGuard aSolarMutexGuard;
254
0
    Reference< XStatusListener > xStatusListener(this);
255
0
    for (auto const& listener : m_aListenerMap)
256
0
    {
257
0
        try
258
0
        {
259
0
            Reference< XDispatch > xDispatch( listener.second );
260
261
0
            css::util::URL aTargetURL;
262
0
            aTargetURL.Complete = listener.first;
263
0
            if ( m_xUrlTransformer.is() )
264
0
                m_xUrlTransformer->parseStrict( aTargetURL );
265
266
0
            if ( xDispatch.is() && xStatusListener.is() )
267
0
                xDispatch->removeStatusListener( xStatusListener, aTargetURL );
268
0
        }
269
0
        catch ( Exception& )
270
0
        {
271
0
        }
272
273
0
    }
274
275
0
    m_bDisposed = true;
276
0
}
277
278
void SAL_CALL ToolboxController::addEventListener( const Reference< XEventListener >& xListener )
279
0
{
280
0
    m_aListenerContainer.addInterface( cppu::UnoType<XEventListener>::get(), xListener );
281
0
}
282
283
void SAL_CALL ToolboxController::removeEventListener( const Reference< XEventListener >& rListener )
284
0
{
285
0
    m_aListenerContainer.removeInterface( cppu::UnoType<XEventListener>::get(), rListener );
286
0
}
287
288
// XEventListener
289
void SAL_CALL ToolboxController::disposing( const EventObject& Source )
290
0
{
291
0
    Reference< XInterface > xSource( Source.Source );
292
293
0
    SolarMutexGuard aSolarMutexGuard;
294
295
0
    if ( m_bDisposed )
296
0
        return;
297
298
0
    for (auto & listener : m_aListenerMap)
299
0
    {
300
        // Compare references and release dispatch references if they are equal.
301
0
        Reference< XInterface > xIfac(listener.second, UNO_QUERY);
302
0
        if ( xSource == xIfac )
303
0
            listener.second.clear();
304
0
    }
305
306
0
    Reference< XInterface > xIfac( m_xFrame, UNO_QUERY );
307
0
    if ( xIfac == xSource )
308
0
        m_xFrame.clear();
309
0
}
310
311
// XStatusListener
312
void SAL_CALL ToolboxController::statusChanged( const FeatureStateEvent& )
313
0
{
314
    // must be implemented by sub class
315
0
}
316
317
// XToolbarController
318
void SAL_CALL ToolboxController::execute( sal_Int16 KeyModifier )
319
0
{
320
0
    Reference< XDispatch >       xDispatch;
321
0
    OUString                     aCommandURL;
322
323
0
    {
324
0
        SolarMutexGuard aSolarMutexGuard;
325
326
0
        if ( m_bDisposed )
327
0
            throw DisposedException();
328
329
0
        if ( m_bInitialized &&
330
0
             m_xFrame.is() &&
331
0
             !m_aCommandURL.isEmpty() )
332
0
        {
333
0
            aCommandURL = m_aCommandURL;
334
0
            URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
335
0
            if ( pIter != m_aListenerMap.end() )
336
0
                xDispatch = pIter->second;
337
0
        }
338
0
    }
339
340
0
    if ( !xDispatch.is() )
341
0
        return;
342
343
0
    try
344
0
    {
345
0
        css::util::URL aTargetURL;
346
347
        // Provide key modifier information to dispatch function
348
0
        Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue(u"KeyModifier"_ustr, KeyModifier) };
349
350
0
        aTargetURL.Complete = aCommandURL;
351
0
        if ( m_xUrlTransformer.is() )
352
0
            m_xUrlTransformer->parseStrict( aTargetURL );
353
0
        xDispatch->dispatch( aTargetURL, aArgs );
354
0
    }
355
0
    catch ( DisposedException& )
356
0
    {
357
0
    }
358
0
}
359
360
void SAL_CALL ToolboxController::click()
361
0
{
362
0
}
363
364
void SAL_CALL ToolboxController::doubleClick()
365
0
{
366
0
}
367
368
Reference< XWindow > SAL_CALL ToolboxController::createPopupWindow()
369
0
{
370
0
    return Reference< XWindow >();
371
0
}
372
373
Reference< XWindow > SAL_CALL ToolboxController::createItemWindow( const Reference< XWindow >& )
374
0
{
375
0
    return Reference< XWindow >();
376
0
}
377
378
void ToolboxController::addStatusListener( const OUString& rCommandURL )
379
0
{
380
0
    Reference< XDispatch >       xDispatch;
381
0
    Reference< XStatusListener > xStatusListener;
382
0
    css::util::URL    aTargetURL;
383
384
0
    {
385
0
        SolarMutexGuard aSolarMutexGuard;
386
0
        URLToDispatchMap::iterator pIter = m_aListenerMap.find( rCommandURL );
387
388
        // Already in the list of status listener. Do nothing.
389
0
        if ( pIter != m_aListenerMap.end() )
390
0
            return;
391
392
        // Check if we are already initialized. Implementation starts adding itself as status listener when
393
        // initialize is called.
394
0
        if ( !m_bInitialized )
395
0
        {
396
            // Put into the unordered_map of status listener. Will be activated when initialized is called
397
0
            m_aListenerMap.emplace( rCommandURL, Reference< XDispatch >() );
398
0
            return;
399
0
        }
400
0
        else
401
0
        {
402
            // Add status listener directly as initialize has already been called.
403
0
            Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
404
0
            if ( m_xContext.is() && xDispatchProvider.is() )
405
0
            {
406
0
                aTargetURL.Complete = rCommandURL;
407
0
                if ( m_xUrlTransformer.is() )
408
0
                    m_xUrlTransformer->parseStrict( aTargetURL );
409
0
                xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
410
411
0
                xStatusListener = this;
412
0
                URLToDispatchMap::iterator aIter = m_aListenerMap.find( rCommandURL );
413
0
                if ( aIter != m_aListenerMap.end() )
414
0
                {
415
0
                    Reference< XDispatch > xOldDispatch( aIter->second );
416
0
                    aIter->second = xDispatch;
417
418
0
                    try
419
0
                    {
420
0
                        if ( xOldDispatch.is() )
421
0
                            xOldDispatch->removeStatusListener( xStatusListener, aTargetURL );
422
0
                    }
423
0
                    catch ( Exception& )
424
0
                    {
425
0
                    }
426
0
                }
427
0
                else
428
0
                    m_aListenerMap.emplace( rCommandURL, xDispatch );
429
0
            }
430
0
        }
431
0
    }
432
433
    // Call without locked mutex as we are called back from dispatch implementation
434
0
    try
435
0
    {
436
0
        if ( xDispatch.is() )
437
0
            xDispatch->addStatusListener( xStatusListener, aTargetURL );
438
0
    }
439
0
    catch ( Exception& )
440
0
    {
441
0
    }
442
0
}
443
444
void ToolboxController::removeStatusListener( const OUString& rCommandURL )
445
0
{
446
0
    SolarMutexGuard aSolarMutexGuard;
447
448
0
    URLToDispatchMap::iterator pIter = m_aListenerMap.find( rCommandURL );
449
0
    if ( pIter == m_aListenerMap.end() )
450
0
        return;
451
452
0
    Reference< XDispatch > xDispatch( pIter->second );
453
0
    Reference< XStatusListener > xStatusListener(this);
454
0
    m_aListenerMap.erase( pIter );
455
456
0
    try
457
0
    {
458
0
        css::util::URL aTargetURL;
459
0
        aTargetURL.Complete = rCommandURL;
460
0
        if ( m_xUrlTransformer.is() )
461
0
            m_xUrlTransformer->parseStrict( aTargetURL );
462
463
0
        if ( xDispatch.is() && xStatusListener.is() )
464
0
            xDispatch->removeStatusListener( xStatusListener, aTargetURL );
465
0
    }
466
0
    catch ( Exception& )
467
0
    {
468
0
    }
469
0
}
470
471
void ToolboxController::bindListener()
472
0
{
473
0
    std::vector< Listener > aDispatchVector;
474
0
    Reference< XStatusListener > xStatusListener;
475
476
0
    {
477
0
        SolarMutexGuard aSolarMutexGuard;
478
479
0
        if ( !m_bInitialized )
480
0
            return;
481
482
        // Collect all registered command URL's and store them temporary
483
0
        Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
484
0
        if ( m_xContext.is() && xDispatchProvider.is() )
485
0
        {
486
0
            xStatusListener = this;
487
0
            for (auto & listener : m_aListenerMap)
488
0
            {
489
0
                css::util::URL aTargetURL;
490
0
                aTargetURL.Complete = listener.first;
491
0
                if ( m_xUrlTransformer.is() )
492
0
                    m_xUrlTransformer->parseStrict( aTargetURL );
493
494
0
                Reference< XDispatch > xDispatch(listener.second);
495
0
                if ( xDispatch.is() )
496
0
                {
497
                    // We already have a dispatch object => we have to requery.
498
                    // Release old dispatch object and remove it as listener
499
0
                    try
500
0
                    {
501
0
                        xDispatch->removeStatusListener( xStatusListener, aTargetURL );
502
0
                    }
503
0
                    catch ( Exception& )
504
0
                    {
505
0
                    }
506
0
                }
507
508
0
                listener.second.clear();
509
0
                xDispatch.clear();
510
511
                // Query for dispatch object. Old dispatch will be released with this, too.
512
0
                try
513
0
                {
514
0
                    xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
515
0
                }
516
0
                catch ( Exception& )
517
0
                {
518
0
                }
519
520
                // it may be a command alias
521
0
                if (!xDispatch.is())
522
0
                {
523
0
                    try
524
0
                    {
525
0
                        auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(listener.first,
526
0
                            vcl::CommandInfoProvider::GetModuleIdentifier(m_xFrame));
527
0
                        OUString sRealCommand = vcl::CommandInfoProvider::GetRealCommandForCommand(aProperties);
528
529
0
                        if (!sRealCommand.isEmpty())
530
0
                        {
531
0
                            aTargetURL.Complete = sRealCommand;
532
0
                            if ( m_xUrlTransformer.is() )
533
0
                                m_xUrlTransformer->parseStrict( aTargetURL );
534
535
0
                            xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
536
0
                        }
537
0
                    }
538
0
                    catch ( Exception& )
539
0
                    {
540
0
                    }
541
0
                }
542
543
0
                listener.second = xDispatch;
544
545
0
                aDispatchVector.emplace_back(aTargetURL, xDispatch);
546
0
            }
547
0
        }
548
0
    }
549
550
    // Call without locked mutex as we are called back from dispatch implementation
551
0
    if ( !xStatusListener.is() )
552
0
        return;
553
554
0
    try
555
0
    {
556
0
        for (Listener & rListener : aDispatchVector)
557
0
        {
558
0
            if ( rListener.xDispatch.is() )
559
0
                rListener.xDispatch->addStatusListener( xStatusListener, rListener.aURL );
560
0
            else if ( rListener.aURL.Complete == m_aCommandURL )
561
0
            {
562
0
                try
563
0
                {
564
                    // Send status changed for the main URL, if we cannot get a valid dispatch object.
565
                    // UI disables the button. Catch exception as we release our mutex, it is possible
566
                    // that someone else already disposed this instance!
567
0
                    FeatureStateEvent aFeatureStateEvent;
568
0
                    aFeatureStateEvent.IsEnabled = false;
569
0
                    aFeatureStateEvent.FeatureURL = rListener.aURL;
570
0
                    aFeatureStateEvent.State = Any();
571
0
                    xStatusListener->statusChanged( aFeatureStateEvent );
572
0
                }
573
0
                catch ( Exception& )
574
0
                {
575
0
                }
576
0
            }
577
0
        }
578
0
    }
579
0
    catch ( Exception& )
580
0
    {
581
0
    }
582
0
}
583
584
void ToolboxController::unbindListener()
585
0
{
586
0
    SolarMutexGuard aSolarMutexGuard;
587
588
0
    if ( !m_bInitialized )
589
0
        return;
590
591
    // Collect all registered command URL's and store them temporary
592
0
    Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
593
0
    if ( !(m_xContext.is() && xDispatchProvider.is()) )
594
0
        return;
595
596
0
    Reference< XStatusListener > xStatusListener(this);
597
0
    for (auto & listener : m_aListenerMap)
598
0
    {
599
0
        css::util::URL aTargetURL;
600
0
        aTargetURL.Complete = listener.first;
601
0
        if ( m_xUrlTransformer.is() )
602
0
            m_xUrlTransformer->parseStrict( aTargetURL );
603
604
0
        Reference< XDispatch > xDispatch(listener.second);
605
0
        if ( xDispatch.is() )
606
0
        {
607
            // We already have a dispatch object => we have to requery.
608
            // Release old dispatch object and remove it as listener
609
0
            try
610
0
            {
611
0
                xDispatch->removeStatusListener( xStatusListener, aTargetURL );
612
0
            }
613
0
            catch ( Exception& )
614
0
            {
615
0
            }
616
0
        }
617
0
        listener.second.clear();
618
0
    }
619
0
}
620
621
void ToolboxController::updateStatus()
622
0
{
623
0
    bindListener();
624
0
}
625
626
void ToolboxController::updateStatus( const OUString& rCommandURL )
627
0
{
628
0
    Reference< XDispatch > xDispatch;
629
0
    Reference< XStatusListener > xStatusListener;
630
0
    css::util::URL aTargetURL;
631
632
0
    {
633
0
        SolarMutexGuard aSolarMutexGuard;
634
635
0
        if ( !m_bInitialized )
636
0
            return;
637
638
        // Try to find a dispatch object for the requested command URL
639
0
        Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
640
0
        xStatusListener = this;
641
0
        if ( m_xContext.is() && xDispatchProvider.is() )
642
0
        {
643
0
            aTargetURL.Complete = rCommandURL;
644
0
            if ( m_xUrlTransformer.is() )
645
0
                m_xUrlTransformer->parseStrict( aTargetURL );
646
0
            xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
647
0
        }
648
0
    }
649
650
0
    if ( !(xDispatch.is() && xStatusListener.is()) )
651
0
        return;
652
653
    // Catch exception as we release our mutex, it is possible that someone else
654
    // has already disposed this instance!
655
    // Add/remove status listener to get an update status information from the
656
    // requested command.
657
0
    try
658
0
    {
659
0
        xDispatch->addStatusListener( xStatusListener, aTargetURL );
660
0
        xDispatch->removeStatusListener( xStatusListener, aTargetURL );
661
0
    }
662
0
    catch ( Exception& )
663
0
    {
664
0
    }
665
0
}
666
667
668
void ToolboxController::dispatchCommand( const OUString& sCommandURL, const Sequence< PropertyValue >& rArgs, const OUString &sTarget )
669
0
{
670
0
    try
671
0
    {
672
0
        Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW );
673
0
        URL aURL;
674
0
        aURL.Complete = sCommandURL;
675
0
        getURLTransformer()->parseStrict( aURL );
676
677
0
        Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, sTarget, 0 ), UNO_SET_THROW );
678
679
0
        std::unique_ptr<DispatchInfo> pDispatchInfo(new DispatchInfo( xDispatch, std::move(aURL), rArgs ));
680
0
        if ( Application::PostUserEvent( LINK(nullptr, ToolboxController, ExecuteHdl_Impl),
681
0
                                          pDispatchInfo.get() ) )
682
0
            pDispatchInfo.release();
683
684
0
    }
685
0
    catch( Exception& )
686
0
    {
687
0
    }
688
0
}
689
690
691
css::uno::Reference< css::beans::XPropertySetInfo >  SAL_CALL ToolboxController::getPropertySetInfo()
692
0
{
693
0
    Reference<XPropertySetInfo>  xInfo( createPropertySetInfo( getInfoHelper() ) );
694
0
    return xInfo;
695
0
}
696
697
::cppu::IPropertyArrayHelper& ToolboxController::getInfoHelper()
698
0
{
699
0
        return *getArrayHelper();
700
0
}
701
702
703
::cppu::IPropertyArrayHelper* ToolboxController::createArrayHelper( ) const
704
0
{
705
0
        css::uno::Sequence< Property > aProps;
706
0
        describeProperties(aProps);
707
0
        return new ::cppu::OPropertyArrayHelper(aProps);
708
0
}
709
710
sal_Bool SAL_CALL ToolboxController::convertFastPropertyValue(css::uno::Any& aConvertedValue,
711
                                                              css::uno::Any& aOldValue,
712
                                                              sal_Int32 nHandle,
713
                                                              const css::uno::Any& rValue)
714
0
{
715
0
    switch (nHandle)
716
0
    {
717
0
        case TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIBLE:
718
0
        {
719
0
            bool aNewValue(false);
720
0
            rValue >>= aNewValue;
721
0
            if (aNewValue != m_bSupportVisible)
722
0
            {
723
0
                aConvertedValue <<= aNewValue;
724
0
                aOldValue <<= m_bSupportVisible;
725
0
                return true;
726
0
            }
727
0
            return false;
728
0
        }
729
0
    }
730
0
    return OPropertyContainer::convertFastPropertyValue(aConvertedValue, aOldValue, nHandle, rValue);
731
0
}
732
733
void SAL_CALL ToolboxController::setFastPropertyValue_NoBroadcast(
734
    sal_Int32                       nHandle,
735
    const css::uno::Any& rValue )
736
0
{
737
0
    OPropertyContainer::setFastPropertyValue_NoBroadcast(nHandle, rValue);
738
0
    if (TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIBLE == nHandle)
739
0
    {
740
0
        bool bValue(false);
741
0
        if (( rValue >>= bValue ) && m_bInitialized)
742
0
            m_bSupportVisible = bValue;
743
0
    }
744
0
}
745
746
747
IMPL_STATIC_LINK( ToolboxController, ExecuteHdl_Impl, void*, p, void )
748
0
{
749
0
    DispatchInfo* pDispatchInfo = static_cast<DispatchInfo*>(p);
750
0
    pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs );
751
0
    delete pDispatchInfo;
752
0
}
753
754
void ToolboxController::enable( bool bEnable )
755
0
{
756
0
    ToolBox* pToolBox = nullptr;
757
0
    ToolBoxItemId nItemId;
758
0
    if( getToolboxId( nItemId, &pToolBox ) )
759
0
    {
760
0
        pToolBox->EnableItem( nItemId, bEnable );
761
0
    }
762
0
}
763
764
bool ToolboxController::getToolboxId( ToolBoxItemId& rItemId, ToolBox** ppToolBox )
765
0
{
766
0
    if( (m_nToolBoxId != ToolBoxItemId(SAL_MAX_UINT16)) && (ppToolBox == nullptr) )
767
0
        return false;
768
769
0
    ToolBox* pToolBox = static_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) );
770
771
0
    if( (m_nToolBoxId == ToolBoxItemId(SAL_MAX_UINT16)) && pToolBox )
772
0
    {
773
0
        const ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
774
0
        for ( ToolBox::ImplToolItems::size_type nPos = 0; nPos < nCount; ++nPos )
775
0
        {
776
0
            const ToolBoxItemId nItemId = pToolBox->GetItemId( nPos );
777
0
            if ( pToolBox->GetItemCommand( nItemId ) == m_aCommandURL )
778
0
            {
779
0
                m_nToolBoxId = nItemId;
780
0
                break;
781
0
            }
782
0
        }
783
0
    }
784
785
0
    if( ppToolBox )
786
0
        *ppToolBox = pToolBox;
787
788
0
    rItemId = m_nToolBoxId;
789
790
0
    return (rItemId != ToolBoxItemId(SAL_MAX_UINT16)) && (( ppToolBox == nullptr) || (*ppToolBox != nullptr) );
791
0
}
792
//end
793
794
} // svt
795
796
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */