diff options
Diffstat (limited to 'sfx2/source/toolbox/tbxitem.cxx')
-rw-r--r-- | sfx2/source/toolbox/tbxitem.cxx | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/sfx2/source/toolbox/tbxitem.cxx b/sfx2/source/toolbox/tbxitem.cxx new file mode 100644 index 000000000..0559ac646 --- /dev/null +++ b/sfx2/source/toolbox/tbxitem.cxx @@ -0,0 +1,569 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#ifdef __sun +#include <ctime> +#endif + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/status/ItemStatus.hpp> +#include <com/sun/star/ui/XUIElementFactory.hpp> +#include <com/sun/star/frame/status/Visibility.hpp> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <svl/visitem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> + +#include <svtools/framestatuslistener.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/taskpanelist.hxx> +#include <vcl/event.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/globname.hxx> + +#include <vcl/InterimItemWindow.hxx> +#include <sfx2/tbxctrl.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/module.hxx> +#include <sfx2/app.hxx> +#include <unoctitm.hxx> +#include <ctrlfactoryimpl.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame::status; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ui; + + +SFX_IMPL_TOOLBOX_CONTROL_ARG(SfxToolBoxControl, SfxStringItem, true); + +svt::ToolboxController* SfxToolBoxControllerFactory( const Reference< XFrame >& rFrame, ToolBox* pToolbox, unsigned short nID, const OUString& aCommandURL ) +{ + SolarMutexGuard aGuard; + + URL aTargetURL; + aTargetURL.Complete = aCommandURL; + Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) ); + xTrans->parseStrict( aTargetURL ); + if ( !aTargetURL.Arguments.isEmpty() ) + return nullptr; + + SfxObjectShell* pObjShell = nullptr; + Reference < XController > xController; + Reference < XModel > xModel; + if ( rFrame.is() ) + { + xController = rFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + } + + if ( xModel.is() ) + { + // Get tunnel from model to retrieve the SfxObjectShell pointer from it + css::uno::Reference < css::lang::XUnoTunnel > xObj( xModel, UNO_QUERY ); + if ( xObj.is() ) + { + css::uno::Sequence < sal_Int8 > aSeq = SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence(); + sal_Int64 nHandle = xObj->getSomething( aSeq ); + if ( nHandle ) + pObjShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle )); + } + } + + SfxModule* pModule = pObjShell ? pObjShell->GetModule() : nullptr; + SfxSlotPool* pSlotPool = nullptr; + + if ( pModule ) + pSlotPool = pModule->GetSlotPool(); + else + pSlotPool = &(SfxSlotPool::GetSlotPool()); + + const SfxSlot* pSlot = pSlotPool->GetUnoSlot( aTargetURL.Path ); + if ( pSlot ) + { + sal_uInt16 nSlotId = pSlot->GetSlotId(); + if ( nSlotId > 0 ) + return SfxToolBoxControl::CreateControl( nSlotId, nID, pToolbox, pModule ); + } + + return nullptr; +} + +struct SfxToolBoxControl_Impl +{ + VclPtr<ToolBox> pBox; + bool bShowString; + sal_uInt16 nTbxId; + sal_uInt16 nSlotId; +}; + +SfxToolBoxControl::SfxToolBoxControl( + sal_uInt16 nSlotID, + sal_uInt16 nID, + ToolBox& rBox, + bool bShowStringItems ) + : pImpl( new SfxToolBoxControl_Impl ) +{ + pImpl->pBox = &rBox; + pImpl->bShowString = bShowStringItems; + pImpl->nTbxId = nID; + pImpl->nSlotId = nSlotID; +} + + +SfxToolBoxControl::~SfxToolBoxControl() +{ +} + + +ToolBox& SfxToolBoxControl::GetToolBox() const +{ + return *pImpl->pBox; +} +unsigned short SfxToolBoxControl::GetId() const +{ + return pImpl->nTbxId; +} +unsigned short SfxToolBoxControl::GetSlotId() const +{ + return pImpl->nSlotId; +} + + +void SAL_CALL SfxToolBoxControl::dispose() +{ + if ( m_bDisposed ) + return; + + svt::ToolboxController::dispose(); + + // Remove and destroy our item window at our toolbox + SolarMutexGuard aGuard; + VclPtr< vcl::Window > pWindow = pImpl->pBox->GetItemWindow( pImpl->nTbxId ); + pImpl->pBox->SetItemWindow( pImpl->nTbxId, nullptr ); + pWindow.disposeAndClear(); +} + + +void SfxToolBoxControl::RegisterToolBoxControl( SfxModule* pMod, const SfxTbxCtrlFactory& rFact) +{ + SfxGetpApp()->RegisterToolBoxControl_Impl( pMod, rFact ); +} + +SfxToolBoxControl* SfxToolBoxControl::CreateControl( sal_uInt16 nSlotId, sal_uInt16 nTbxId, ToolBox *pBox, SfxModule const * pMod ) +{ + SolarMutexGuard aGuard; + + SfxApplication *pApp = SfxGetpApp(); + + SfxSlotPool *pSlotPool; + if ( pMod ) + pSlotPool = pMod->GetSlotPool(); + else + pSlotPool = &SfxSlotPool::GetSlotPool(); + const std::type_info* aSlotType = pSlotPool->GetSlotType( nSlotId ); + if ( aSlotType ) + { + SfxToolBoxControl *pCtrl; + if ( pMod ) + { + SfxTbxCtrlFactArr_Impl *pFactories = pMod->GetTbxCtrlFactories_Impl(); + if ( pFactories ) + { + SfxTbxCtrlFactArr_Impl &rFactories = *pFactories; + sal_uInt16 nFactory; + const sal_uInt16 nCount = rFactories.size(); + + // search for a factory with the given slot id + for( nFactory = 0; nFactory < nCount; ++nFactory ) + if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == nSlotId) ) + break; + + if( nFactory == nCount ) + { + // if no factory exists for the given slot id, see if we + // have a generic factory with the correct slot type and slot id == 0 + for ( nFactory = 0; nFactory < nCount; ++nFactory ) + if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == 0) ) + break; + } + + if( nFactory < nCount ) + { + pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox ); + return pCtrl; + } + } + } + + SfxTbxCtrlFactArr_Impl &rFactories = pApp->GetTbxCtrlFactories_Impl(); + sal_uInt16 nFactory; + const sal_uInt16 nCount = rFactories.size(); + + for( nFactory = 0; nFactory < nCount; ++nFactory ) + if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == nSlotId) ) + break; + + if( nFactory == nCount ) + { + // if no factory exists for the given slot id, see if we + // have a generic factory with the correct slot type and slot id == 0 + for( nFactory = 0; nFactory < nCount; ++nFactory ) + if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == 0) ) + break; + } + + if( nFactory < nCount ) + { + pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox ); + return pCtrl; + } + } + + return nullptr; +} + +SfxItemState SfxToolBoxControl::GetItemState( + const SfxPoolItem* pState ) +/* [Description] + + Static method for determining the status of the SfxPoolItem-pointer, + used in the method <SfxControllerItem::StateChanged(const SfxPoolItem*)>. + + [Return value] + + SfxItemState SfxItemState::UNKNOWN + Enabled, however no further status information is available. + Typical for <Slot>s, which are temporarily disabled a + anyway but other than that do not change their appearance. + + SfxItemState::DISABLED + Disabled, no further status information is available. + All other displayed values should be reset to the default + if possible. + + SfxItemState::DONTCARE + Enabled but there were only ambiguous values available + (i.e. none that could be queried). + + SfxItemState::DEFAULT + Enabled and with available values which can be queried + through'pState'. The type is thus by the Slot clearly + defined in the entire Program. +*/ + +{ + return !pState + ? SfxItemState::DISABLED + : IsInvalidItem(pState) + ? SfxItemState::DONTCARE + : pState->IsVoidItem() && !pState->Which() + ? SfxItemState::UNKNOWN + : SfxItemState::DEFAULT; +} + +void SfxToolBoxControl::Dispatch( + const Reference< XDispatchProvider >& rProvider, + const OUString& rCommand, + Sequence< ::PropertyValue > const & aArgs ) +{ + if ( rProvider.is() ) + { + css::util::URL aTargetURL; + aTargetURL.Complete = rCommand; + Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) ); + xTrans->parseStrict( aTargetURL ); + + Reference < XDispatch > xDispatch = rProvider->queryDispatch( aTargetURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aTargetURL, aArgs ); + } +} + +void SfxToolBoxControl::Dispatch( const OUString& aCommand, css::uno::Sequence< css::beans::PropertyValue > const & aArgs ) +{ + Reference < XController > xController; + + SolarMutexGuard aGuard; + if ( getFrameInterface().is() ) + xController = getFrameInterface()->getController(); + + Reference < XDispatchProvider > xProvider( xController, UNO_QUERY ); + if ( xProvider.is() ) + { + css::util::URL aTargetURL; + aTargetURL.Complete = aCommand; + getURLTransformer()->parseStrict( aTargetURL ); + + Reference < XDispatch > xDispatch = xProvider->queryDispatch( aTargetURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aTargetURL, aArgs ); + } +} + +// XStatusListener +void SAL_CALL SfxToolBoxControl::statusChanged( const FeatureStateEvent& rEvent ) +{ + SfxViewFrame* pViewFrame = nullptr; + Reference < XController > xController; + + SolarMutexGuard aGuard; + if ( getFrameInterface().is() ) + xController = getFrameInterface()->getController(); + + Reference < XDispatchProvider > xProvider( xController, UNO_QUERY ); + if ( xProvider.is() ) + { + Reference < XDispatch > xDisp = xProvider->queryDispatch( rEvent.FeatureURL, OUString(), 0 ); + if ( xDisp.is() ) + { + Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY ); + SfxOfficeDispatch* pDisp = nullptr; + if ( xTunnel.is() ) + { + sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier()); + pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation )); + } + + if ( pDisp ) + pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame(); + } + } + + sal_uInt16 nSlotId = 0; + SfxSlotPool& rPool = SfxSlotPool::GetSlotPool( pViewFrame ); + const SfxSlot* pSlot = rPool.GetUnoSlot( rEvent.FeatureURL.Path ); + if ( pSlot ) + nSlotId = pSlot->GetSlotId(); + else if ( m_aCommandURL == rEvent.FeatureURL.Path ) + nSlotId = GetSlotId(); + + if ( nSlotId <= 0 ) + return; + + if ( rEvent.Requery ) + svt::ToolboxController::statusChanged( rEvent ); + else + { + SfxItemState eState = SfxItemState::DISABLED; + std::unique_ptr<SfxPoolItem> pItem; + if ( rEvent.IsEnabled ) + { + eState = SfxItemState::DEFAULT; + css::uno::Type aType = rEvent.State.getValueType(); + + if ( aType == cppu::UnoType<void>::get() ) + { + pItem.reset(new SfxVoidItem( nSlotId )); + eState = SfxItemState::UNKNOWN; + } + else if ( aType == cppu::UnoType<bool>::get() ) + { + bool bTemp = false; + rEvent.State >>= bTemp ; + pItem.reset(new SfxBoolItem( nSlotId, bTemp )); + } + else if ( aType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get()) + { + sal_uInt16 nTemp = 0; + rEvent.State >>= nTemp ; + pItem.reset(new SfxUInt16Item( nSlotId, nTemp )); + } + else if ( aType == cppu::UnoType<sal_uInt32>::get() ) + { + sal_uInt32 nTemp = 0; + rEvent.State >>= nTemp ; + pItem.reset(new SfxUInt32Item( nSlotId, nTemp )); + } + else if ( aType == cppu::UnoType<OUString>::get() ) + { + OUString sTemp ; + rEvent.State >>= sTemp ; + pItem.reset(new SfxStringItem( nSlotId, sTemp )); + } + else if ( aType == cppu::UnoType< css::frame::status::ItemStatus>::get() ) + { + ItemStatus aItemStatus; + rEvent.State >>= aItemStatus; + SfxItemState tmpState = static_cast<SfxItemState>(aItemStatus.State); + // make sure no-one tries to send us a combination of states + if (tmpState != SfxItemState::UNKNOWN && tmpState != SfxItemState::DISABLED && + tmpState != SfxItemState::READONLY && tmpState != SfxItemState::DONTCARE && + tmpState != SfxItemState::DEFAULT && tmpState != SfxItemState::SET) + throw css::uno::RuntimeException("unknown status"); + eState = tmpState; + pItem.reset(new SfxVoidItem( nSlotId )); + } + else if ( aType == cppu::UnoType< css::frame::status::Visibility>::get() ) + { + Visibility aVisibilityStatus; + rEvent.State >>= aVisibilityStatus; + pItem.reset(new SfxVisibilityItem( nSlotId, aVisibilityStatus.bVisible )); + } + else + { + if ( pSlot ) + pItem = pSlot->GetType()->CreateItem(); + if ( pItem ) + { + pItem->SetWhich( nSlotId ); + pItem->PutValue( rEvent.State, 0 ); + } + else + pItem.reset(new SfxVoidItem( nSlotId )); + } + } + + StateChanged( nSlotId, eState, pItem.get() ); + } +} + +// XToolbarController +void SAL_CALL SfxToolBoxControl::execute( sal_Int16 KeyModifier ) +{ + SolarMutexGuard aGuard; + Select( static_cast<sal_uInt16>(KeyModifier) ); +} + +void SAL_CALL SfxToolBoxControl::click() +{ + SolarMutexGuard aGuard; + Click(); +} + +void SAL_CALL SfxToolBoxControl::doubleClick() +{ + SolarMutexGuard aGuard; + DoubleClick(); +} + +Reference< css::awt::XWindow > SAL_CALL SfxToolBoxControl::createPopupWindow() +{ + SolarMutexGuard aGuard; + CreatePopupWindow(); + return nullptr; +} + +Reference< css::awt::XWindow > SAL_CALL SfxToolBoxControl::createItemWindow( const Reference< css::awt::XWindow >& rParent ) +{ + SolarMutexGuard aGuard; + return VCLUnoHelper::GetInterface( CreateItemWindow( VCLUnoHelper::GetWindow( rParent ))); +} + +void SfxToolBoxControl::StateChanged +( + sal_uInt16 nId, + SfxItemState eState, + const SfxPoolItem* pState +) +{ + DBG_ASSERT( pImpl->pBox != nullptr, "setting state to dangling ToolBox" ); + + // enabled/disabled-Flag correcting the lump sum + pImpl->pBox->EnableItem( GetId(), eState != SfxItemState::DISABLED ); + + ToolBoxItemBits nItemBits = pImpl->pBox->GetItemBits( GetId() ); + nItemBits &= ~ToolBoxItemBits::CHECKABLE; + ::TriState eTri = TRISTATE_FALSE; + switch ( eState ) + { + case SfxItemState::DEFAULT: + if ( pState ) + { + if ( auto pBoolItem = dynamic_cast< const SfxBoolItem* >(pState) ) + { + // BoolItem for checking + if ( pBoolItem->GetValue() ) + eTri = TRISTATE_TRUE; + nItemBits |= ToolBoxItemBits::CHECKABLE; + } + else if ( dynamic_cast< const SfxEnumItemInterface *>( pState ) != nullptr && + static_cast<const SfxEnumItemInterface *>(pState)->HasBoolValue()) + { + // EnumItem is handled as Bool + if ( static_cast<const SfxEnumItemInterface *>(pState)->GetBoolValue() ) + eTri = TRISTATE_TRUE; + nItemBits |= ToolBoxItemBits::CHECKABLE; + } + else if ( pImpl->bShowString && dynamic_cast< const SfxStringItem *>( pState ) != nullptr ) + pImpl->pBox->SetItemText(nId, static_cast<const SfxStringItem*>(pState)->GetValue() ); + } + break; + + case SfxItemState::DONTCARE: + { + eTri = TRISTATE_INDET; + nItemBits |= ToolBoxItemBits::CHECKABLE; + } + break; + + default: break; // do nothing + } + + pImpl->pBox->SetItemState( GetId(), eTri ); + pImpl->pBox->SetItemBits( GetId(), nItemBits ); +} + + +void SfxToolBoxControl::Select( sal_uInt16 nSelectModifier ) +{ + svt::ToolboxController::execute( nSelectModifier ); +} + + +void SfxToolBoxControl::DoubleClick() +{ +} + + +void SfxToolBoxControl::Click() +{ +} + +void SfxToolBoxControl::CreatePopupWindow() +{ +} + +VclPtr<InterimItemWindow> SfxToolBoxControl::CreateItemWindow(vcl::Window*) +{ + return VclPtr<InterimItemWindow>(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |