1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
25 #include <com/sun/star/uno/Reference.h>
26 #include <com/sun/star/frame/XFrame.hpp>
27 #include <com/sun/star/awt/XWindow.hpp>
28 #include <com/sun/star/util/URL.hpp>
29 #include <com/sun/star/util/URLTransformer.hpp>
30 #include <com/sun/star/util/XURLTransformer.hpp>
31 #include <com/sun/star/frame/XController.hpp>
32 #include <com/sun/star/frame/XDispatchProvider.hpp>
33 #include <com/sun/star/lang/XUnoTunnel.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/frame/status/ItemStatus.hpp>
36 #include <com/sun/star/ui/XUIElementFactory.hpp>
37 #include <com/sun/star/frame/status/Visibility.hpp>
38 #include <svl/eitem.hxx>
39 #include <svl/stritem.hxx>
40 #include <svl/intitem.hxx>
41 #include <svl/visitem.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/toolbox.hxx>
45 #include <svtools/framestatuslistener.hxx>
46 #include <comphelper/processfactory.hxx>
47 #include <vcl/taskpanelist.hxx>
48 #include <vcl/event.hxx>
49 #include <toolkit/helper/vclunohelper.hxx>
51 #include <vcl/InterimItemWindow.hxx>
52 #include <sfx2/tbxctrl.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include <sfx2/msg.hxx>
55 #include <sfx2/msgpool.hxx>
56 #include <sfx2/viewfrm.hxx>
57 #include <sfx2/module.hxx>
58 #include <sfx2/app.hxx>
59 #include <unoctitm.hxx>
60 #include <ctrlfactoryimpl.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::beans
;
64 using namespace ::com::sun::star::frame
;
65 using namespace ::com::sun::star::frame::status
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::util
;
69 using namespace ::com::sun::star::container
;
70 using namespace ::com::sun::star::ui
;
73 SFX_IMPL_TOOLBOX_CONTROL_ARG(SfxToolBoxControl
, SfxStringItem
, true);
75 svt::ToolboxController
* SfxToolBoxControllerFactory( const Reference
< XFrame
>& rFrame
, ToolBox
* pToolbox
, unsigned short nID
, const OUString
& aCommandURL
)
77 SolarMutexGuard aGuard
;
80 aTargetURL
.Complete
= aCommandURL
;
81 Reference
< XURLTransformer
> xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
82 xTrans
->parseStrict( aTargetURL
);
83 if ( !aTargetURL
.Arguments
.isEmpty() )
86 Reference
< XController
> xController
;
87 Reference
< XModel
> xModel
;
90 xController
= rFrame
->getController();
91 if ( xController
.is() )
92 xModel
= xController
->getModel();
95 SfxObjectShell
* pObjShell
= SfxObjectShell::GetShellFromComponent(xModel
);
96 SfxModule
* pModule
= pObjShell
? pObjShell
->GetModule() : nullptr;
97 SfxSlotPool
* pSlotPool
= nullptr;
100 pSlotPool
= pModule
->GetSlotPool();
102 pSlotPool
= &(SfxSlotPool::GetSlotPool());
104 const SfxSlot
* pSlot
= pSlotPool
->GetUnoSlot( aTargetURL
.Path
);
107 sal_uInt16 nSlotId
= pSlot
->GetSlotId();
109 return SfxToolBoxControl::CreateControl( nSlotId
, nID
, pToolbox
, pModule
);
115 struct SfxToolBoxControl_Impl
117 VclPtr
<ToolBox
> pBox
;
123 SfxToolBoxControl::SfxToolBoxControl(
127 bool bShowStringItems
)
128 : pImpl( new SfxToolBoxControl_Impl
)
131 pImpl
->bShowString
= bShowStringItems
;
133 pImpl
->nSlotId
= nSlotID
;
137 SfxToolBoxControl::~SfxToolBoxControl()
142 ToolBox
& SfxToolBoxControl::GetToolBox() const
146 unsigned short SfxToolBoxControl::GetId() const
148 return pImpl
->nTbxId
;
150 unsigned short SfxToolBoxControl::GetSlotId() const
152 return pImpl
->nSlotId
;
156 void SAL_CALL
SfxToolBoxControl::dispose()
161 svt::ToolboxController::dispose();
163 // Remove and destroy our item window at our toolbox
164 SolarMutexGuard aGuard
;
165 VclPtr
< vcl::Window
> pWindow
= pImpl
->pBox
->GetItemWindow( pImpl
->nTbxId
);
166 pImpl
->pBox
->SetItemWindow( pImpl
->nTbxId
, nullptr );
167 pWindow
.disposeAndClear();
171 void SfxToolBoxControl::RegisterToolBoxControl( SfxModule
* pMod
, const SfxTbxCtrlFactory
& rFact
)
173 SfxGetpApp()->RegisterToolBoxControl_Impl( pMod
, rFact
);
176 SfxToolBoxControl
* SfxToolBoxControl::CreateControl( sal_uInt16 nSlotId
, sal_uInt16 nTbxId
, ToolBox
*pBox
, SfxModule
const * pMod
)
178 SolarMutexGuard aGuard
;
180 SfxApplication
*pApp
= SfxGetpApp();
182 SfxSlotPool
*pSlotPool
;
184 pSlotPool
= pMod
->GetSlotPool();
186 pSlotPool
= &SfxSlotPool::GetSlotPool();
187 const std::type_info
* aSlotType
= pSlotPool
->GetSlotType( nSlotId
);
190 SfxToolBoxControl
*pCtrl
;
193 SfxTbxCtrlFactArr_Impl
*pFactories
= pMod
->GetTbxCtrlFactories_Impl();
196 SfxTbxCtrlFactArr_Impl
&rFactories
= *pFactories
;
198 const sal_uInt16 nCount
= rFactories
.size();
200 // search for a factory with the given slot id
201 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
202 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== nSlotId
) )
205 if( nFactory
== nCount
)
207 // if no factory exists for the given slot id, see if we
208 // have a generic factory with the correct slot type and slot id == 0
209 for ( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
210 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== 0) )
214 if( nFactory
< nCount
)
216 pCtrl
= rFactories
[nFactory
].pCtor( nSlotId
, nTbxId
, *pBox
);
222 SfxTbxCtrlFactArr_Impl
&rFactories
= pApp
->GetTbxCtrlFactories_Impl();
224 const sal_uInt16 nCount
= rFactories
.size();
226 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
227 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== nSlotId
) )
230 if( nFactory
== nCount
)
232 // if no factory exists for the given slot id, see if we
233 // have a generic factory with the correct slot type and slot id == 0
234 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
235 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== 0) )
239 if( nFactory
< nCount
)
241 pCtrl
= rFactories
[nFactory
].pCtor( nSlotId
, nTbxId
, *pBox
);
249 SfxItemState
SfxToolBoxControl::GetItemState(
250 const SfxPoolItem
* pState
)
253 Static method for determining the status of the SfxPoolItem-pointer,
254 used in the method <SfxControllerItem::StateChanged(const SfxPoolItem*)>.
258 SfxItemState SfxItemState::UNKNOWN
259 Enabled, however no further status information is available.
260 Typical for <Slot>s, which are temporarily disabled a
261 anyway but other than that do not change their appearance.
263 SfxItemState::DISABLED
264 Disabled, no further status information is available.
265 All other displayed values should be reset to the default
268 SfxItemState::DONTCARE
269 Enabled but there were only ambiguous values available
270 (i.e. none that could be queried).
272 SfxItemState::DEFAULT
273 Enabled and with available values which can be queried
274 through'pState'. The type is thus by the Slot clearly
275 defined in the entire Program.
280 ? SfxItemState::DISABLED
281 : IsInvalidItem(pState
)
282 ? SfxItemState::DONTCARE
283 : pState
->IsVoidItem() && !pState
->Which()
284 ? SfxItemState::UNKNOWN
285 : SfxItemState::DEFAULT
;
288 void SfxToolBoxControl::Dispatch(
289 const Reference
< XDispatchProvider
>& rProvider
,
290 const OUString
& rCommand
,
291 Sequence
< ::PropertyValue
> const & aArgs
)
293 if ( rProvider
.is() )
295 css::util::URL aTargetURL
;
296 aTargetURL
.Complete
= rCommand
;
297 Reference
< XURLTransformer
> xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
298 xTrans
->parseStrict( aTargetURL
);
300 Reference
< XDispatch
> xDispatch
= rProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
301 if ( xDispatch
.is() )
302 xDispatch
->dispatch( aTargetURL
, aArgs
);
306 void SfxToolBoxControl::Dispatch( const OUString
& aCommand
, css::uno::Sequence
< css::beans::PropertyValue
> const & aArgs
)
308 Reference
< XController
> xController
;
310 SolarMutexGuard aGuard
;
311 if ( getFrameInterface().is() )
312 xController
= getFrameInterface()->getController();
314 Reference
< XDispatchProvider
> xProvider( xController
, UNO_QUERY
);
315 if ( xProvider
.is() )
317 css::util::URL aTargetURL
;
318 aTargetURL
.Complete
= aCommand
;
319 getURLTransformer()->parseStrict( aTargetURL
);
321 Reference
< XDispatch
> xDispatch
= xProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
322 if ( xDispatch
.is() )
323 xDispatch
->dispatch( aTargetURL
, aArgs
);
328 void SAL_CALL
SfxToolBoxControl::statusChanged( const FeatureStateEvent
& rEvent
)
330 SfxViewFrame
* pViewFrame
= nullptr;
331 Reference
< XController
> xController
;
333 SolarMutexGuard aGuard
;
334 if ( getFrameInterface().is() )
335 xController
= getFrameInterface()->getController();
337 Reference
< XDispatchProvider
> xProvider( xController
, UNO_QUERY
);
338 if ( xProvider
.is() )
340 Reference
< XDispatch
> xDisp
= xProvider
->queryDispatch( rEvent
.FeatureURL
, OUString(), 0 );
343 Reference
< XUnoTunnel
> xTunnel( xDisp
, UNO_QUERY
);
344 SfxOfficeDispatch
* pDisp
= nullptr;
347 sal_Int64 nImplementation
= xTunnel
->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
348 pDisp
= reinterpret_cast< SfxOfficeDispatch
* >( sal::static_int_cast
< sal_IntPtr
>( nImplementation
));
352 pViewFrame
= pDisp
->GetDispatcher_Impl()->GetFrame();
356 sal_uInt16 nSlotId
= 0;
357 SfxSlotPool
& rPool
= SfxSlotPool::GetSlotPool( pViewFrame
);
358 const SfxSlot
* pSlot
= rPool
.GetUnoSlot( rEvent
.FeatureURL
.Path
);
360 nSlotId
= pSlot
->GetSlotId();
361 else if ( m_aCommandURL
== rEvent
.FeatureURL
.Path
)
362 nSlotId
= GetSlotId();
367 if ( rEvent
.Requery
)
368 svt::ToolboxController::statusChanged( rEvent
);
371 SfxItemState eState
= SfxItemState::DISABLED
;
372 std::unique_ptr
<SfxPoolItem
> pItem
;
373 if ( rEvent
.IsEnabled
)
375 eState
= SfxItemState::DEFAULT
;
376 css::uno::Type aType
= rEvent
.State
.getValueType();
378 if ( aType
== cppu::UnoType
<void>::get() )
380 pItem
.reset(new SfxVoidItem( nSlotId
));
381 eState
= SfxItemState::UNKNOWN
;
383 else if ( aType
== cppu::UnoType
<bool>::get() )
386 rEvent
.State
>>= bTemp
;
387 pItem
.reset(new SfxBoolItem( nSlotId
, bTemp
));
389 else if ( aType
== ::cppu::UnoType
< ::cppu::UnoUnsignedShortType
>::get())
391 sal_uInt16 nTemp
= 0;
392 rEvent
.State
>>= nTemp
;
393 pItem
.reset(new SfxUInt16Item( nSlotId
, nTemp
));
395 else if ( aType
== cppu::UnoType
<sal_uInt32
>::get() )
397 sal_uInt32 nTemp
= 0;
398 rEvent
.State
>>= nTemp
;
399 pItem
.reset(new SfxUInt32Item( nSlotId
, nTemp
));
401 else if ( aType
== cppu::UnoType
<OUString
>::get() )
404 rEvent
.State
>>= sTemp
;
405 pItem
.reset(new SfxStringItem( nSlotId
, sTemp
));
407 else if ( aType
== cppu::UnoType
< css::frame::status::ItemStatus
>::get() )
409 ItemStatus aItemStatus
;
410 rEvent
.State
>>= aItemStatus
;
411 SfxItemState tmpState
= static_cast<SfxItemState
>(aItemStatus
.State
);
412 // make sure no-one tries to send us a combination of states
413 if (tmpState
!= SfxItemState::UNKNOWN
&& tmpState
!= SfxItemState::DISABLED
&&
414 tmpState
!= SfxItemState::READONLY
&& tmpState
!= SfxItemState::DONTCARE
&&
415 tmpState
!= SfxItemState::DEFAULT
&& tmpState
!= SfxItemState::SET
)
416 throw css::uno::RuntimeException("unknown status");
418 pItem
.reset(new SfxVoidItem( nSlotId
));
420 else if ( aType
== cppu::UnoType
< css::frame::status::Visibility
>::get() )
422 Visibility aVisibilityStatus
;
423 rEvent
.State
>>= aVisibilityStatus
;
424 pItem
.reset(new SfxVisibilityItem( nSlotId
, aVisibilityStatus
.bVisible
));
429 pItem
= pSlot
->GetType()->CreateItem();
432 pItem
->SetWhich( nSlotId
);
433 pItem
->PutValue( rEvent
.State
, 0 );
436 pItem
.reset(new SfxVoidItem( nSlotId
));
440 StateChanged( nSlotId
, eState
, pItem
.get() );
444 // XToolbarController
445 void SAL_CALL
SfxToolBoxControl::execute( sal_Int16 KeyModifier
)
447 SolarMutexGuard aGuard
;
448 Select( static_cast<sal_uInt16
>(KeyModifier
) );
451 void SAL_CALL
SfxToolBoxControl::click()
453 SolarMutexGuard aGuard
;
457 void SAL_CALL
SfxToolBoxControl::doubleClick()
459 SolarMutexGuard aGuard
;
463 Reference
< css::awt::XWindow
> SAL_CALL
SfxToolBoxControl::createPopupWindow()
465 SolarMutexGuard aGuard
;
470 Reference
< css::awt::XWindow
> SAL_CALL
SfxToolBoxControl::createItemWindow( const Reference
< css::awt::XWindow
>& rParent
)
472 SolarMutexGuard aGuard
;
473 return VCLUnoHelper::GetInterface( CreateItemWindow( VCLUnoHelper::GetWindow( rParent
)));
476 void SfxToolBoxControl::StateChanged
480 const SfxPoolItem
* pState
483 DBG_ASSERT( pImpl
->pBox
!= nullptr, "setting state to dangling ToolBox" );
485 // enabled/disabled-Flag correcting the lump sum
486 pImpl
->pBox
->EnableItem( GetId(), eState
!= SfxItemState::DISABLED
);
488 ToolBoxItemBits nItemBits
= pImpl
->pBox
->GetItemBits( GetId() );
489 nItemBits
&= ~ToolBoxItemBits::CHECKABLE
;
490 ::TriState eTri
= TRISTATE_FALSE
;
493 case SfxItemState::DEFAULT
:
496 if ( auto pBoolItem
= dynamic_cast< const SfxBoolItem
* >(pState
) )
498 // BoolItem for checking
499 if ( pBoolItem
->GetValue() )
500 eTri
= TRISTATE_TRUE
;
501 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
503 else if ( dynamic_cast< const SfxEnumItemInterface
*>( pState
) != nullptr &&
504 static_cast<const SfxEnumItemInterface
*>(pState
)->HasBoolValue())
506 // EnumItem is handled as Bool
507 if ( static_cast<const SfxEnumItemInterface
*>(pState
)->GetBoolValue() )
508 eTri
= TRISTATE_TRUE
;
509 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
511 else if ( pImpl
->bShowString
&& dynamic_cast< const SfxStringItem
*>( pState
) != nullptr )
512 pImpl
->pBox
->SetItemText(nId
, static_cast<const SfxStringItem
*>(pState
)->GetValue() );
516 case SfxItemState::DONTCARE
:
518 eTri
= TRISTATE_INDET
;
519 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
523 default: break; // do nothing
526 pImpl
->pBox
->SetItemState( GetId(), eTri
);
527 pImpl
->pBox
->SetItemBits( GetId(), nItemBits
);
531 void SfxToolBoxControl::Select( sal_uInt16 nSelectModifier
)
533 svt::ToolboxController::execute( nSelectModifier
);
537 void SfxToolBoxControl::DoubleClick()
542 void SfxToolBoxControl::Click()
546 void SfxToolBoxControl::CreatePopupWindow()
550 VclPtr
<InterimItemWindow
> SfxToolBoxControl::CreateItemWindow(vcl::Window
*)
552 return VclPtr
<InterimItemWindow
>();
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */