bump product version to 6.4.0.3
[LibreOffice.git] / sd / source / core / stlfamily.cxx
blobbb332e7939abb33698882e1289e00003727e8b5d
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 <vcl/svapp.hxx>
27 #include <svl/style.hxx>
29 #include <tools/debug.hxx>
30 #include <tools/weakbase.hxx>
32 #include <strings.hrc>
33 #include <stlfamily.hxx>
34 #include <stlsheet.hxx>
35 #include <sdresid.hxx>
36 #include <sdpage.hxx>
37 #include <glob.hxx>
39 #include <map>
40 #include <memory>
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::lang;
44 using namespace ::com::sun::star::container;
45 using namespace ::com::sun::star::style;
46 using namespace ::com::sun::star::beans;
48 typedef std::map< OUString, rtl::Reference< SdStyleSheet > > PresStyleMap;
50 struct SdStyleFamilyImpl
52 tools::WeakReference<SdPage> mxMasterPage;
53 OUString maLayoutName;
55 PresStyleMap& getStyleSheets();
56 rtl::Reference< SfxStyleSheetPool > mxPool;
58 private:
59 PresStyleMap maStyleSheets;
62 PresStyleMap& SdStyleFamilyImpl::getStyleSheets()
64 if( mxMasterPage.is() && (mxMasterPage->GetLayoutName() != maLayoutName) )
66 maLayoutName = mxMasterPage->GetLayoutName();
68 OUString aLayoutName( maLayoutName );
69 const sal_Int32 nLen = aLayoutName.indexOf(SD_LT_SEPARATOR ) + 4;
70 aLayoutName = aLayoutName.copy(0, nLen );
72 if( (maStyleSheets.empty()) || !(*maStyleSheets.begin()).second->GetName().startsWith( aLayoutName) )
74 maStyleSheets.clear();
76 // The iterator will return only style sheets of family master page
77 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), SfxStyleFamily::Page);
78 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
79 pStyle = aSSSIterator->Next() )
81 // we assume that we have only SdStyleSheets
82 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
83 if (pSdStyle->GetName().startsWith(aLayoutName))
85 maStyleSheets[ pSdStyle->GetApiName() ].set( pSdStyle );
91 return maStyleSheets;
94 SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, SfxStyleFamily nFamily )
95 : mnFamily( nFamily )
96 , mxPool( xPool )
100 SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage )
101 : mnFamily( SfxStyleFamily::Page )
102 , mxPool( xPool )
103 , mpImpl( new SdStyleFamilyImpl )
105 mpImpl->mxMasterPage.reset( const_cast< SdPage* >( pMasterPage ) );
106 mpImpl->mxPool = xPool;
109 SdStyleFamily::~SdStyleFamily()
111 DBG_ASSERT( !mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" );
114 void SdStyleFamily::throwIfDisposed() const
116 if( !mxPool.is() )
117 throw DisposedException();
120 SdStyleSheet* SdStyleFamily::GetValidNewSheet( const Any& rElement )
122 Reference< XStyle > xStyle( rElement, UNO_QUERY );
123 SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( xStyle.get() );
125 if( pStyle == nullptr || (pStyle->GetFamily() != mnFamily) || (pStyle->GetPool() != mxPool.get()) || (mxPool->Find( pStyle->GetName(), mnFamily) != nullptr) )
126 throw IllegalArgumentException();
128 return pStyle;
131 SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName )
133 SdStyleSheet* pRet = nullptr;
134 if( !rName.isEmpty() )
136 if( mnFamily == SfxStyleFamily::Page )
138 PresStyleMap& rStyleMap = mpImpl->getStyleSheets();
139 PresStyleMap::iterator iter( rStyleMap.find(rName) );
140 if( iter != rStyleMap.end() )
141 pRet = (*iter).second.get();
143 else
145 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
146 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
147 pStyle = aSSSIterator->Next() )
149 // we assume that we have only SdStyleSheets
150 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
151 if (pSdStyle->GetApiName() == rName)
153 pRet = pSdStyle;
154 break;
159 if( pRet )
160 return pRet;
162 throw NoSuchElementException();
165 // XServiceInfo
166 OUString SAL_CALL SdStyleFamily::getImplementationName()
168 return "SdStyleFamily";
171 sal_Bool SAL_CALL SdStyleFamily::supportsService( const OUString& ServiceName )
173 return cppu::supportsService( this, ServiceName );
176 Sequence< OUString > SAL_CALL SdStyleFamily::getSupportedServiceNames()
178 return { "com.sun.star.style.StyleFamily" };
181 // XNamed
182 OUString SAL_CALL SdStyleFamily::getName()
184 if( mnFamily == SfxStyleFamily::Page )
186 SdPage* pPage = mpImpl->mxMasterPage.get();
187 if( pPage == nullptr )
188 throw DisposedException();
190 OUString aLayoutName( pPage->GetLayoutName() );
191 const OUString aSep( SD_LT_SEPARATOR );
192 sal_Int32 nIndex = aLayoutName.indexOf(aSep);
193 if( nIndex != -1 )
194 aLayoutName = aLayoutName.copy(0, nIndex);
196 return aLayoutName;
198 else
200 return SdStyleSheet::GetFamilyString( mnFamily );
204 void SAL_CALL SdStyleFamily::setName( const OUString& )
208 // XNameAccess
210 Any SAL_CALL SdStyleFamily::getByName( const OUString& rName )
212 SolarMutexGuard aGuard;
213 throwIfDisposed();
214 return Any( Reference< XStyle >( static_cast<SfxUnoStyleSheet*>(GetSheetByName( rName )) ) );
217 Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames()
219 SolarMutexGuard aGuard;
221 throwIfDisposed();
223 if( mnFamily == SfxStyleFamily::Page )
225 PresStyleMap& rStyleMap = mpImpl->getStyleSheets();
226 Sequence< OUString > aNames( rStyleMap.size() );
228 OUString* pNames = aNames.getArray();
229 for( const auto& rEntry : rStyleMap )
231 rtl::Reference< SdStyleSheet > xStyle( rEntry.second );
232 if( xStyle.is() )
234 *pNames++ = xStyle->GetApiName();
238 return aNames;
240 else
242 std::vector< OUString > aNames;
243 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
244 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
245 pStyle = aSSSIterator->Next() )
247 // we assume that we have only SdStyleSheets
248 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
249 aNames.push_back(pSdStyle->GetApiName());
251 return Sequence< OUString >( &(*aNames.begin()), aNames.size() );
255 sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName )
257 SolarMutexGuard aGuard;
258 throwIfDisposed();
260 if( !aName.isEmpty() )
262 if( mnFamily == SfxStyleFamily::Page )
264 PresStyleMap& rStyleSheets = mpImpl->getStyleSheets();
265 PresStyleMap::iterator iter( rStyleSheets.find(aName) );
266 return iter != rStyleSheets.end();
268 else
270 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
271 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
272 pStyle = aSSSIterator->Next() )
274 // we assume that we have only SdStyleSheets
275 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
276 if (pSdStyle->GetApiName() == aName)
278 return true;
284 return false;
287 // XElementAccess
289 Type SAL_CALL SdStyleFamily::getElementType()
291 return cppu::UnoType<XStyle>::get();
294 sal_Bool SAL_CALL SdStyleFamily::hasElements()
296 SolarMutexGuard aGuard;
297 throwIfDisposed();
299 if( mnFamily == SfxStyleFamily::Page )
301 return true;
303 else
305 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
306 if (aSSSIterator->First())
308 return true;
312 return false;
315 // XIndexAccess
317 sal_Int32 SAL_CALL SdStyleFamily::getCount()
319 SolarMutexGuard aGuard;
320 throwIfDisposed();
322 sal_Int32 nCount = 0;
323 if( mnFamily == SfxStyleFamily::Page )
325 return mpImpl->getStyleSheets().size();
327 else
329 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
330 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
331 pStyle = aSSSIterator->Next() )
333 nCount++;
337 return nCount;
340 Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index )
342 SolarMutexGuard aGuard;
343 throwIfDisposed();
345 if( Index >= 0 )
347 if( mnFamily == SfxStyleFamily::Page )
349 PresStyleMap& rStyleSheets = mpImpl->getStyleSheets();
350 if( Index < static_cast<sal_Int32>(rStyleSheets.size()) )
352 PresStyleMap::iterator iter( rStyleSheets.begin() );
353 std::advance(iter, Index);
354 return Any( Reference< XStyle >( (*iter).second.get() ) );
357 else
359 std::shared_ptr<SfxStyleSheetIterator> aSSSIterator = std::make_shared<SfxStyleSheetIterator>(mxPool.get(), mnFamily);
360 for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle;
361 pStyle = aSSSIterator->Next() )
363 // we assume that we have only SdStyleSheets
364 SdStyleSheet* pSdStyle = static_cast< SdStyleSheet* >( pStyle );
365 if( Index-- == 0 )
367 return Any( Reference< XStyle >( pSdStyle ) );
373 throw IndexOutOfBoundsException();
376 // XNameContainer
378 void SAL_CALL SdStyleFamily::insertByName( const OUString& rName, const Any& rElement )
380 SolarMutexGuard aGuard;
381 throwIfDisposed();
383 if(rName.isEmpty())
384 throw IllegalArgumentException();
386 SdStyleSheet* pStyle = GetValidNewSheet( rElement );
387 if( !pStyle->SetName( rName ) )
388 throw ElementExistException();
390 pStyle->SetApiName( rName );
391 mxPool->Insert( pStyle );
394 void SAL_CALL SdStyleFamily::removeByName( const OUString& rName )
396 SolarMutexGuard aGuard;
397 throwIfDisposed();
399 SdStyleSheet* pStyle = GetSheetByName( rName );
401 if( !pStyle->IsUserDefined() )
402 throw WrappedTargetException();
404 mxPool->Remove( pStyle );
407 // XNameReplace
409 void SAL_CALL SdStyleFamily::replaceByName( const OUString& rName, const Any& aElement )
411 SolarMutexGuard aGuard;
412 throwIfDisposed();
414 SdStyleSheet* pOldStyle = GetSheetByName( rName );
415 SdStyleSheet* pNewStyle = GetValidNewSheet( aElement );
417 mxPool->Remove( pOldStyle );
418 mxPool->Insert( pNewStyle );
421 // XSingleServiceFactory
423 Reference< XInterface > SAL_CALL SdStyleFamily::createInstance()
425 SolarMutexGuard aGuard;
426 throwIfDisposed();
428 if( mnFamily == SfxStyleFamily::Page )
430 throw IllegalAccessException();
432 return Reference<XInterface>(
433 static_cast<XStyle*>(SdStyleSheet::CreateEmptyUserStyle(*mxPool, mnFamily)));
436 Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( const Sequence< Any >& )
438 return createInstance();
441 // XComponent
443 void SAL_CALL SdStyleFamily::dispose( )
445 if( mxPool.is() )
446 mxPool.clear();
448 mpImpl.reset();
451 void SAL_CALL SdStyleFamily::addEventListener( const Reference< XEventListener >& )
455 void SAL_CALL SdStyleFamily::removeEventListener( const Reference< XEventListener >& )
459 // XPropertySet
461 Reference<XPropertySetInfo> SdStyleFamily::getPropertySetInfo()
463 OSL_FAIL( "###unexpected!" );
464 return Reference<XPropertySetInfo>();
467 void SdStyleFamily::setPropertyValue( const OUString& , const Any& )
469 OSL_FAIL( "###unexpected!" );
472 Any SdStyleFamily::getPropertyValue( const OUString& PropertyName )
474 if ( PropertyName != "DisplayName" )
476 throw UnknownPropertyException( "unknown property: " + PropertyName, static_cast<OWeakObject *>(this) );
479 SolarMutexGuard aGuard;
480 OUString sDisplayName;
481 switch( mnFamily )
483 case SfxStyleFamily::Page: sDisplayName = getName(); break;
484 case SfxStyleFamily::Frame: sDisplayName = SdResId(STR_CELL_STYLE_FAMILY); break;
485 default: sDisplayName = SdResId(STR_GRAPHICS_STYLE_FAMILY); break;
487 return Any( sDisplayName );
490 void SdStyleFamily::addPropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& )
492 OSL_FAIL( "###unexpected!" );
495 void SdStyleFamily::removePropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& )
497 OSL_FAIL( "###unexpected!" );
500 void SdStyleFamily::addVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& )
502 OSL_FAIL( "###unexpected!" );
505 void SdStyleFamily::removeVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& )
507 OSL_FAIL( "###unexpected!" );
510 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */