diff options
Diffstat (limited to '')
-rw-r--r-- | sd/source/core/stlfamily.cxx | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/sd/source/core/stlfamily.cxx b/sd/source/core/stlfamily.cxx new file mode 100644 index 000000000..a396bd170 --- /dev/null +++ b/sd/source/core/stlfamily.cxx @@ -0,0 +1,513 @@ +/* -*- 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 <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include <vcl/svapp.hxx> + +#include <svl/style.hxx> + +#include <tools/debug.hxx> +#include <unotools/weakref.hxx> + +#include <strings.hrc> +#include <stlfamily.hxx> +#include <stlsheet.hxx> +#include <sdresid.hxx> +#include <sdpage.hxx> +#include <glob.hxx> + +#include <map> +#include <memory> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::beans; + +typedef std::map< OUString, rtl::Reference< SdStyleSheet > > PresStyleMap; + +struct SdStyleFamilyImpl +{ + unotools::WeakReference<SdPage> mxMasterPage; + OUString maLayoutName; + + PresStyleMap& getStyleSheets(); + rtl::Reference< SfxStyleSheetPool > mxPool; + +private: + PresStyleMap maStyleSheets; +}; + +PresStyleMap& SdStyleFamilyImpl::getStyleSheets() +{ + auto pMasterPage = mxMasterPage.get(); + if (!pMasterPage) + return maStyleSheets; + + if (pMasterPage->GetLayoutName() != maLayoutName ) + { + maLayoutName = pMasterPage->GetLayoutName(); + + OUString aLayoutName( maLayoutName ); + const sal_Int32 nLen = aLayoutName.indexOf(SD_LT_SEPARATOR ) + 4; + aLayoutName = aLayoutName.copy(0, nLen ); + + if( (maStyleSheets.empty()) || !(*maStyleSheets.begin()).second->GetName().startsWith( aLayoutName) ) + { + maStyleSheets.clear(); + + // The iterator will return only style sheets of family master page + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), SfxStyleFamily::Page); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + // we assume that we have only SdStyleSheets + SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle ); + if (pSdStyle->GetName().startsWith(aLayoutName)) + { + maStyleSheets[ pSdStyle->GetApiName() ].set( pSdStyle ); + } + } + } + } + + return maStyleSheets; +} + +SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, SfxStyleFamily nFamily ) +: mnFamily( nFamily ) +, mxPool( xPool ) +{ +} + +SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage ) +: mnFamily( SfxStyleFamily::Page ) +, mxPool( xPool ) +, mpImpl( new SdStyleFamilyImpl ) +{ + mpImpl->mxMasterPage = const_cast< SdPage* >( pMasterPage ); + mpImpl->mxPool = xPool; +} + +SdStyleFamily::~SdStyleFamily() +{ + DBG_ASSERT( !mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" ); +} + +void SdStyleFamily::throwIfDisposed() const +{ + if( !mxPool.is() ) + throw DisposedException(); +} + +SdStyleSheet* SdStyleFamily::GetValidNewSheet( const Any& rElement ) +{ + Reference< XStyle > xStyle( rElement, UNO_QUERY ); + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( xStyle.get() ); + + if( pStyle == nullptr || (pStyle->GetFamily() != mnFamily) || (pStyle->GetPool() != mxPool.get()) || (mxPool->Find( pStyle->GetName(), mnFamily) != nullptr) ) + throw IllegalArgumentException(); + + return pStyle; +} + +SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName ) +{ + SdStyleSheet* pRet = nullptr; + if( !rName.isEmpty() ) + { + if( mnFamily == SfxStyleFamily::Page ) + { + PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); + PresStyleMap::iterator iter( rStyleMap.find(rName) ); + if( iter != rStyleMap.end() ) + pRet = (*iter).second.get(); + } + else + { + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + // we assume that we have only SdStyleSheets + SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle ); + if (pSdStyle->GetApiName() == rName) + { + pRet = pSdStyle; + break; + } + } + } + } + if( pRet ) + return pRet; + + throw NoSuchElementException(); +} + +// XServiceInfo +OUString SAL_CALL SdStyleFamily::getImplementationName() +{ + return "SdStyleFamily"; +} + +sal_Bool SAL_CALL SdStyleFamily::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +Sequence< OUString > SAL_CALL SdStyleFamily::getSupportedServiceNames() +{ + return { "com.sun.star.style.StyleFamily" }; +} + +// XNamed +OUString SAL_CALL SdStyleFamily::getName() +{ + if( mnFamily == SfxStyleFamily::Page ) + { + rtl::Reference<SdPage> pPage = mpImpl->mxMasterPage.get(); + if( pPage == nullptr ) + throw DisposedException(); + + OUString aLayoutName( pPage->GetLayoutName() ); + sal_Int32 nIndex = aLayoutName.indexOf(SD_LT_SEPARATOR); + if( nIndex != -1 ) + aLayoutName = aLayoutName.copy(0, nIndex); + + return aLayoutName; + } + else + { + return SdStyleSheet::GetFamilyString( mnFamily ); + } +} + +void SAL_CALL SdStyleFamily::setName( const OUString& ) +{ +} + +// XNameAccess + +Any SAL_CALL SdStyleFamily::getByName( const OUString& rName ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + return Any( Reference< XStyle >( static_cast<SfxUnoStyleSheet*>(GetSheetByName( rName )) ) ); +} + +Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames() +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + if( mnFamily == SfxStyleFamily::Page ) + { + PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); + Sequence< OUString > aNames( rStyleMap.size() ); + + OUString* pNames = aNames.getArray(); + for( const auto& rEntry : rStyleMap ) + { + rtl::Reference< SdStyleSheet > xStyle( rEntry.second ); + if( xStyle.is() ) + { + *pNames++ = xStyle->GetApiName(); + } + } + + return aNames; + } + else + { + std::vector< OUString > aNames; + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + // we assume that we have only SdStyleSheets + SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle ); + aNames.push_back(pSdStyle->GetApiName()); + } + return Sequence< OUString >( &(*aNames.begin()), aNames.size() ); + } +} + +sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( !aName.isEmpty() ) + { + if( mnFamily == SfxStyleFamily::Page ) + { + PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); + PresStyleMap::iterator iter( rStyleSheets.find(aName) ); + return iter != rStyleSheets.end(); + } + else + { + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + // we assume that we have only SdStyleSheets + SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle ); + if (pSdStyle->GetApiName() == aName) + { + return true; + } + } + } + } + + return false; +} + +// XElementAccess + +Type SAL_CALL SdStyleFamily::getElementType() +{ + return cppu::UnoType<XStyle>::get(); +} + +sal_Bool SAL_CALL SdStyleFamily::hasElements() +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( mnFamily == SfxStyleFamily::Page ) + { + return true; + } + else + { + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + if (aSSSIterator->First()) + { + return true; + } + } + + return false; +} + +// XIndexAccess + +sal_Int32 SAL_CALL SdStyleFamily::getCount() +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + sal_Int32 nCount = 0; + if( mnFamily == SfxStyleFamily::Page ) + { + return mpImpl->getStyleSheets().size(); + } + else + { + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + nCount++; + } + } + + return nCount; +} + +Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( Index >= 0 ) + { + if( mnFamily == SfxStyleFamily::Page ) + { + PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); + if( Index < static_cast<sal_Int32>(rStyleSheets.size()) ) + { + PresStyleMap::iterator iter( rStyleSheets.begin() ); + std::advance(iter, Index); + return Any( Reference< XStyle >( (*iter).second ) ); + } + } + else + { + std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily); + for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; + pStyle = aSSSIterator->Next() ) + { + // we assume that we have only SdStyleSheets + SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle ); + if( Index-- == 0 ) + { + return Any( Reference< XStyle >( pSdStyle ) ); + } + } + } + } + + throw IndexOutOfBoundsException(); +} + +// XNameContainer + +void SAL_CALL SdStyleFamily::insertByName( const OUString& rName, const Any& rElement ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if(rName.isEmpty()) + throw IllegalArgumentException(); + + SdStyleSheet* pStyle = GetValidNewSheet( rElement ); + if( !pStyle->SetName( rName ) ) + throw ElementExistException(); + + pStyle->SetApiName( rName ); + mxPool->Insert( pStyle ); +} + +void SAL_CALL SdStyleFamily::removeByName( const OUString& rName ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + SdStyleSheet* pStyle = GetSheetByName( rName ); + + if( !pStyle->IsUserDefined() ) + throw WrappedTargetException(); + + mxPool->Remove( pStyle ); +} + +// XNameReplace + +void SAL_CALL SdStyleFamily::replaceByName( const OUString& rName, const Any& aElement ) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + SdStyleSheet* pOldStyle = GetSheetByName( rName ); + SdStyleSheet* pNewStyle = GetValidNewSheet( aElement ); + + mxPool->Remove( pOldStyle ); + mxPool->Insert( pNewStyle ); +} + +// XSingleServiceFactory + +Reference< XInterface > SAL_CALL SdStyleFamily::createInstance() +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( mnFamily == SfxStyleFamily::Page ) + { + throw IllegalAccessException(); + } + return Reference<XInterface>( + static_cast<XStyle*>(SdStyleSheet::CreateEmptyUserStyle(*mxPool, mnFamily).get())); +} + +Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( const Sequence< Any >& ) +{ + return createInstance(); +} + +// XComponent + +void SAL_CALL SdStyleFamily::dispose( ) +{ + if( mxPool.is() ) + mxPool.clear(); + + mpImpl.reset(); +} + +void SAL_CALL SdStyleFamily::addEventListener( const Reference< XEventListener >& ) +{ +} + +void SAL_CALL SdStyleFamily::removeEventListener( const Reference< XEventListener >& ) +{ +} + +// XPropertySet + +Reference<XPropertySetInfo> SdStyleFamily::getPropertySetInfo() +{ + OSL_FAIL( "###unexpected!" ); + return Reference<XPropertySetInfo>(); +} + +void SdStyleFamily::setPropertyValue( const OUString& , const Any& ) +{ + OSL_FAIL( "###unexpected!" ); +} + +Any SdStyleFamily::getPropertyValue( const OUString& PropertyName ) +{ + if ( PropertyName != "DisplayName" ) + { + throw UnknownPropertyException( "unknown property: " + PropertyName, static_cast<OWeakObject *>(this) ); + } + + SolarMutexGuard aGuard; + OUString sDisplayName; + switch( mnFamily ) + { + case SfxStyleFamily::Page: sDisplayName = getName(); break; + case SfxStyleFamily::Frame: sDisplayName = SdResId(STR_CELL_STYLE_FAMILY); break; + default: sDisplayName = SdResId(STR_GRAPHICS_STYLE_FAMILY); break; + } + return Any( sDisplayName ); +} + +void SdStyleFamily::addPropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& ) +{ + OSL_FAIL( "###unexpected!" ); +} + +void SdStyleFamily::removePropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& ) +{ + OSL_FAIL( "###unexpected!" ); +} + +void SdStyleFamily::addVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& ) +{ + OSL_FAIL( "###unexpected!" ); +} + +void SdStyleFamily::removeVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& ) +{ + OSL_FAIL( "###unexpected!" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |