/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 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 aSSSIterator = std::make_shared(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 aSSSIterator = std::make_shared(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 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(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 aSSSIterator = std::make_shared(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 aSSSIterator = std::make_shared(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::get(); } sal_Bool SAL_CALL SdStyleFamily::hasElements() { SolarMutexGuard aGuard; throwIfDisposed(); if( mnFamily == SfxStyleFamily::Page ) { return true; } else { std::shared_ptr aSSSIterator = std::make_shared(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 aSSSIterator = std::make_shared(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(rStyleSheets.size()) ) { PresStyleMap::iterator iter( rStyleSheets.begin() ); std::advance(iter, Index); return Any( Reference< XStyle >( (*iter).second ) ); } } else { std::shared_ptr aSSSIterator = std::make_shared(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( static_cast(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 SdStyleFamily::getPropertySetInfo() { OSL_FAIL( "###unexpected!" ); return Reference(); } 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(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& ) { OSL_FAIL( "###unexpected!" ); } void SdStyleFamily::removePropertyChangeListener( const OUString& , const Reference& ) { OSL_FAIL( "###unexpected!" ); } void SdStyleFamily::addVetoableChangeListener( const OUString& , const Reference& ) { OSL_FAIL( "###unexpected!" ); } void SdStyleFamily::removeVetoableChangeListener( const OUString& , const Reference& ) { OSL_FAIL( "###unexpected!" ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */