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 <sidebar/ControllerFactory.hxx>
60 #include <unoctitm.hxx>
61 #include <ctrlfactoryimpl.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::beans
;
65 using namespace ::com::sun::star::frame
;
66 using namespace ::com::sun::star::frame::status
;
67 using namespace ::com::sun::star::lang
;
68 using namespace ::com::sun::star::uno
;
69 using namespace ::com::sun::star::util
;
70 using namespace ::com::sun::star::container
;
71 using namespace ::com::sun::star::ui
;
74 SFX_IMPL_TOOLBOX_CONTROL_ARG(SfxToolBoxControl
, SfxStringItem
, true);
76 svt::ToolboxController
* SfxToolBoxControllerFactory( const Reference
< XFrame
>& rFrame
, ToolBox
* pToolbox
, unsigned short nID
, const OUString
& aCommandURL
)
78 SolarMutexGuard aGuard
;
81 aTargetURL
.Complete
= aCommandURL
;
82 Reference
< XURLTransformer
> xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
83 xTrans
->parseStrict( aTargetURL
);
84 if ( !aTargetURL
.Arguments
.isEmpty() )
87 Reference
< XController
> xController
;
88 Reference
< XModel
> xModel
;
91 xController
= rFrame
->getController();
92 if ( xController
.is() )
93 xModel
= xController
->getModel();
96 SfxObjectShell
* pObjShell
= SfxObjectShell::GetShellFromComponent(xModel
);
97 SfxModule
* pModule
= pObjShell
? pObjShell
->GetModule() : nullptr;
98 SfxSlotPool
* pSlotPool
= nullptr;
101 pSlotPool
= pModule
->GetSlotPool();
103 pSlotPool
= &(SfxSlotPool::GetSlotPool());
105 const SfxSlot
* pSlot
= pSlotPool
->GetUnoSlot( aTargetURL
.Path
);
108 sal_uInt16 nSlotId
= pSlot
->GetSlotId();
110 return SfxToolBoxControl::CreateControl( nSlotId
, nID
, pToolbox
, pModule
);
116 struct SfxToolBoxControl_Impl
118 VclPtr
<ToolBox
> pBox
;
124 SfxToolBoxControl::SfxToolBoxControl(
128 bool bShowStringItems
)
129 : pImpl( new SfxToolBoxControl_Impl
)
132 pImpl
->bShowString
= bShowStringItems
;
134 pImpl
->nSlotId
= nSlotID
;
138 SfxToolBoxControl::~SfxToolBoxControl()
143 ToolBox
& SfxToolBoxControl::GetToolBox() const
147 unsigned short SfxToolBoxControl::GetId() const
149 return pImpl
->nTbxId
;
151 unsigned short SfxToolBoxControl::GetSlotId() const
153 return pImpl
->nSlotId
;
157 void SAL_CALL
SfxToolBoxControl::dispose()
162 svt::ToolboxController::dispose();
164 // Remove and destroy our item window at our toolbox
165 SolarMutexGuard aGuard
;
166 VclPtr
< vcl::Window
> pWindow
= pImpl
->pBox
->GetItemWindow( pImpl
->nTbxId
);
167 pImpl
->pBox
->SetItemWindow( pImpl
->nTbxId
, nullptr );
168 pWindow
.disposeAndClear();
172 void SfxToolBoxControl::RegisterToolBoxControl( SfxModule
* pMod
, const SfxTbxCtrlFactory
& rFact
)
174 SfxGetpApp()->RegisterToolBoxControl_Impl( pMod
, rFact
);
177 SfxToolBoxControl
* SfxToolBoxControl::CreateControl( sal_uInt16 nSlotId
, sal_uInt16 nTbxId
, ToolBox
*pBox
, SfxModule
const * pMod
)
179 SolarMutexGuard aGuard
;
181 SfxApplication
*pApp
= SfxGetpApp();
183 SfxSlotPool
*pSlotPool
;
185 pSlotPool
= pMod
->GetSlotPool();
187 pSlotPool
= &SfxSlotPool::GetSlotPool();
188 const std::type_info
* aSlotType
= pSlotPool
->GetSlotType( nSlotId
);
191 SfxToolBoxControl
*pCtrl
;
194 SfxTbxCtrlFactArr_Impl
*pFactories
= pMod
->GetTbxCtrlFactories_Impl();
197 SfxTbxCtrlFactArr_Impl
&rFactories
= *pFactories
;
199 const sal_uInt16 nCount
= rFactories
.size();
201 // search for a factory with the given slot id
202 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
203 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== nSlotId
) )
206 if( nFactory
== nCount
)
208 // if no factory exists for the given slot id, see if we
209 // have a generic factory with the correct slot type and slot id == 0
210 for ( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
211 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== 0) )
215 if( nFactory
< nCount
)
217 pCtrl
= rFactories
[nFactory
].pCtor( nSlotId
, nTbxId
, *pBox
);
223 SfxTbxCtrlFactArr_Impl
&rFactories
= pApp
->GetTbxCtrlFactories_Impl();
225 const sal_uInt16 nCount
= rFactories
.size();
227 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
228 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== nSlotId
) )
231 if( nFactory
== nCount
)
233 // if no factory exists for the given slot id, see if we
234 // have a generic factory with the correct slot type and slot id == 0
235 for( nFactory
= 0; nFactory
< nCount
; ++nFactory
)
236 if( (rFactories
[nFactory
].nTypeId
== *aSlotType
) && (rFactories
[nFactory
].nSlotId
== 0) )
240 if( nFactory
< nCount
)
242 pCtrl
= rFactories
[nFactory
].pCtor( nSlotId
, nTbxId
, *pBox
);
250 SfxItemState
SfxToolBoxControl::GetItemState(
251 const SfxPoolItem
* pState
)
254 Static method for determining the status of the SfxPoolItem-pointer,
255 used in the method <SfxControllerItem::StateChanged(const SfxPoolItem*)>.
259 SfxItemState SfxItemState::UNKNOWN
260 Enabled, however no further status information is available.
261 Typical for <Slot>s, which are temporarily disabled a
262 anyway but other than that do not change their appearance.
264 SfxItemState::DISABLED
265 Disabled, no further status information is available.
266 All other displayed values should be reset to the default
269 SfxItemState::DONTCARE
270 Enabled but there were only ambiguous values available
271 (i.e. none that could be queried).
273 SfxItemState::DEFAULT
274 Enabled and with available values which can be queried
275 through'pState'. The type is thus by the Slot clearly
276 defined in the entire Program.
281 ? SfxItemState::DISABLED
282 : IsInvalidItem(pState
)
283 ? SfxItemState::DONTCARE
284 : pState
->IsVoidItem() && !pState
->Which()
285 ? SfxItemState::UNKNOWN
286 : SfxItemState::DEFAULT
;
289 void SfxToolBoxControl::Dispatch(
290 const Reference
< XDispatchProvider
>& rProvider
,
291 const OUString
& rCommand
,
292 Sequence
< ::PropertyValue
> const & aArgs
)
294 if ( rProvider
.is() )
296 css::util::URL aTargetURL
;
297 aTargetURL
.Complete
= rCommand
;
298 Reference
< XURLTransformer
> xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
299 xTrans
->parseStrict( aTargetURL
);
301 Reference
< XDispatch
> xDispatch
= rProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
302 if ( xDispatch
.is() )
303 xDispatch
->dispatch( aTargetURL
, aArgs
);
307 void SfxToolBoxControl::Dispatch( const OUString
& aCommand
, css::uno::Sequence
< css::beans::PropertyValue
> const & aArgs
)
309 Reference
< XController
> xController
;
311 SolarMutexGuard aGuard
;
312 if ( getFrameInterface().is() )
313 xController
= getFrameInterface()->getController();
315 Reference
< XDispatchProvider
> xProvider( xController
, UNO_QUERY
);
316 if ( xProvider
.is() )
318 css::util::URL aTargetURL
;
319 aTargetURL
.Complete
= aCommand
;
320 getURLTransformer()->parseStrict( aTargetURL
);
322 Reference
< XDispatch
> xDispatch
= xProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
323 if ( xDispatch
.is() )
324 xDispatch
->dispatch( aTargetURL
, aArgs
);
329 void SAL_CALL
SfxToolBoxControl::statusChanged( const FeatureStateEvent
& rEvent
)
331 SfxViewFrame
* pViewFrame
= nullptr;
332 Reference
< XController
> xController
;
334 SolarMutexGuard aGuard
;
335 if ( getFrameInterface().is() )
336 xController
= getFrameInterface()->getController();
338 Reference
< XDispatchProvider
> xProvider( xController
, UNO_QUERY
);
339 if ( xProvider
.is() )
341 Reference
< XDispatch
> xDisp
= xProvider
->queryDispatch( rEvent
.FeatureURL
, OUString(), 0 );
344 Reference
< XUnoTunnel
> xTunnel( xDisp
, UNO_QUERY
);
345 SfxOfficeDispatch
* pDisp
= nullptr;
348 sal_Int64 nImplementation
= xTunnel
->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
349 pDisp
= reinterpret_cast< SfxOfficeDispatch
* >( sal::static_int_cast
< sal_IntPtr
>( nImplementation
));
353 pViewFrame
= pDisp
->GetDispatcher_Impl()->GetFrame();
357 sal_uInt16 nSlotId
= 0;
358 SfxSlotPool
& rPool
= SfxSlotPool::GetSlotPool( pViewFrame
);
359 const SfxSlot
* pSlot
= rPool
.GetUnoSlot( rEvent
.FeatureURL
.Path
);
361 nSlotId
= pSlot
->GetSlotId();
362 else if ( m_aCommandURL
== rEvent
.FeatureURL
.Path
)
363 nSlotId
= GetSlotId();
368 if ( rEvent
.Requery
)
369 svt::ToolboxController::statusChanged( rEvent
);
372 SfxItemState eState
= SfxItemState::DISABLED
;
373 std::unique_ptr
<SfxPoolItem
> pItem
;
374 if ( rEvent
.IsEnabled
)
376 eState
= SfxItemState::DEFAULT
;
377 css::uno::Type aType
= rEvent
.State
.getValueType();
379 if ( aType
== cppu::UnoType
<void>::get() )
381 pItem
.reset(new SfxVoidItem( nSlotId
));
382 eState
= SfxItemState::UNKNOWN
;
384 else if ( aType
== cppu::UnoType
<bool>::get() )
387 rEvent
.State
>>= bTemp
;
388 pItem
.reset(new SfxBoolItem( nSlotId
, bTemp
));
390 else if ( aType
== ::cppu::UnoType
< ::cppu::UnoUnsignedShortType
>::get())
392 sal_uInt16 nTemp
= 0;
393 rEvent
.State
>>= nTemp
;
394 pItem
.reset(new SfxUInt16Item( nSlotId
, nTemp
));
396 else if ( aType
== cppu::UnoType
<sal_uInt32
>::get() )
398 sal_uInt32 nTemp
= 0;
399 rEvent
.State
>>= nTemp
;
400 pItem
.reset(new SfxUInt32Item( nSlotId
, nTemp
));
402 else if ( aType
== cppu::UnoType
<OUString
>::get() )
405 rEvent
.State
>>= sTemp
;
406 pItem
.reset(new SfxStringItem( nSlotId
, sTemp
));
408 else if ( aType
== cppu::UnoType
< css::frame::status::ItemStatus
>::get() )
410 ItemStatus aItemStatus
;
411 rEvent
.State
>>= aItemStatus
;
412 SfxItemState tmpState
= static_cast<SfxItemState
>(aItemStatus
.State
);
413 // make sure no-one tries to send us a combination of states
414 if (tmpState
!= SfxItemState::UNKNOWN
&& tmpState
!= SfxItemState::DISABLED
&&
415 tmpState
!= SfxItemState::READONLY
&& tmpState
!= SfxItemState::DONTCARE
&&
416 tmpState
!= SfxItemState::DEFAULT
&& tmpState
!= SfxItemState::SET
)
417 throw css::uno::RuntimeException("unknown status");
419 pItem
.reset(new SfxVoidItem( nSlotId
));
421 else if ( aType
== cppu::UnoType
< css::frame::status::Visibility
>::get() )
423 Visibility aVisibilityStatus
;
424 rEvent
.State
>>= aVisibilityStatus
;
425 pItem
.reset(new SfxVisibilityItem( nSlotId
, aVisibilityStatus
.bVisible
));
430 pItem
= pSlot
->GetType()->CreateItem();
433 pItem
->SetWhich( nSlotId
);
434 pItem
->PutValue( rEvent
.State
, 0 );
437 pItem
.reset(new SfxVoidItem( nSlotId
));
441 StateChanged( nSlotId
, eState
, pItem
.get() );
445 // XToolbarController
446 void SAL_CALL
SfxToolBoxControl::execute( sal_Int16 KeyModifier
)
448 SolarMutexGuard aGuard
;
449 Select( static_cast<sal_uInt16
>(KeyModifier
) );
452 void SAL_CALL
SfxToolBoxControl::click()
454 SolarMutexGuard aGuard
;
458 void SAL_CALL
SfxToolBoxControl::doubleClick()
460 SolarMutexGuard aGuard
;
464 Reference
< css::awt::XWindow
> SAL_CALL
SfxToolBoxControl::createPopupWindow()
466 SolarMutexGuard aGuard
;
471 Reference
< css::awt::XWindow
> SAL_CALL
SfxToolBoxControl::createItemWindow( const Reference
< css::awt::XWindow
>& rParent
)
473 SolarMutexGuard aGuard
;
474 return VCLUnoHelper::GetInterface( CreateItemWindow( VCLUnoHelper::GetWindow( rParent
)));
477 void SfxToolBoxControl::StateChanged
481 const SfxPoolItem
* pState
484 DBG_ASSERT( pImpl
->pBox
!= nullptr, "setting state to dangling ToolBox" );
486 // enabled/disabled-Flag correcting the lump sum
487 pImpl
->pBox
->EnableItem( GetId(), eState
!= SfxItemState::DISABLED
);
489 ToolBoxItemBits nItemBits
= pImpl
->pBox
->GetItemBits( GetId() );
490 nItemBits
&= ~ToolBoxItemBits::CHECKABLE
;
491 ::TriState eTri
= TRISTATE_FALSE
;
494 case SfxItemState::DEFAULT
:
497 if ( auto pBoolItem
= dynamic_cast< const SfxBoolItem
* >(pState
) )
499 // BoolItem for checking
500 if ( pBoolItem
->GetValue() )
501 eTri
= TRISTATE_TRUE
;
502 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
504 else if ( dynamic_cast< const SfxEnumItemInterface
*>( pState
) != nullptr &&
505 static_cast<const SfxEnumItemInterface
*>(pState
)->HasBoolValue())
507 // EnumItem is handled as Bool
508 if ( static_cast<const SfxEnumItemInterface
*>(pState
)->GetBoolValue() )
509 eTri
= TRISTATE_TRUE
;
510 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
512 else if ( pImpl
->bShowString
&& dynamic_cast< const SfxStringItem
*>( pState
) != nullptr )
513 pImpl
->pBox
->SetItemText(nId
, static_cast<const SfxStringItem
*>(pState
)->GetValue() );
517 case SfxItemState::DONTCARE
:
519 eTri
= TRISTATE_INDET
;
520 nItemBits
|= ToolBoxItemBits::CHECKABLE
;
524 default: break; // do nothing
527 pImpl
->pBox
->SetItemState( GetId(), eTri
);
528 pImpl
->pBox
->SetItemBits( GetId(), nItemBits
);
532 void SfxToolBoxControl::Select( sal_uInt16 nSelectModifier
)
534 svt::ToolboxController::execute( nSelectModifier
);
538 void SfxToolBoxControl::DoubleClick()
543 void SfxToolBoxControl::Click()
547 void SfxToolBoxControl::CreatePopupWindow()
551 VclPtr
<InterimItemWindow
> SfxToolBoxControl::CreateItemWindow(vcl::Window
*)
553 return VclPtr
<InterimItemWindow
>();
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */