diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /forms/source/helper | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'forms/source/helper')
-rw-r--r-- | forms/source/helper/commandimageprovider.cxx | 133 | ||||
-rw-r--r-- | forms/source/helper/controlfeatureinterception.cxx | 147 | ||||
-rw-r--r-- | forms/source/helper/formnavigation.cxx | 447 | ||||
-rw-r--r-- | forms/source/helper/resettable.cxx | 79 | ||||
-rw-r--r-- | forms/source/helper/urltransformer.cxx | 83 | ||||
-rw-r--r-- | forms/source/helper/windowstateguard.cxx | 213 |
6 files changed, 1102 insertions, 0 deletions
diff --git a/forms/source/helper/commandimageprovider.cxx b/forms/source/helper/commandimageprovider.cxx new file mode 100644 index 000000000..ca2d70525 --- /dev/null +++ b/forms/source/helper/commandimageprovider.cxx @@ -0,0 +1,133 @@ +/* -*- 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 . + */ + + +#include <commandimageprovider.hxx> + +#include <com/sun/star/ui/XImageManager.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/ui/ImageType.hpp> + +#include <tools/diagnose_ex.h> + + +namespace frm +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::ui::XImageManager; + using ::com::sun::star::ui::XUIConfigurationManagerSupplier; + using ::com::sun::star::ui::XUIConfigurationManager; + using ::com::sun::star::ui::XModuleUIConfigurationManagerSupplier; + using ::com::sun::star::ui::theModuleUIConfigurationManagerSupplier; + using ::com::sun::star::frame::ModuleManager; + using ::com::sun::star::frame::XModuleManager2; + using ::com::sun::star::graphic::XGraphic; + + namespace ImageType = ::com::sun::star::ui::ImageType; + + DocumentCommandImageProvider::DocumentCommandImageProvider( const Reference<XComponentContext>& _rContext, const Reference< XModel >& _rxDocument ) + { + OSL_ENSURE( _rxDocument.is(), "DocumentCommandImageProvider::impl_init_nothrow: no document => no images!" ); + if ( !_rxDocument.is() ) + return; + + // obtain the image manager of the document + try + { + Reference< XUIConfigurationManagerSupplier > xSuppUIConfig( _rxDocument, UNO_QUERY_THROW ); + Reference< XUIConfigurationManager > xUIConfig = xSuppUIConfig->getUIConfigurationManager(); + m_xDocumentImageManager.set( xUIConfig->getImageManager(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("forms.helper"); + } + + // obtain the image manager or the module + try + { + Reference< XModuleManager2 > xModuleManager( ModuleManager::create(_rContext) ); + OUString sModuleID = xModuleManager->identify( _rxDocument ); + + Reference< XModuleUIConfigurationManagerSupplier > xSuppUIConfig( + theModuleUIConfigurationManagerSupplier::get(_rContext) ); + Reference< XUIConfigurationManager > xUIConfig( + xSuppUIConfig->getUIConfigurationManager( sModuleID ), UNO_SET_THROW ); + m_xModuleImageManager.set( xUIConfig->getImageManager(), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("forms.helper"); + } + } + + + std::vector<Image> DocumentCommandImageProvider::getCommandImages( const css::uno::Sequence< OUString >& _rCommandURLs, const bool _bLarge ) const + { + const size_t nCommandCount = _rCommandURLs.getLength(); + std::vector<Image> aImages( nCommandCount ); + try + { + const sal_Int16 nImageType = ImageType::COLOR_NORMAL + + ( _bLarge ? ImageType::SIZE_LARGE : ImageType::SIZE_DEFAULT ); + + Sequence< Reference< XGraphic > > aDocImages( nCommandCount ); + Sequence< Reference< XGraphic > > aModImages( nCommandCount ); + + // first try the document image manager + if ( m_xDocumentImageManager.is() ) + aDocImages = m_xDocumentImageManager->getImages( nImageType, _rCommandURLs ); + + // then the module's image manager + if ( m_xModuleImageManager.is() ) + aModImages = m_xModuleImageManager->getImages( nImageType, _rCommandURLs ); + + ENSURE_OR_THROW( static_cast<size_t>(aDocImages.getLength()) == nCommandCount, "illegal array size returned by getImages (document image manager)" ); + ENSURE_OR_THROW( static_cast<size_t>(aModImages.getLength()) == nCommandCount, "illegal array size returned by getImages (module image manager)" ); + + for ( size_t i=0; i<nCommandCount; ++i ) + { + if ( aDocImages[i].is() ) + aImages[i] = Image( aDocImages[i] ); + else + aImages[i] = Image( aModImages[i] ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("forms.helper"); + } + return aImages; + } + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/helper/controlfeatureinterception.cxx b/forms/source/helper/controlfeatureinterception.cxx new file mode 100644 index 000000000..091af550c --- /dev/null +++ b/forms/source/helper/controlfeatureinterception.cxx @@ -0,0 +1,147 @@ +/* -*- 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 . + */ + +#include <controlfeatureinterception.hxx> +#include <urltransformer.hxx> +#include <osl/diagnose.h> + + +namespace frm +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + ControlFeatureInterception::ControlFeatureInterception( const Reference< XComponentContext >& _rxORB ) + :m_pUrlTransformer( new UrlTransformer( _rxORB ) ) + { + } + + + void ControlFeatureInterception::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) + { + if ( !_rxInterceptor.is() ) + { + OSL_FAIL( "ControlFeatureInterception::registerDispatchProviderInterceptor: invalid interceptor!" ); + return; + } + + if ( m_xFirstDispatchInterceptor.is() ) + { + // there is already an interceptor; the new one will become its master + _rxInterceptor->setSlaveDispatchProvider( m_xFirstDispatchInterceptor ); + m_xFirstDispatchInterceptor->setMasterDispatchProvider( m_xFirstDispatchInterceptor ); + } + + // we are the master of the chain's first interceptor + m_xFirstDispatchInterceptor = _rxInterceptor; + m_xFirstDispatchInterceptor->setMasterDispatchProvider( nullptr ); + // it's the first of the interceptor chain + } + + + void ControlFeatureInterception::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) + { + if ( !_rxInterceptor.is() ) + { + OSL_FAIL( "ControlFeatureInterception::releaseDispatchProviderInterceptor: invalid interceptor!" ); + return; + } + + Reference< XDispatchProviderInterceptor > xChainWalk( m_xFirstDispatchInterceptor ); + + if ( m_xFirstDispatchInterceptor == _rxInterceptor ) + { // our chain will have a new first element + Reference< XDispatchProviderInterceptor > xSlave( m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY ); + m_xFirstDispatchInterceptor = xSlave; + } + // do this before removing the interceptor from the chain as we won't know it's slave afterwards) + + while ( xChainWalk.is() ) + { + // walk along the chain of interceptors and look for the interceptor that has to be removed + Reference< XDispatchProviderInterceptor > xSlave( xChainWalk->getSlaveDispatchProvider(), UNO_QUERY ); + + if ( xChainWalk == _rxInterceptor ) + { + // old master may be an interceptor too + Reference< XDispatchProviderInterceptor > xMaster( xChainWalk->getMasterDispatchProvider(), UNO_QUERY ); + + // unchain the interceptor that has to be removed + xChainWalk->setSlaveDispatchProvider( nullptr ); + xChainWalk->setMasterDispatchProvider( nullptr ); + + // reconnect the chain + if ( xMaster.is() ) + { + xMaster->setSlaveDispatchProvider( xSlave ); + } + + // if somebody has registered the same interceptor twice, then we will remove + // it once per call ... + break; + } + + xChainWalk = xSlave; + } + } + + + void ControlFeatureInterception::dispose() + { + // release all interceptors + Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor ); + m_xFirstDispatchInterceptor.clear(); + while ( xInterceptor.is() ) + { + // tell the interceptor it has a new (means no) predecessor + xInterceptor->setMasterDispatchProvider( nullptr ); + + // ask for its successor + Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider(); + // and give it the new (means no) successoert + xInterceptor->setSlaveDispatchProvider( nullptr ); + + // start over with the next chain element + xInterceptor.set(xSlave, css::uno::UNO_QUERY); + } + } + + Reference< XDispatch > ControlFeatureInterception::queryDispatch( const URL& _rURL ) + { + Reference< XDispatch > xDispatcher; + if ( m_xFirstDispatchInterceptor.is() ) + xDispatcher = m_xFirstDispatchInterceptor->queryDispatch( _rURL, OUString(), 0 ); + return xDispatcher; + } + + + Reference< XDispatch > ControlFeatureInterception::queryDispatch( const char* _pAsciiURL ) + { + return queryDispatch( m_pUrlTransformer->getStrictURLFromAscii( _pAsciiURL ) ); + } + + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/helper/formnavigation.cxx b/forms/source/helper/formnavigation.cxx new file mode 100644 index 000000000..a99f29b24 --- /dev/null +++ b/forms/source/helper/formnavigation.cxx @@ -0,0 +1,447 @@ +/* -*- 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 . + */ + +#include <formnavigation.hxx> +#include <urltransformer.hxx> +#include <controlfeatureinterception.hxx> +#include <frm_strings.hxx> + +#include <com/sun/star/form/runtime/FormFeature.hpp> + +#include <comphelper/propertyvalue.hxx> +#include <tools/debug.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + + +namespace frm +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::frame; + namespace FormFeature = ::com::sun::star::form::runtime::FormFeature; + + OFormNavigationHelper::OFormNavigationHelper( const Reference< XComponentContext >& _rxORB ) + :m_xORB( _rxORB ) + ,m_nConnectedFeatures( 0 ) + { + m_pFeatureInterception.reset( new ControlFeatureInterception( m_xORB ) ); + } + + + OFormNavigationHelper::~OFormNavigationHelper() + { + } + + + void OFormNavigationHelper::dispose( ) + { + m_pFeatureInterception->dispose(); + disconnectDispatchers(); + } + + + void OFormNavigationHelper::interceptorsChanged( ) + { + updateDispatches(); + } + + + void OFormNavigationHelper::featureStateChanged( sal_Int16 /*_nFeatureId*/, bool /*_bEnabled*/ ) + { + // not interested in + } + + + void OFormNavigationHelper::allFeatureStatesChanged( ) + { + // not interested in + } + + + void SAL_CALL OFormNavigationHelper::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) + { + m_pFeatureInterception->registerDispatchProviderInterceptor( _rxInterceptor ); + interceptorsChanged(); + } + + + void SAL_CALL OFormNavigationHelper::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) + { + m_pFeatureInterception->releaseDispatchProviderInterceptor( _rxInterceptor ); + interceptorsChanged(); + } + + + void SAL_CALL OFormNavigationHelper::statusChanged( const FeatureStateEvent& _rState ) + { + for (auto & feature : m_aSupportedFeatures) + { + if ( feature.second.aURL.Main == _rState.FeatureURL.Main ) + { + if ( ( feature.second.bCachedState != bool(_rState.IsEnabled) ) + || ( feature.second.aCachedAdditionalState != _rState.State ) + ) + { + // change the cached state + feature.second.bCachedState = _rState.IsEnabled; + feature.second.aCachedAdditionalState = _rState.State; + // tell derivees what happened + featureStateChanged( feature.first, _rState.IsEnabled ); + } + return; + } + } + + // unreachable + OSL_FAIL( "OFormNavigationHelper::statusChanged: huh? An invalid/unknown URL?" ); + } + + + void SAL_CALL OFormNavigationHelper::disposing( const EventObject& _rSource ) + { + // was it one of our external dispatchers? + if ( !m_nConnectedFeatures ) + return; + + for (auto & feature : m_aSupportedFeatures) + { + if ( feature.second.xDispatcher == _rSource.Source ) + { + feature.second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), feature.second.aURL ); + feature.second.xDispatcher = nullptr; + feature.second.bCachedState = false; + feature.second.aCachedAdditionalState.clear(); + --m_nConnectedFeatures; + + featureStateChanged( feature.first, false ); + break; + } + } + } + + + void OFormNavigationHelper::updateDispatches() + { + if ( !m_nConnectedFeatures ) + { // we don't have any dispatchers yet -> do the initial connect + connectDispatchers(); + return; + } + + initializeSupportedFeatures(); + + m_nConnectedFeatures = 0; + + Reference< XDispatch > xNewDispatcher; + Reference< XDispatch > xCurrentDispatcher; + + for (auto & feature : m_aSupportedFeatures) + { + xNewDispatcher = queryDispatch( feature.second.aURL ); + xCurrentDispatcher = feature.second.xDispatcher; + if ( xNewDispatcher != xCurrentDispatcher ) + { + // the dispatcher for this particular URL changed + if ( xCurrentDispatcher.is() ) + xCurrentDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), feature.second.aURL ); + + xCurrentDispatcher = feature.second.xDispatcher = xNewDispatcher; + + if ( xCurrentDispatcher.is() ) + xCurrentDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), feature.second.aURL ); + } + + if ( xCurrentDispatcher.is() ) + ++m_nConnectedFeatures; + else + feature.second.bCachedState = false; + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + + void OFormNavigationHelper::connectDispatchers() + { + if ( m_nConnectedFeatures ) + { // already connected -> just do an update + updateDispatches(); + return; + } + + initializeSupportedFeatures(); + + m_nConnectedFeatures = 0; + + for (auto & feature : m_aSupportedFeatures) + { + feature.second.bCachedState = false; + feature.second.aCachedAdditionalState.clear(); + feature.second.xDispatcher = queryDispatch( feature.second.aURL ); + if ( feature.second.xDispatcher.is() ) + { + ++m_nConnectedFeatures; + feature.second.xDispatcher->addStatusListener( static_cast< XStatusListener* >( this ), feature.second.aURL ); + } + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + + void OFormNavigationHelper::disconnectDispatchers() + { + if ( m_nConnectedFeatures ) + { + for (auto & feature : m_aSupportedFeatures) + { + if ( feature.second.xDispatcher.is() ) + feature.second.xDispatcher->removeStatusListener( static_cast< XStatusListener* >( this ), feature.second.aURL ); + + feature.second.xDispatcher = nullptr; + feature.second.bCachedState = false; + feature.second.aCachedAdditionalState.clear(); + } + + m_nConnectedFeatures = 0; + } + + // notify derivee that (potentially) all features changed their state + allFeatureStatesChanged( ); + } + + + void OFormNavigationHelper::initializeSupportedFeatures( ) + { + if ( !m_aSupportedFeatures.empty() ) + return; + + // ask the derivee which feature ids it wants us to support + ::std::vector< sal_Int16 > aFeatureIds; + getSupportedFeatures( aFeatureIds ); + + OFormNavigationMapper aUrlMapper( m_xORB ); + + for (auto const& feature : aFeatureIds) + { + FeatureInfo aFeatureInfo; + + bool bKnownId = + aUrlMapper.getFeatureURL( feature, aFeatureInfo.aURL ); + DBG_ASSERT( bKnownId, "OFormNavigationHelper::initializeSupportedFeatures: unknown feature id!" ); + + if ( bKnownId ) + // add to our map + m_aSupportedFeatures.emplace( feature, aFeatureInfo ); + } + } + + + Reference< XDispatch > OFormNavigationHelper::queryDispatch( const URL& _rURL ) + { + return m_pFeatureInterception->queryDispatch( _rURL ); + } + + + void OFormNavigationHelper::dispatchWithArgument( sal_Int16 _nFeatureId, const char* _pParamAsciiName, + const Any& _rParamValue ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + { + if ( aInfo->second.xDispatcher.is() ) + { + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue( + OUString::createFromAscii( _pParamAsciiName ), _rParamValue) }; + + aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aArgs ); + } + } + } + + + void OFormNavigationHelper::dispatch( sal_Int16 _nFeatureId ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + { + if ( aInfo->second.xDispatcher.is() ) + { + Sequence< PropertyValue > aEmptyArgs; + aInfo->second.xDispatcher->dispatch( aInfo->second.aURL, aEmptyArgs ); + } + } + } + + + bool OFormNavigationHelper::isEnabled( sal_Int16 _nFeatureId ) const + { + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + return aInfo->second.bCachedState; + + return false; + } + + + bool OFormNavigationHelper::getBooleanState( sal_Int16 _nFeatureId ) const + { + bool bState = false; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= bState; + + return bState; + } + + + OUString OFormNavigationHelper::getStringState( sal_Int16 _nFeatureId ) const + { + OUString sState; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= sState; + + return sState; + } + + + sal_Int32 OFormNavigationHelper::getIntegerState( sal_Int16 _nFeatureId ) const + { + sal_Int32 nState = 0; + + FeatureMap::const_iterator aInfo = m_aSupportedFeatures.find( _nFeatureId ); + if ( m_aSupportedFeatures.end() != aInfo ) + aInfo->second.aCachedAdditionalState >>= nState; + + return nState; + } + + + void OFormNavigationHelper::invalidateSupportedFeaturesSet() + { + disconnectDispatchers( ); + // no supported features anymore: + FeatureMap().swap(m_aSupportedFeatures); + } + + OFormNavigationMapper::OFormNavigationMapper( const Reference< XComponentContext >& _rxORB ) + { + m_pUrlTransformer.reset( new UrlTransformer( _rxORB ) ); + } + + + OFormNavigationMapper::~OFormNavigationMapper( ) + { + } + + + bool OFormNavigationMapper::getFeatureURL( sal_Int16 _nFeatureId, URL& /* [out] */ _rURL ) + { + // get the ascii version of the URL + const char* pAsciiURL = getFeatureURLAscii( _nFeatureId ); + if ( pAsciiURL ) + _rURL = m_pUrlTransformer->getStrictURLFromAscii( pAsciiURL ); + + return ( pAsciiURL != nullptr ); + } + + + namespace + { + struct FeatureURL + { + const sal_Int16 nFormFeature; + const char* pAsciiURL; + + FeatureURL( const sal_Int16 _nFormFeature, const char* _pAsciiURL ) + :nFormFeature( _nFormFeature ) + ,pAsciiURL( _pAsciiURL ) + { + } + }; + const FeatureURL* lcl_getFeatureTable() + { + static const FeatureURL s_aFeatureURLs[] = + { + FeatureURL( FormFeature::MoveAbsolute, URL_FORM_POSITION ), + FeatureURL( FormFeature::TotalRecords, URL_FORM_RECORDCOUNT ), + FeatureURL( FormFeature::MoveToFirst, URL_RECORD_FIRST ), + FeatureURL( FormFeature::MoveToPrevious, URL_RECORD_PREV ), + FeatureURL( FormFeature::MoveToNext, URL_RECORD_NEXT ), + FeatureURL( FormFeature::MoveToLast, URL_RECORD_LAST ), + FeatureURL( FormFeature::SaveRecordChanges, URL_RECORD_SAVE ), + FeatureURL( FormFeature::UndoRecordChanges, URL_RECORD_UNDO ), + FeatureURL( FormFeature::MoveToInsertRow, URL_RECORD_NEW ), + FeatureURL( FormFeature::DeleteRecord, URL_RECORD_DELETE ), + FeatureURL( FormFeature::ReloadForm, URL_FORM_REFRESH ), + FeatureURL( FormFeature::RefreshCurrentControl, URL_FORM_REFRESH_CURRENT_CONTROL ), + FeatureURL( FormFeature::SortAscending, URL_FORM_SORT_UP ), + FeatureURL( FormFeature::SortDescending, URL_FORM_SORT_DOWN ), + FeatureURL( FormFeature::InteractiveSort, URL_FORM_SORT ), + FeatureURL( FormFeature::AutoFilter, URL_FORM_AUTO_FILTER ), + FeatureURL( FormFeature::InteractiveFilter, URL_FORM_FILTER ), + FeatureURL( FormFeature::ToggleApplyFilter, URL_FORM_APPLY_FILTER ), + FeatureURL( FormFeature::RemoveFilterAndSort, URL_FORM_REMOVE_FILTER ), + FeatureURL( 0, nullptr ) + }; + return s_aFeatureURLs; + } + } + + + const char* OFormNavigationMapper::getFeatureURLAscii( sal_Int16 _nFeatureId ) + { + const FeatureURL* pFeatures = lcl_getFeatureTable(); + while ( pFeatures->pAsciiURL ) + { + if ( pFeatures->nFormFeature == _nFeatureId ) + return pFeatures->pAsciiURL; + ++pFeatures; + } + return nullptr; + } + + + sal_Int16 OFormNavigationMapper::getFeatureId( std::u16string_view _rCompleteURL ) + { + const FeatureURL* pFeatures = lcl_getFeatureTable(); + while ( pFeatures->pAsciiURL ) + { + if ( o3tl::equalsAscii( _rCompleteURL, pFeatures->pAsciiURL ) ) + return pFeatures->nFormFeature; + ++pFeatures; + } + return -1; + } + + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/helper/resettable.cxx b/forms/source/helper/resettable.cxx new file mode 100644 index 000000000..8994254a6 --- /dev/null +++ b/forms/source/helper/resettable.cxx @@ -0,0 +1,79 @@ +/* -*- 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 . + */ + +#include <resettable.hxx> + +#include <cppuhelper/weak.hxx> + + +namespace frm +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::form::XResetListener; + using ::com::sun::star::lang::EventObject; + + + //= ResetHelper + + + void ResetHelper::addResetListener( const Reference< XResetListener >& _listener ) + { + m_aResetListeners.addInterface( _listener ); + } + + + void ResetHelper::removeResetListener( const Reference< XResetListener >& _listener ) + { + m_aResetListeners.removeInterface( _listener ); + } + + + bool ResetHelper::approveReset() + { + ::comphelper::OInterfaceIteratorHelper3 aIter( m_aResetListeners ); + EventObject aResetEvent( m_rParent ); + + bool bContinue = true; + while ( aIter.hasMoreElements() && bContinue ) + bContinue = aIter.next()->approveReset( aResetEvent ); + + return bContinue; + } + + + void ResetHelper::notifyResetted() + { + EventObject aResetEvent( m_rParent ); + m_aResetListeners.notifyEach( &XResetListener::resetted, aResetEvent ); + } + + + void ResetHelper::disposing() + { + EventObject aEvent( m_rParent ); + m_aResetListeners.disposeAndClear( aEvent ); + } + + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/helper/urltransformer.cxx b/forms/source/helper/urltransformer.cxx new file mode 100644 index 000000000..e112041c2 --- /dev/null +++ b/forms/source/helper/urltransformer.cxx @@ -0,0 +1,83 @@ +/* -*- 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 . + */ + +#include <urltransformer.hxx> + +#include <com/sun/star/util/URLTransformer.hpp> +#include <tools/debug.hxx> + + +namespace frm +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + UrlTransformer::UrlTransformer( const Reference< XComponentContext >& _rxORB ) + :m_xORB( _rxORB ) + ,m_bTriedToCreateTransformer( false ) + { + DBG_ASSERT( _rxORB.is(), "UrlTransformer::UrlTransformer: invalid service factory!" ); + } + + + bool UrlTransformer::implEnsureTransformer() const + { + // create the transformer, if not already attempted to do so + if ( !m_xTransformer.is() && !m_bTriedToCreateTransformer ) + { + if ( m_xORB.is() ) + { + m_xTransformer.set(URLTransformer::create(m_xORB)); + } + + m_bTriedToCreateTransformer = true; + } + return m_xTransformer.is(); + } + + + URL UrlTransformer::getStrictURL( const OUString& _rURL ) const + { + URL aReturn; + aReturn.Complete = _rURL; + if ( implEnsureTransformer() ) + m_xTransformer->parseStrict( aReturn ); + return aReturn; + } + + + URL UrlTransformer::getStrictURLFromAscii( const char* _pAsciiURL ) const + { + return getStrictURL( OUString::createFromAscii( _pAsciiURL ) ); + } + + + void UrlTransformer::parseSmartWithProtocol( css::util::URL& _rURL, const OUString& _rProtocol ) const + { + if ( implEnsureTransformer() ) + m_xTransformer->parseSmart( _rURL, _rProtocol ); + } + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/helper/windowstateguard.cxx b/forms/source/helper/windowstateguard.cxx new file mode 100644 index 000000000..0202baa74 --- /dev/null +++ b/forms/source/helper/windowstateguard.cxx @@ -0,0 +1,213 @@ +/* -*- 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 . + */ + +#include <windowstateguard.hxx> +#include <frm_strings.hxx> + +#include <com/sun/star/awt/XWindowListener2.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/implbase.hxx> +#include <tools/diagnose_ex.h> + + +namespace frm +{ + + + using ::com::sun::star::awt::XWindowListener2; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::awt::XWindow2; + using ::com::sun::star::awt::WindowEvent; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::awt::XControlModel; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::Exception; + + typedef ::cppu::WeakImplHelper < XWindowListener2 + > WindowStateGuard_Impl_Base; + class WindowStateGuard_Impl : public WindowStateGuard_Impl_Base + { + private: + ::osl::Mutex m_aMutex; + Reference< XWindow2 > m_xWindow; + Reference< XPropertySet > m_xModelProps; + + public: + /** constructs the instance + @param _rxWindow + the window at which to listen. Must not be <NULL/>. + @param _rxModel + the model which acts as the reference for the states to be enforced. Must not be <NULL/>. + */ + WindowStateGuard_Impl( const Reference< XWindow2 >& _rxWindow, const Reference< XPropertySet >& _rxMdelProps ); + + void dispose(); + + protected: + // XWindowListener2 + virtual void SAL_CALL windowEnabled( const css::lang::EventObject& e ) override; + virtual void SAL_CALL windowDisabled( const css::lang::EventObject& e ) override; + + // XWindowListener + virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override; + virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override; + virtual void SAL_CALL windowShown( const css::lang::EventObject& e ) override; + virtual void SAL_CALL windowHidden( const css::lang::EventObject& e ) override; + + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; + + private: + /** ensures that the window's Enabled state matches what is described at the model + @precond + our mutex is locked + */ + void impl_ensureEnabledState_nothrow_nolck(); + }; + + + WindowStateGuard_Impl::WindowStateGuard_Impl( const Reference< XWindow2 >& _rxWindow, const Reference< XPropertySet >& _rxMdelProps ) + :m_xWindow( _rxWindow ) + ,m_xModelProps( _rxMdelProps ) + { + if ( !m_xWindow.is() || !m_xModelProps.is() ) + throw RuntimeException(); + + osl_atomic_increment( &m_refCount ); + { + m_xWindow->addWindowListener( this ); + } + osl_atomic_decrement( &m_refCount ); + } + + + void WindowStateGuard_Impl::dispose() + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xWindow.is() ) + // already disposed + return; + + m_xWindow->removeWindowListener( this ); + m_xWindow.clear(); + } + + + void WindowStateGuard_Impl::impl_ensureEnabledState_nothrow_nolck() + { + try + { + Reference< XWindow2 > xWindow; + Reference< XPropertySet > xModelProps; + bool bShouldBeEnabled = false; + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xWindow.is() || !m_xModelProps.is() ) + return; + xWindow = m_xWindow; + xModelProps = m_xModelProps; + } + // fdo#42157: do not lock m_aMutex to prevent deadlock + bool const bEnabled = xWindow->isEnabled(); + OSL_VERIFY( xModelProps->getPropertyValue( PROPERTY_ENABLED ) + >>= bShouldBeEnabled ); + + if ( !bShouldBeEnabled && bEnabled ) + xWindow->setEnable( false ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("forms.helper"); + } + } + + + void SAL_CALL WindowStateGuard_Impl::windowEnabled( const EventObject& /*e*/ ) + { + impl_ensureEnabledState_nothrow_nolck(); + } + + + void SAL_CALL WindowStateGuard_Impl::windowDisabled( const EventObject& /*e*/ ) + { + impl_ensureEnabledState_nothrow_nolck(); + } + + + void SAL_CALL WindowStateGuard_Impl::windowResized( const WindowEvent& /*e*/ ) + { + // not interested in + } + + + void SAL_CALL WindowStateGuard_Impl::windowMoved( const WindowEvent& /*e*/ ) + { + // not interested in + } + + + void SAL_CALL WindowStateGuard_Impl::windowShown( const EventObject& /*e*/ ) + { + // not interested in + } + + + void SAL_CALL WindowStateGuard_Impl::windowHidden( const EventObject& /*e*/ ) + { + // not interested in + } + + + void SAL_CALL WindowStateGuard_Impl::disposing( const EventObject& Source ) + { + OSL_ENSURE( Source.Source == m_xWindow, "WindowStateGuard_Impl::disposing: where does this come from?" ); + dispose(); + } + + WindowStateGuard::WindowStateGuard() + { + } + + + WindowStateGuard::~WindowStateGuard() + { + } + + + void WindowStateGuard::attach( const Reference< XWindow2 >& _rxWindow, const Reference< XControlModel >& _rxModel ) + { + if ( m_pImpl.is() ) + { + m_pImpl->dispose(); + m_pImpl = nullptr; + } + + Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY ); + OSL_ENSURE( xModelProps.is() || !_rxModel.is(), "WindowStateGuard::attach: a model which is no XPropertySet?" ); + if ( _rxWindow.is() && xModelProps.is() ) + m_pImpl = new WindowStateGuard_Impl( _rxWindow, xModelProps ); + } + + +} // namespace frm + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |