Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / core / stlfamily.cxx
blob02594ea9fadaaa4e8d94d16dbddf048e62d305ea
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 .
20 #include <com/sun/star/lang/DisposedException.hpp>
21 #include <com/sun/star/lang/IllegalAccessException.hpp>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <cppuhelper/supportsservice.hxx>
25 #include <utility>
26 #include <vcl/svapp.hxx>
28 #include <svl/style.hxx>
30 #include <tools/debug.hxx>
31 #include <unotools/weakref.hxx>
33 #include <strings.hrc>
34 #include <stlfamily.hxx>
35 #include <stlsheet.hxx>
36 #include <sdresid.hxx>
37 #include <sdpage.hxx>
38 #include <glob.hxx>
40 #include <map>
41 #include <memory>
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::container;
46 using namespace ::com::sun::star::style;
47 using namespace ::com::sun::star::beans;
49 typedef std::map< OUString, rtl::Reference< SdStyleSheet > > PresStyleMap;
51 struct SdStyleFamilyImpl
53 unotools::WeakReference<SdPage> mxMasterPage;
54 OUString maLayoutName;
56 PresStyleMap& getStyleSheets();
57 rtl::Reference< SfxStyleSheetPool > mxPool;
59 private:
60 PresStyleMap maStyleSheets;
63 PresStyleMap& SdStyleFamilyImpl::getStyleSheets()
65 auto pMasterPage = mxMasterPage.get();
66 if (!pMasterPage)
67 return maStyleSheets;
69 if (pMasterPage->GetLayoutName() != maLayoutName )
71 maLayoutName = pMasterPage->GetLayoutName();
73 OUString aLayoutName( maLayoutName );
74 const sal_Int32 nLen = aLayoutName.indexOf(SD_LT_SEPARATOR ) + 4;
75 aLayoutName = aLayoutName.copy(0, nLen );
77 if( (maStyleSheets.empty()) || !(*maStyleSheets.begin()).second->GetName().startsWith( aLayoutName) )
79 maStyleSheets.clear();
81 // The iterator will return only style sheets of family master page
82 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), SfxStyleFamily::Page);
83 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
84 pStyle = aSSSIterator->Next() )
86 // we assume that we have only SdStyleSheets
87 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
88 if (pSdStyle->GetName().startsWith(aLayoutName))
90 maStyleSheets[ pSdStyle->GetApiName() ].set( pSdStyle );
96 return maStyleSheets;
99 SdStyleFamily::SdStyleFamily( rtl::Reference< SfxStyleSheetPool > xPool, SfxStyleFamily nFamily )
100 : mnFamily( nFamily )
101 , mxPool(std::move( xPool ))
105 SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage )
106 : mnFamily( SfxStyleFamily::Page )
107 , mxPool( xPool )
108 , mpImpl( new SdStyleFamilyImpl )
110 mpImpl->mxMasterPage = const_cast< SdPage* >( pMasterPage );
111 mpImpl->mxPool = xPool;
114 SdStyleFamily::~SdStyleFamily()
116 DBG_ASSERT( !mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" );
119 void SdStyleFamily::throwIfDisposed() const
121 if( !mxPool.is() )
122 throw DisposedException();
125 SdStyleSheet* SdStyleFamily::GetValidNewSheet( const Any& rElement )
127 Reference< XStyle > xStyle( rElement, UNO_QUERY );
128 SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( xStyle.get() );
130 if( pStyle == nullptr || (pStyle->GetFamily() != mnFamily) || (pStyle->GetPool() != mxPool.get()) || (mxPool->Find( pStyle->GetName(), mnFamily) != nullptr) )
131 throw IllegalArgumentException();
133 return pStyle;
136 SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName )
138 SdStyleSheet* pRet = nullptr;
139 if( !rName.isEmpty() )
141 if( mnFamily == SfxStyleFamily::Page )
143 PresStyleMap& rStyleMap = mpImpl->getStyleSheets();
144 PresStyleMap::iterator iter( rStyleMap.find(rName) );
145 if( iter != rStyleMap.end() )
146 pRet = (*iter).second.get();
148 else
150 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
151 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
152 pStyle = aSSSIterator->Next() )
154 // we assume that we have only SdStyleSheets
155 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
156 if (pSdStyle->GetApiName() == rName)
158 pRet = pSdStyle;
159 break;
164 if( pRet )
165 return pRet;
167 throw NoSuchElementException();
170 // XServiceInfo
171 OUString SAL_CALL SdStyleFamily::getImplementationName()
173 return "SdStyleFamily";
176 sal_Bool SAL_CALL SdStyleFamily::supportsService( const OUString& ServiceName )
178 return cppu::supportsService( this, ServiceName );
181 Sequence< OUString > SAL_CALL SdStyleFamily::getSupportedServiceNames()
183 return { "com.sun.star.style.StyleFamily" };
186 // XNamed
187 OUString SAL_CALL SdStyleFamily::getName()
189 if( mnFamily == SfxStyleFamily::Page )
191 rtl::Reference<SdPage> pPage = mpImpl->mxMasterPage.get();
192 if( pPage == nullptr )
193 throw DisposedException();
195 OUString aLayoutName( pPage->GetLayoutName() );
196 sal_Int32 nIndex = aLayoutName.indexOf(SD_LT_SEPARATOR);
197 if( nIndex != -1 )
198 aLayoutName = aLayoutName.copy(0, nIndex);
200 return aLayoutName;
202 else
204 return SdStyleSheet::GetFamilyString( mnFamily );
208 void SAL_CALL SdStyleFamily::setName( const OUString& )
212 // XNameAccess
214 Any SAL_CALL SdStyleFamily::getByName( const OUString& rName )
216 SolarMutexGuard aGuard;
217 throwIfDisposed();
218 return Any( Reference< XStyle >( static_cast<SfxUnoStyleSheet*>(GetSheetByName( rName )) ) );
221 Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames()
223 SolarMutexGuard aGuard;
225 throwIfDisposed();
227 if( mnFamily == SfxStyleFamily::Page )
229 PresStyleMap& rStyleMap = mpImpl->getStyleSheets();
230 Sequence< OUString > aNames( rStyleMap.size() );
232 OUString* pNames = aNames.getArray();
233 for( const auto& rEntry : rStyleMap )
235 rtl::Reference< SdStyleSheet > xStyle( rEntry.second );
236 if( xStyle.is() )
238 *pNames++ = xStyle->GetApiName();
242 return aNames;
244 else
246 std::vector< OUString > aNames;
247 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
248 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
249 pStyle = aSSSIterator->Next() )
251 // we assume that we have only SdStyleSheets
252 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
253 aNames.push_back(pSdStyle->GetApiName());
255 return Sequence< OUString >( &(*aNames.begin()), aNames.size() );
259 sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName )
261 SolarMutexGuard aGuard;
262 throwIfDisposed();
264 if( !aName.isEmpty() )
266 if( mnFamily == SfxStyleFamily::Page )
268 PresStyleMap& rStyleSheets = mpImpl->getStyleSheets();
269 PresStyleMap::iterator iter( rStyleSheets.find(aName) );
270 return iter != rStyleSheets.end();
272 else
274 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
275 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
276 pStyle = aSSSIterator->Next() )
278 // we assume that we have only SdStyleSheets
279 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
280 if (pSdStyle->GetApiName() == aName)
282 return true;
288 return false;
291 // XElementAccess
293 Type SAL_CALL SdStyleFamily::getElementType()
295 return cppu::UnoType<XStyle>::get();
298 sal_Bool SAL_CALL SdStyleFamily::hasElements()
300 SolarMutexGuard aGuard;
301 throwIfDisposed();
303 if( mnFamily == SfxStyleFamily::Page )
305 return true;
307 else
309 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
310 if (aSSSIterator->First())
312 return true;
316 return false;
319 // XIndexAccess
321 sal_Int32 SAL_CALL SdStyleFamily::getCount()
323 SolarMutexGuard aGuard;
324 throwIfDisposed();
326 sal_Int32 nCount = 0;
327 if( mnFamily == SfxStyleFamily::Page )
329 return mpImpl->getStyleSheets().size();
331 else
333 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
334 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
335 pStyle = aSSSIterator->Next() )
337 nCount++;
341 return nCount;
344 Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index )
346 SolarMutexGuard aGuard;
347 throwIfDisposed();
349 if( Index >= 0 )
351 if( mnFamily == SfxStyleFamily::Page )
353 PresStyleMap& rStyleSheets = mpImpl->getStyleSheets();
354 if( Index < static_cast<sal_Int32>(rStyleSheets.size()) )
356 PresStyleMap::iterator iter( rStyleSheets.begin() );
357 std::advance(iter, Index);
358 return Any( Reference< XStyle >( (*iter).second ) );
361 else
363 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
364 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
365 pStyle = aSSSIterator->Next() )
367 // we assume that we have only SdStyleSheets
368 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
369 if( Index-- == 0 )
371 return Any( Reference< XStyle >( pSdStyle ) );
377 throw IndexOutOfBoundsException();
380 // XNameContainer
382 void SAL_CALL SdStyleFamily::insertByName( const OUString& rName, const Any& rElement )
384 SolarMutexGuard aGuard;
385 throwIfDisposed();
387 if(rName.isEmpty())
388 throw IllegalArgumentException();
390 SdStyleSheet* pStyle = GetValidNewSheet( rElement );
391 if( !pStyle->SetName( rName ) )
392 throw ElementExistException();
394 pStyle->SetApiName( rName );
395 mxPool->Insert( pStyle );
398 void SAL_CALL SdStyleFamily::removeByName( const OUString& rName )
400 SolarMutexGuard aGuard;
401 throwIfDisposed();
403 SdStyleSheet* pStyle = GetSheetByName( rName );
405 if( !pStyle->IsUserDefined() )
406 throw WrappedTargetException();
408 mxPool->Remove( pStyle );
411 // XNameReplace
413 void SAL_CALL SdStyleFamily::replaceByName( const OUString& rName, const Any& aElement )
415 SolarMutexGuard aGuard;
416 throwIfDisposed();
418 SdStyleSheet* pOldStyle = GetSheetByName( rName );
419 SdStyleSheet* pNewStyle = GetValidNewSheet( aElement );
421 mxPool->Remove( pOldStyle );
422 mxPool->Insert( pNewStyle );
425 // XSingleServiceFactory
427 Reference< XInterface > SAL_CALL SdStyleFamily::createInstance()
429 SolarMutexGuard aGuard;
430 throwIfDisposed();
432 if( mnFamily == SfxStyleFamily::Page )
434 throw IllegalAccessException();
436 return Reference<XInterface>(
437 static_cast<XStyle*>(SdStyleSheet::CreateEmptyUserStyle(*mxPool, mnFamily).get()));
440 Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( const Sequence< Any >& )
442 return createInstance();
445 // XComponent
447 void SAL_CALL SdStyleFamily::dispose( )
449 if( mxPool.is() )
450 mxPool.clear();
452 mpImpl.reset();
455 void SAL_CALL SdStyleFamily::addEventListener( const Reference< XEventListener >& )
459 void SAL_CALL SdStyleFamily::removeEventListener( const Reference< XEventListener >& )
463 // XPropertySet
465 Reference<XPropertySetInfo> SdStyleFamily::getPropertySetInfo()
467 OSL_FAIL( "###unexpected!" );
468 return Reference<XPropertySetInfo>();
471 void SdStyleFamily::setPropertyValue( const OUString& , const Any& )
473 OSL_FAIL( "###unexpected!" );
476 Any SdStyleFamily::getPropertyValue( const OUString& PropertyName )
478 if ( PropertyName != "DisplayName" )
480 throw UnknownPropertyException( "unknown property: " + PropertyName, static_cast<OWeakObject *>(this) );
483 SolarMutexGuard aGuard;
484 OUString sDisplayName;
485 switch( mnFamily )
487 case SfxStyleFamily::Page: sDisplayName = getName(); break;
488 case SfxStyleFamily::Frame: sDisplayName = SdResId(STR_CELL_STYLE_FAMILY); break;
489 default: sDisplayName = SdResId(STR_GRAPHICS_STYLE_FAMILY); break;
491 return Any( sDisplayName );
494 void SdStyleFamily::addPropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& )
496 OSL_FAIL( "###unexpected!" );
499 void SdStyleFamily::removePropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& )
501 OSL_FAIL( "###unexpected!" );
504 void SdStyleFamily::addVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& )
506 OSL_FAIL( "###unexpected!" );
509 void SdStyleFamily::removeVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& )
511 OSL_FAIL( "###unexpected!" );
514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */