Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / toolbox / tbxitem.cxx
blob1240100e9daab18989d784587a0343214f74bea7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #ifdef __sun
22 #include <ctime>
23 #endif
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;
79 URL aTargetURL;
80 aTargetURL.Complete = aCommandURL;
81 Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
82 xTrans->parseStrict( aTargetURL );
83 if ( !aTargetURL.Arguments.isEmpty() )
84 return nullptr;
86 Reference < XController > xController;
87 Reference < XModel > xModel;
88 if ( rFrame.is() )
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;
99 if ( pModule )
100 pSlotPool = pModule->GetSlotPool();
101 else
102 pSlotPool = &(SfxSlotPool::GetSlotPool());
104 const SfxSlot* pSlot = pSlotPool->GetUnoSlot( aTargetURL.Path );
105 if ( pSlot )
107 sal_uInt16 nSlotId = pSlot->GetSlotId();
108 if ( nSlotId > 0 )
109 return SfxToolBoxControl::CreateControl( nSlotId, nID, pToolbox, pModule );
112 return nullptr;
115 struct SfxToolBoxControl_Impl
117 VclPtr<ToolBox> pBox;
118 bool bShowString;
119 sal_uInt16 nTbxId;
120 sal_uInt16 nSlotId;
123 SfxToolBoxControl::SfxToolBoxControl(
124 sal_uInt16 nSlotID,
125 sal_uInt16 nID,
126 ToolBox& rBox,
127 bool bShowStringItems )
128 : pImpl( new SfxToolBoxControl_Impl )
130 pImpl->pBox = &rBox;
131 pImpl->bShowString = bShowStringItems;
132 pImpl->nTbxId = nID;
133 pImpl->nSlotId = nSlotID;
137 SfxToolBoxControl::~SfxToolBoxControl()
142 ToolBox& SfxToolBoxControl::GetToolBox() const
144 return *pImpl->pBox;
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()
158 if ( m_bDisposed )
159 return;
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;
183 if ( pMod )
184 pSlotPool = pMod->GetSlotPool();
185 else
186 pSlotPool = &SfxSlotPool::GetSlotPool();
187 const std::type_info* aSlotType = pSlotPool->GetSlotType( nSlotId );
188 if ( aSlotType )
190 SfxToolBoxControl *pCtrl;
191 if ( pMod )
193 SfxTbxCtrlFactArr_Impl *pFactories = pMod->GetTbxCtrlFactories_Impl();
194 if ( pFactories )
196 SfxTbxCtrlFactArr_Impl &rFactories = *pFactories;
197 sal_uInt16 nFactory;
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) )
203 break;
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) )
211 break;
214 if( nFactory < nCount )
216 pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox );
217 return pCtrl;
222 SfxTbxCtrlFactArr_Impl &rFactories = pApp->GetTbxCtrlFactories_Impl();
223 sal_uInt16 nFactory;
224 const sal_uInt16 nCount = rFactories.size();
226 for( nFactory = 0; nFactory < nCount; ++nFactory )
227 if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == nSlotId) )
228 break;
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) )
236 break;
239 if( nFactory < nCount )
241 pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox );
242 return pCtrl;
246 return nullptr;
249 SfxItemState SfxToolBoxControl::GetItemState(
250 const SfxPoolItem* pState )
251 /* [Description]
253 Static method for determining the status of the SfxPoolItem-pointer,
254 used in the method <SfxControllerItem::StateChanged(const SfxPoolItem*)>.
256 [Return value]
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
266 if possible.
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.
279 return !pState
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 );
327 // XStatusListener
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 );
341 if ( xDisp.is() )
343 Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY );
344 SfxOfficeDispatch* pDisp = nullptr;
345 if ( xTunnel.is() )
347 sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
348 pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
351 if ( pDisp )
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 );
359 if ( pSlot )
360 nSlotId = pSlot->GetSlotId();
361 else if ( m_aCommandURL == rEvent.FeatureURL.Path )
362 nSlotId = GetSlotId();
364 if ( nSlotId <= 0 )
365 return;
367 if ( rEvent.Requery )
368 svt::ToolboxController::statusChanged( rEvent );
369 else
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() )
385 bool bTemp = false;
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() )
403 OUString sTemp ;
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");
417 eState = tmpState;
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 ));
426 else
428 if ( pSlot )
429 pItem = pSlot->GetType()->CreateItem();
430 if ( pItem )
432 pItem->SetWhich( nSlotId );
433 pItem->PutValue( rEvent.State, 0 );
435 else
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;
454 Click();
457 void SAL_CALL SfxToolBoxControl::doubleClick()
459 SolarMutexGuard aGuard;
460 DoubleClick();
463 Reference< css::awt::XWindow > SAL_CALL SfxToolBoxControl::createPopupWindow()
465 SolarMutexGuard aGuard;
466 CreatePopupWindow();
467 return nullptr;
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
478 sal_uInt16 nId,
479 SfxItemState eState,
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;
491 switch ( eState )
493 case SfxItemState::DEFAULT:
494 if ( pState )
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() );
514 break;
516 case SfxItemState::DONTCARE:
518 eTri = TRISTATE_INDET;
519 nItemBits |= ToolBoxItemBits::CHECKABLE;
521 break;
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: */