xref: /trunk/main/sd/source/core/CustomAnimationPreset.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 #include <com/sun/star/util/XCloneable.hpp>
31 #include <com/sun/star/util/XMacroExpander.hpp>
32 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/xml/sax/InputSource.hpp>
35 #include <com/sun/star/xml/sax/XParser.hpp>
36 #include <com/sun/star/xml/sax/SAXParseException.hpp>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/presentation/EffectPresetClass.hpp>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <tools/urlobj.hxx>
42 #include <unotools/streamwrap.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <unotools/pathoptions.hxx>
45 #include <tools/stream.hxx>
46 
47 #include <tools/debug.hxx>
48 #include <rtl/uri.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vos/mutex.hxx>
51 #include <unotools/ucbstreamhelper.hxx>
52 #include <CustomAnimationPreset.hxx>
53 
54 #include <algorithm>
55 
56 using namespace ::vos;
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::animations;
59 using namespace ::com::sun::star::presentation;
60 
61 using ::rtl::OUString;
62 using ::com::sun::star::uno::UNO_QUERY;
63 using ::com::sun::star::uno::UNO_QUERY_THROW;
64 using ::com::sun::star::uno::Any;
65 using ::com::sun::star::uno::Sequence;
66 using ::com::sun::star::uno::Reference;
67 using ::com::sun::star::uno::Exception;
68 using ::com::sun::star::io::XInputStream;
69 using ::com::sun::star::lang::XMultiServiceFactory;
70 using ::com::sun::star::container::XNameAccess;
71 using ::com::sun::star::beans::PropertyValue;
72 using ::com::sun::star::util::XCloneable;
73 using ::com::sun::star::beans::NamedValue;
74 
75 namespace sd {
76 
77 static Reference< XNameAccess > getNodeAccess( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath )
78 {
79     Reference< XNameAccess > xConfigAccess;
80 
81     try
82     {
83         Sequence< Any > aArgs( 1 );
84         PropertyValue   aPropValue;
85         aPropValue.Name  = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
86         aPropValue.Value <<= rNodePath;
87         aArgs[0] <<= aPropValue;
88 
89         xConfigAccess = Reference< XNameAccess >::query(
90             xConfigProvider->createInstanceWithArguments(
91                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" )),
92                 aArgs ));
93     }
94     catch( Exception& e )
95     {
96         (void)e;
97         DBG_ERROR( "sd::getNodeAccess(), Exception catched!" );
98     }
99 
100     return xConfigAccess;
101 }
102 
103 void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap )
104 {
105     try
106     {
107         Reference< XNameAccess > xConfigAccess( getNodeAccess( xConfigProvider, rNodePath ) );
108         if( xConfigAccess.is() )
109         {
110             OUString aLabel( RTL_CONSTASCII_USTRINGPARAM( "Label" ) );
111             Reference< XNameAccess > xNameAccess;
112             Sequence< OUString > aNames( xConfigAccess->getElementNames() );
113             const OUString* p = aNames.getConstArray();
114             sal_Int32 n = aNames.getLength();
115             while(n--)
116             {
117                 xConfigAccess->getByName( *p ) >>= xNameAccess;
118                 if( xNameAccess.is() )
119                 {
120                     OUString aUIName;
121                     xNameAccess->getByName( aLabel ) >>= aUIName;
122                     if( aUIName.getLength() )
123                     {
124                         rStringMap[ *p ] = aUIName;
125                     }
126                 }
127 
128                 p++;
129             }
130         }
131     }
132     catch( lang::WrappedTargetException& e )
133     {
134         (void)e;
135         DBG_ERROR( "sd::implImportLabels(), WrappedTargetException catched!" );
136     }
137     catch( Exception& e )
138     {
139         (void)e;
140         DBG_ERROR( "sd::implImportLabels(), Exception catched!" );
141     }
142 }
143 
144 CustomAnimationPreset::CustomAnimationPreset( CustomAnimationEffectPtr pEffect )
145 {
146     maPresetId = pEffect->getPresetId();
147     maProperty = pEffect->getProperty();
148     mnPresetClass = pEffect->getPresetClass();
149 
150     add( pEffect );
151 
152     mfDuration = pEffect->getDuration();
153     maDefaultSubTyp = pEffect->getPresetSubType();
154 
155     mbIsTextOnly = false;
156 
157     Sequence< NamedValue > aUserData( pEffect->getNode()->getUserData() );
158     sal_Int32 nLength = aUserData.getLength();
159     const NamedValue* p = aUserData.getConstArray();
160 
161     while( nLength-- )
162     {
163         if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) )
164         {
165             mbIsTextOnly = true;
166             break;
167         }
168         p++;
169     }
170 
171 }
172 
173 void CustomAnimationPreset::add( CustomAnimationEffectPtr pEffect )
174 {
175     maSubTypes[ pEffect->getPresetSubType() ] = pEffect;
176 }
177 
178 UStringList CustomAnimationPreset::getSubTypes()
179 {
180     UStringList aSubTypes;
181 
182     if( maSubTypes.size() > 1 )
183     {
184         EffectsSubTypeMap::iterator aIter( maSubTypes.begin() );
185         const EffectsSubTypeMap::iterator aEnd( maSubTypes.end() );
186         while( aIter != aEnd )
187             aSubTypes.push_back( (*aIter++).first );
188     }
189 
190     return aSubTypes;
191 }
192 
193 Reference< XAnimationNode > CustomAnimationPreset::create( const rtl::OUString& rstrSubType )
194 {
195     try
196     {
197         OUString strSubType( rstrSubType );
198         if( strSubType.getLength() == 0 )
199             strSubType = maDefaultSubTyp;
200 
201         CustomAnimationEffectPtr pEffect = maSubTypes[strSubType];
202         if( pEffect.get() )
203         {
204             Reference< XCloneable > xCloneable( pEffect->getNode(), UNO_QUERY_THROW );
205             Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW );
206             return xNode;
207         }
208     }
209     catch( Exception& e )
210     {
211         (void)e;
212         DBG_ERROR( "sd::CustomAnimationPresets::create(), exception catched!" );
213     }
214 
215     Reference< XAnimationNode > xNode;
216     return xNode;
217 }
218 
219 UStringList CustomAnimationPreset::getProperties() const
220 {
221     String aProperties( maProperty );
222     sal_uInt16 nTokens = aProperties.GetTokenCount();
223     sal_uInt16 nToken;
224     UStringList aPropertyList;
225     for( nToken = 0; nToken < nTokens; nToken++ )
226         aPropertyList.push_back( aProperties.GetToken( nToken ) );
227 
228     return aPropertyList;
229 
230 }
231 
232 bool CustomAnimationPreset::hasProperty( const OUString& rProperty )const
233 {
234     String aProperties( maProperty );
235     String aProperty( rProperty );
236     sal_uInt16 nTokens = aProperties.GetTokenCount();
237     sal_uInt16 nToken;
238     for( nToken = 0; nToken < nTokens; nToken++ )
239     {
240         if( aProperties.GetToken( nToken ) == aProperty )
241             return true;
242     }
243 
244     return false;
245 }
246 
247 CustomAnimationPresets::CustomAnimationPresets()
248 {
249 }
250 
251 CustomAnimationPresets::~CustomAnimationPresets()
252 {
253 }
254 
255 void CustomAnimationPresets::init()
256 {
257     importResources();
258 }
259 
260 Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xServiceFactory, const OUString& rPath )
261 {
262     Reference< XAnimationNode > xRootNode;
263 
264     try
265     {
266         // create stream
267         SvStream*   pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ );
268         Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( pIStm, sal_True ) );
269 
270         // prepare ParserInputSrouce
271         xml::sax::InputSource aParserInput;
272         aParserInput.sSystemId = rPath;
273         aParserInput.aInputStream = xInputStream;
274 
275         // get parser
276         Reference< xml::sax::XParser > xParser(
277             xServiceFactory->createInstance(
278                 OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
279             UNO_QUERY );
280 
281         DBG_ASSERT( xParser.is(), "Can't create parser" );
282         if( !xParser.is() )
283             return xRootNode;
284 
285         // get filter
286         Reference< xml::sax::XDocumentHandler > xFilter(
287             xServiceFactory->createInstance(
288                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Xmloff.AnimationsImport" ) ) ), UNO_QUERY );
289 
290         DBG_ASSERT( xFilter.is(), "Can't instantiate filter component." );
291         if( !xFilter.is() )
292             return xRootNode;
293 
294         // connect parser and filter
295         xParser->setDocumentHandler( xFilter );
296 
297         // finally, parser the stream
298         xParser->parseStream( aParserInput );
299 
300         Reference< XAnimationNodeSupplier > xAnimationNodeSupplier( xFilter, UNO_QUERY );
301         if( xAnimationNodeSupplier.is() )
302             xRootNode = xAnimationNodeSupplier->getAnimationNode();
303     }
304     catch( xml::sax::SAXParseException& r )
305     {
306         (void)r;
307         DBG_ERROR( "sd::implImportEffects(), SAXParseException catched!" );
308     }
309     catch( xml::sax::SAXException& r )
310     {
311         (void)r;
312         DBG_ERROR( "sd::implImportEffects(), SAXException catched!" );
313     }
314     catch( io::IOException& r )
315     {
316         (void)r;
317         DBG_ERROR( "sd::implImportEffects(), IOException catched!" );
318     }
319     catch( Exception& r )
320     {
321         (void)r;
322         DBG_ERROR( "sd::importEffects(), Exception catched!" );
323     }
324 
325     return xRootNode;
326 }
327 
328 #define EXPAND_PROTOCOL "vnd.sun.star.expand:"
329 
330 void CustomAnimationPresets::importEffects()
331 {
332     try
333     {
334         // Get service factory
335         Reference< XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() );
336         DBG_ASSERT( xServiceFactory.is(), "sd::CustomAnimationPresets::import(), got no service manager" );
337         if( !xServiceFactory.is() )
338             return;
339 
340         uno::Reference< beans::XPropertySet > xProps( xServiceFactory, UNO_QUERY );
341         uno::Reference< uno::XComponentContext > xContext;
342         xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
343 
344         uno::Reference< util::XMacroExpander > xMacroExpander;
345         if( xContext.is() )
346             xMacroExpander.set( xContext->getValueByName(
347                                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))),
348                                 UNO_QUERY );
349 
350         Reference< XMultiServiceFactory > xConfigProvider(
351             xServiceFactory->createInstance(
352                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))),
353             UNO_QUERY_THROW );
354 
355         // read path to transition effects files from config
356         Any propValue = uno::makeAny(
357             beans::PropertyValue(
358                 OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )), -1,
359                 uno::makeAny( OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/Misc") )),
360                 beans::PropertyState_DIRECT_VALUE ) );
361 
362         Reference<container::XNameAccess> xNameAccess(
363             xConfigProvider->createInstanceWithArguments(
364                 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")),
365                 Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW );
366         uno::Sequence< rtl::OUString > aFiles;
367         xNameAccess->getByName(
368             OUString( RTL_CONSTASCII_USTRINGPARAM("EffectFiles"))) >>= aFiles;
369 
370         for( sal_Int32 i=0; i<aFiles.getLength(); ++i )
371         {
372             rtl::OUString aURL = aFiles[i];
373             if( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 )
374             {
375                 // cut protocol
376                 rtl::OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) );
377                 // decode uric class chars
378                 aMacro = rtl::Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
379                 // expand macro string
380                 aURL = xMacroExpander->expandMacros( aMacro );
381             }
382 
383             mxRootNode = implImportEffects( xServiceFactory, aURL );
384 
385             if( mxRootNode.is() )
386             {
387                 Reference< XTimeContainer > xRootContainer( mxRootNode, UNO_QUERY_THROW );
388                 EffectSequenceHelper aSequence( xRootContainer );
389 
390                 EffectSequence::iterator aIter( aSequence.getBegin() );
391                 const EffectSequence::iterator aEnd( aSequence.getEnd() );
392 
393                 while( aIter != aEnd )
394                 {
395                     CustomAnimationEffectPtr pEffect = (*aIter);
396 
397                     const OUString aPresetId( pEffect->getPresetId() );
398                     CustomAnimationPresetPtr pDescriptor = getEffectDescriptor( aPresetId );
399                     if( pDescriptor.get() )
400                         pDescriptor->add( pEffect );
401                     else
402                     {
403                         pDescriptor.reset( new CustomAnimationPreset( pEffect ) );
404                         pDescriptor->maLabel = getUINameForPresetId( pEffect->getPresetId() );
405                         maEffectDiscriptorMap[aPresetId] = pDescriptor;
406                     }
407 
408                     aIter++;
409                 }
410             }
411         }
412     }
413     catch( xml::sax::SAXParseException& r )
414     {
415         (void)r;
416         DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXParseException catched!" );
417     }
418     catch( xml::sax::SAXException& r )
419     {
420         (void)r;
421         DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXException catched!" );
422     }
423     catch( io::IOException& r )
424     {
425         (void)r;
426         DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), IOException catched!" );
427     }
428     catch( Exception& r )
429     {
430         (void)r;
431         DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), Exception catched!" );
432     }
433 }
434 
435 void CustomAnimationPresets::importResources()
436 {
437     try
438     {
439         // Get service factory
440         Reference< XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() );
441         DBG_ASSERT( xServiceFactory.is(), "sd::CustomAnimationPresets::import(), got no service manager" );
442         if( !xServiceFactory.is() )
443             return;
444 
445         Reference< XMultiServiceFactory > xConfigProvider(
446             xServiceFactory->createInstance(
447                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))),
448             UNO_QUERY );
449 
450         const OUString aPropertyPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Properties" ) );
451         implImportLabels( xConfigProvider, aPropertyPath, maPropertyNameMap );
452 
453         const OUString aEffectsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Effects" ) );
454         implImportLabels( xConfigProvider, aEffectsPath, maEffectNameMap );
455 
456         importEffects();
457 
458         const OUString aEntrancePath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Entrance" ) );
459         importPresets( xConfigProvider, aEntrancePath, maEntrancePresets );
460 
461         const OUString aEmphasisPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Emphasis" ) );
462         importPresets( xConfigProvider, aEmphasisPath, maEmphasisPresets );
463 
464         const OUString aExitPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Exit" ) );
465         importPresets( xConfigProvider, aExitPath, maExitPresets );
466 
467         const OUString aMotionPathsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/MotionPaths" ) );
468         importPresets( xConfigProvider, aMotionPathsPath, maMotionPathsPresets );
469 
470         const OUString aMiscPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Misc" ) );
471         importPresets( xConfigProvider, aMiscPath, maMiscPresets );
472     }
473     catch( lang::WrappedTargetException& e )
474     {
475         (void)e;
476         DBG_ERROR( "sd::CustomAnimationPresets::importResources(), WrappedTargetException catched!" );
477     }
478     catch( Exception& e )
479     {
480         (void)e;
481         DBG_ERROR( "sd::CustomAnimationPresets::importResources(), Exception catched!" );
482     }
483 }
484 
485 void CustomAnimationPresets::importPresets( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, PresetCategoryList& rPresetMap  )
486 {
487 #ifdef DEBUG
488     String aMissedPresetIds;
489 #endif
490 
491     try
492     {
493         Reference< XNameAccess > xTypeAccess( getNodeAccess( xConfigProvider, rNodePath ) );
494         if( xTypeAccess.is() )
495         {
496             Reference< XNameAccess > xCategoryAccess;
497             const OUString aEffectsName( RTL_CONSTASCII_USTRINGPARAM( "Effects" ) );
498             const OUString aLabelName( RTL_CONSTASCII_USTRINGPARAM( "Label" ) );
499 
500             Sequence< OUString > aNames( xTypeAccess->getElementNames() );
501             const OUString* p = aNames.getConstArray();
502             sal_Int32 n = aNames.getLength();
503             while(n--)
504             {
505                 xTypeAccess->getByName( *p ) >>= xCategoryAccess;
506 
507                 if( xCategoryAccess.is() && xCategoryAccess->hasByName( aLabelName ) && xCategoryAccess->hasByName( aEffectsName ) )
508                 {
509                     OUString aLabel;
510                     xCategoryAccess->getByName( aLabelName ) >>= aLabel;
511 
512                     Sequence< OUString > aEffects;
513                     xCategoryAccess->getByName( aEffectsName ) >>= aEffects;
514 
515                     EffectDescriptorList aEffectsList;
516 
517                     const OUString* pEffectNames = aEffects.getConstArray();
518                     sal_Int32 nEffectCount = aEffects.getLength();
519                     while( nEffectCount-- )
520                     {
521                         CustomAnimationPresetPtr pEffect = getEffectDescriptor( *pEffectNames );
522                         if( pEffect.get() )
523                         {
524                             aEffectsList.push_back( pEffect );
525                         }
526 #ifdef DEBUG
527                         else
528                         {
529                             aMissedPresetIds += String(*pEffectNames);
530                             aMissedPresetIds += String( RTL_CONSTASCII_USTRINGPARAM("\n") );
531                         }
532 #endif
533                         pEffectNames++;
534                     }
535                     rPresetMap.push_back( PresetCategoryPtr( new PresetCategory( aLabel, aEffectsList ) ) );
536                 }
537 
538                 p++;
539             }
540         }
541     }
542     catch( Exception& e )
543     {
544         (void)e;
545         DBG_ERROR( "sd::CustomAnimationPresets::importPresets(), Exception catched!" );
546     }
547 
548 #ifdef DEBUG
549     if( aMissedPresetIds.Len() )
550     {
551         ByteString aTmp( "sd::CustomAnimationPresets::importPresets(), invalid preset id!\n" );
552         aTmp += ByteString( aMissedPresetIds, RTL_TEXTENCODING_ASCII_US );
553         DBG_ERROR( aTmp.GetBuffer() );
554     }
555 #endif
556 }
557 
558 CustomAnimationPresetPtr CustomAnimationPresets::getEffectDescriptor( const rtl::OUString& rPresetId ) const
559 {
560     EffectDescriptorMap::const_iterator aIter( maEffectDiscriptorMap.find( rPresetId ) );
561 
562     if( aIter != maEffectDiscriptorMap.end() )
563     {
564         return (*aIter).second;
565     }
566     else
567     {
568         return CustomAnimationPresetPtr((CustomAnimationPreset*)0);
569     }
570 }
571 
572 const rtl::OUString& CustomAnimationPresets::getUINameForPresetId( const rtl::OUString& rPresetId ) const
573 {
574     return translateName( rPresetId, maEffectNameMap );
575 }
576 
577 const rtl::OUString& CustomAnimationPresets::getUINameForProperty( const rtl::OUString& rPresetId ) const
578 {
579     return translateName( rPresetId, maPropertyNameMap );
580 }
581 
582 const rtl::OUString& CustomAnimationPresets::translateName( const rtl::OUString& rId, const UStringMap& rNameMap ) const
583 {
584     UStringMap::const_iterator aIter( rNameMap.find( rId ) );
585 
586     if( aIter != rNameMap.end() )
587     {
588         return (*aIter).second;
589     }
590     else
591     {
592         return rId;
593     }
594 }
595 void CustomAnimationPresets::changePresetSubType( CustomAnimationEffectPtr pEffect, const rtl::OUString& rPresetSubType ) const
596 {
597     if( pEffect.get() && pEffect->getPresetSubType() != rPresetSubType )
598     {
599         CustomAnimationPresetPtr pDescriptor( getEffectDescriptor( pEffect->getPresetId() ) );
600 
601         if( pDescriptor.get() )
602         {
603             Reference< XAnimationNode > xNewNode( pDescriptor->create( rPresetSubType ) );
604             if( xNewNode.is() )
605                 pEffect->replaceNode( xNewNode );
606         }
607     }
608 }
609 
610 CustomAnimationPresets* CustomAnimationPresets::mpCustomAnimationPresets = 0;
611 
612 const CustomAnimationPresets& CustomAnimationPresets::getCustomAnimationPresets()
613 {
614     if( !mpCustomAnimationPresets )
615     {
616         OGuard aGuard( Application::GetSolarMutex() );
617 
618         if( !mpCustomAnimationPresets )
619         {
620             mpCustomAnimationPresets = new sd::CustomAnimationPresets();
621             mpCustomAnimationPresets->init();
622         }
623     }
624 
625     return *mpCustomAnimationPresets;
626 }
627 
628 Reference< XAnimationNode > CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass ) const
629 {
630     Reference< XAnimationNode > xNode;
631 
632     const PresetCategoryList* pCategoryList = 0;
633     switch( nPresetClass )
634     {
635     case EffectPresetClass::ENTRANCE:   pCategoryList = &maEntrancePresets; break;
636     case EffectPresetClass::EXIT:       pCategoryList = &maExitPresets; break;
637     case EffectPresetClass::EMPHASIS:   pCategoryList = &maEmphasisPresets; break;
638     case EffectPresetClass::MOTIONPATH: pCategoryList = &maMotionPathsPresets; break;
639     default:
640         pCategoryList = 0;
641     }
642 
643     if( pCategoryList && pCategoryList->size() )
644     {
645         sal_Int32 nCategory = (rand() * pCategoryList->size() / RAND_MAX);
646 
647         PresetCategoryPtr pCategory = (*pCategoryList)[nCategory];
648         if( pCategory.get() && !pCategory->maEffects.empty() )
649         {
650             sal_Int32 nDescriptor = (rand() * pCategory->maEffects.size() / RAND_MAX);
651             CustomAnimationPresetPtr pPreset = pCategory->maEffects[nDescriptor];
652             if( pPreset.get() )
653             {
654                 UStringList aSubTypes = pPreset->getSubTypes();
655 
656                 OUString aSubType;
657                 if( !aSubTypes.empty() )
658                 {
659                     sal_Int32 nSubType = (rand() * aSubTypes.size() / RAND_MAX);
660                     aSubType = aSubTypes[nSubType];
661                 }
662                 xNode = pPreset->create( aSubType );
663             }
664         }
665     }
666 
667     return xNode;
668 }
669 
670 
671 }
672 
673