1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: CustomAnimationPreset.cxx,v $
10 * $Revision: 1.7.74.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include <com/sun/star/util/XCloneable.hpp>
34 #include <com/sun/star/util/XMacroExpander.hpp>
35 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/xml/sax/InputSource.hpp>
38 #include <com/sun/star/xml/sax/XParser.hpp>
39 #include <com/sun/star/xml/sax/SAXParseException.hpp>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/presentation/EffectPresetClass.hpp>
43 #include <com/sun/star/beans/NamedValue.hpp>
44 #include <tools/urlobj.hxx>
45 #include <unotools/streamwrap.hxx>
46 #include <comphelper/processfactory.hxx>
47 #include <svtools/pathoptions.hxx>
48 #include <tools/stream.hxx>
50 #include <tools/debug.hxx>
51 #include <rtl/uri.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vos/mutex.hxx>
54 #include <unotools/ucbstreamhelper.hxx>
55 #include <CustomAnimationPreset.hxx>
59 using namespace ::vos
;
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::animations
;
62 using namespace ::com::sun::star::presentation
;
64 using ::rtl::OUString
;
65 using ::com::sun::star::uno::UNO_QUERY
;
66 using ::com::sun::star::uno::UNO_QUERY_THROW
;
67 using ::com::sun::star::uno::Any
;
68 using ::com::sun::star::uno::Sequence
;
69 using ::com::sun::star::uno::Reference
;
70 using ::com::sun::star::uno::Exception
;
71 using ::com::sun::star::io::XInputStream
;
72 using ::com::sun::star::lang::XMultiServiceFactory
;
73 using ::com::sun::star::container::XNameAccess
;
74 using ::com::sun::star::beans::PropertyValue
;
75 using ::com::sun::star::util::XCloneable
;
76 using ::com::sun::star::beans::NamedValue
;
80 static Reference
< XNameAccess
> getNodeAccess( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
)
82 Reference
< XNameAccess
> xConfigAccess
;
86 Sequence
< Any
> aArgs( 1 );
87 PropertyValue aPropValue
;
88 aPropValue
.Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
89 aPropValue
.Value
<<= rNodePath
;
90 aArgs
[0] <<= aPropValue
;
92 xConfigAccess
= Reference
< XNameAccess
>::query(
93 xConfigProvider
->createInstanceWithArguments(
94 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" )),
100 DBG_ERROR( "sd::getNodeAccess(), Exception catched!" );
103 return xConfigAccess
;
106 void implImportLabels( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
, UStringMap
& rStringMap
)
110 Reference
< XNameAccess
> xConfigAccess( getNodeAccess( xConfigProvider
, rNodePath
) );
111 if( xConfigAccess
.is() )
113 OUString
aLabel( RTL_CONSTASCII_USTRINGPARAM( "Label" ) );
114 Reference
< XNameAccess
> xNameAccess
;
115 Sequence
< OUString
> aNames( xConfigAccess
->getElementNames() );
116 const OUString
* p
= aNames
.getConstArray();
117 sal_Int32 n
= aNames
.getLength();
120 xConfigAccess
->getByName( *p
) >>= xNameAccess
;
121 if( xNameAccess
.is() )
124 xNameAccess
->getByName( aLabel
) >>= aUIName
;
125 if( aUIName
.getLength() )
127 rStringMap
[ *p
] = aUIName
;
135 catch( lang::WrappedTargetException
& e
)
138 DBG_ERROR( "sd::implImportLabels(), WrappedTargetException catched!" );
140 catch( Exception
& e
)
143 DBG_ERROR( "sd::implImportLabels(), Exception catched!" );
147 CustomAnimationPreset::CustomAnimationPreset( CustomAnimationEffectPtr pEffect
)
149 maPresetId
= pEffect
->getPresetId();
150 maProperty
= pEffect
->getProperty();
151 mnPresetClass
= pEffect
->getPresetClass();
155 mfDuration
= pEffect
->getDuration();
156 maDefaultSubTyp
= pEffect
->getPresetSubType();
158 mbIsTextOnly
= false;
160 Sequence
< NamedValue
> aUserData( pEffect
->getNode()->getUserData() );
161 sal_Int32 nLength
= aUserData
.getLength();
162 const NamedValue
* p
= aUserData
.getConstArray();
166 if( p
->Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) )
176 void CustomAnimationPreset::add( CustomAnimationEffectPtr pEffect
)
178 maSubTypes
[ pEffect
->getPresetSubType() ] = pEffect
;
181 UStringList
CustomAnimationPreset::getSubTypes()
183 UStringList aSubTypes
;
185 if( maSubTypes
.size() > 1 )
187 EffectsSubTypeMap::iterator
aIter( maSubTypes
.begin() );
188 const EffectsSubTypeMap::iterator
aEnd( maSubTypes
.end() );
189 while( aIter
!= aEnd
)
190 aSubTypes
.push_back( (*aIter
++).first
);
196 Reference
< XAnimationNode
> CustomAnimationPreset::create( const rtl::OUString
& rstrSubType
)
200 OUString
strSubType( rstrSubType
);
201 if( strSubType
.getLength() == 0 )
202 strSubType
= maDefaultSubTyp
;
204 CustomAnimationEffectPtr pEffect
= maSubTypes
[strSubType
];
207 Reference
< XCloneable
> xCloneable( pEffect
->getNode(), UNO_QUERY_THROW
);
208 Reference
< XAnimationNode
> xNode( xCloneable
->createClone(), UNO_QUERY_THROW
);
212 catch( Exception
& e
)
215 DBG_ERROR( "sd::CustomAnimationPresets::create(), exception catched!" );
218 Reference
< XAnimationNode
> xNode
;
222 UStringList
CustomAnimationPreset::getProperties() const
224 String
aProperties( maProperty
);
225 USHORT nTokens
= aProperties
.GetTokenCount();
227 UStringList aPropertyList
;
228 for( nToken
= 0; nToken
< nTokens
; nToken
++ )
229 aPropertyList
.push_back( aProperties
.GetToken( nToken
) );
231 return aPropertyList
;
235 bool CustomAnimationPreset::hasProperty( const OUString
& rProperty
)const
237 String
aProperties( maProperty
);
238 String
aProperty( rProperty
);
239 USHORT nTokens
= aProperties
.GetTokenCount();
241 for( nToken
= 0; nToken
< nTokens
; nToken
++ )
243 if( aProperties
.GetToken( nToken
) == aProperty
)
250 CustomAnimationPresets::CustomAnimationPresets()
254 CustomAnimationPresets::~CustomAnimationPresets()
258 void CustomAnimationPresets::init()
263 Reference
< XAnimationNode
> implImportEffects( const Reference
< XMultiServiceFactory
>& xServiceFactory
, const OUString
& rPath
)
265 Reference
< XAnimationNode
> xRootNode
;
270 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( rPath
, STREAM_READ
);
271 Reference
<XInputStream
> xInputStream( new utl::OInputStreamWrapper( pIStm
, sal_True
) );
273 // prepare ParserInputSrouce
274 xml::sax::InputSource aParserInput
;
275 aParserInput
.sSystemId
= rPath
;
276 aParserInput
.aInputStream
= xInputStream
;
279 Reference
< xml::sax::XParser
> xParser(
280 xServiceFactory
->createInstance(
281 OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
284 DBG_ASSERT( xParser
.is(), "Can't create parser" );
289 Reference
< xml::sax::XDocumentHandler
> xFilter(
290 xServiceFactory
->createInstance(
291 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Xmloff.AnimationsImport" ) ) ), UNO_QUERY
);
293 DBG_ASSERT( xFilter
.is(), "Can't instantiate filter component." );
297 // connect parser and filter
298 xParser
->setDocumentHandler( xFilter
);
300 // finally, parser the stream
301 xParser
->parseStream( aParserInput
);
303 Reference
< XAnimationNodeSupplier
> xAnimationNodeSupplier( xFilter
, UNO_QUERY
);
304 if( xAnimationNodeSupplier
.is() )
305 xRootNode
= xAnimationNodeSupplier
->getAnimationNode();
307 catch( xml::sax::SAXParseException
& r
)
310 DBG_ERROR( "sd::implImportEffects(), SAXParseException catched!" );
312 catch( xml::sax::SAXException
& r
)
315 DBG_ERROR( "sd::implImportEffects(), SAXException catched!" );
317 catch( io::IOException
& r
)
320 DBG_ERROR( "sd::implImportEffects(), IOException catched!" );
322 catch( Exception
& r
)
325 DBG_ERROR( "sd::importEffects(), Exception catched!" );
331 #define EXPAND_PROTOCOL "vnd.sun.star.expand:"
333 void CustomAnimationPresets::importEffects()
337 // Get service factory
338 Reference
< XMultiServiceFactory
> xServiceFactory( comphelper::getProcessServiceFactory() );
339 DBG_ASSERT( xServiceFactory
.is(), "sd::CustomAnimationPresets::import(), got no service manager" );
340 if( !xServiceFactory
.is() )
343 uno::Reference
< beans::XPropertySet
> xProps( xServiceFactory
, UNO_QUERY
);
344 uno::Reference
< uno::XComponentContext
> xContext
;
345 xProps
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext
;
347 uno::Reference
< util::XMacroExpander
> xMacroExpander
;
349 xMacroExpander
.set( xContext
->getValueByName(
350 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))),
353 Reference
< XMultiServiceFactory
> xConfigProvider(
354 xServiceFactory
->createInstance(
355 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))),
358 // read path to transition effects files from config
359 Any propValue
= uno::makeAny(
360 beans::PropertyValue(
361 OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )), -1,
362 uno::makeAny( OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/Misc") )),
363 beans::PropertyState_DIRECT_VALUE
) );
365 Reference
<container::XNameAccess
> xNameAccess(
366 xConfigProvider
->createInstanceWithArguments(
367 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")),
368 Sequence
<Any
>( &propValue
, 1 ) ), UNO_QUERY_THROW
);
369 uno::Sequence
< rtl::OUString
> aFiles
;
370 xNameAccess
->getByName(
371 OUString( RTL_CONSTASCII_USTRINGPARAM("EffectFiles"))) >>= aFiles
;
373 for( sal_Int32 i
=0; i
<aFiles
.getLength(); ++i
)
375 rtl::OUString aURL
= aFiles
[i
];
376 if( aURL
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL
)) == 0 )
379 rtl::OUString
aMacro( aURL
.copy( sizeof ( EXPAND_PROTOCOL
) -1 ) );
380 // decode uric class chars
381 aMacro
= rtl::Uri::decode( aMacro
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
382 // expand macro string
383 aURL
= xMacroExpander
->expandMacros( aMacro
);
386 mxRootNode
= implImportEffects( xServiceFactory
, aURL
);
388 if( mxRootNode
.is() )
390 Reference
< XTimeContainer
> xRootContainer( mxRootNode
, UNO_QUERY_THROW
);
391 EffectSequenceHelper
aSequence( xRootContainer
);
393 EffectSequence::iterator
aIter( aSequence
.getBegin() );
394 const EffectSequence::iterator
aEnd( aSequence
.getEnd() );
396 while( aIter
!= aEnd
)
398 CustomAnimationEffectPtr pEffect
= (*aIter
);
400 const OUString
aPresetId( pEffect
->getPresetId() );
401 CustomAnimationPresetPtr pDescriptor
= getEffectDescriptor( aPresetId
);
402 if( pDescriptor
.get() )
403 pDescriptor
->add( pEffect
);
406 pDescriptor
.reset( new CustomAnimationPreset( pEffect
) );
407 pDescriptor
->maLabel
= getUINameForPresetId( pEffect
->getPresetId() );
408 maEffectDiscriptorMap
[aPresetId
] = pDescriptor
;
416 catch( xml::sax::SAXParseException
& r
)
419 DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXParseException catched!" );
421 catch( xml::sax::SAXException
& r
)
424 DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXException catched!" );
426 catch( io::IOException
& r
)
429 DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), IOException catched!" );
431 catch( Exception
& r
)
434 DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), Exception catched!" );
438 void CustomAnimationPresets::importResources()
442 // Get service factory
443 Reference
< XMultiServiceFactory
> xServiceFactory( comphelper::getProcessServiceFactory() );
444 DBG_ASSERT( xServiceFactory
.is(), "sd::CustomAnimationPresets::import(), got no service manager" );
445 if( !xServiceFactory
.is() )
448 Reference
< XMultiServiceFactory
> xConfigProvider(
449 xServiceFactory
->createInstance(
450 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))),
453 const OUString
aPropertyPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Properties" ) );
454 implImportLabels( xConfigProvider
, aPropertyPath
, maPropertyNameMap
);
456 const OUString
aEffectsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Effects" ) );
457 implImportLabels( xConfigProvider
, aEffectsPath
, maEffectNameMap
);
461 const OUString
aEntrancePath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Entrance" ) );
462 importPresets( xConfigProvider
, aEntrancePath
, maEntrancePresets
);
464 const OUString
aEmphasisPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Emphasis" ) );
465 importPresets( xConfigProvider
, aEmphasisPath
, maEmphasisPresets
);
467 const OUString
aExitPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Exit" ) );
468 importPresets( xConfigProvider
, aExitPath
, maExitPresets
);
470 const OUString
aMotionPathsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/MotionPaths" ) );
471 importPresets( xConfigProvider
, aMotionPathsPath
, maMotionPathsPresets
);
473 const OUString
aMiscPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Misc" ) );
474 importPresets( xConfigProvider
, aMiscPath
, maMiscPresets
);
476 catch( lang::WrappedTargetException
& e
)
479 DBG_ERROR( "sd::CustomAnimationPresets::importResources(), WrappedTargetException catched!" );
481 catch( Exception
& e
)
484 DBG_ERROR( "sd::CustomAnimationPresets::importResources(), Exception catched!" );
488 void CustomAnimationPresets::importPresets( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
, PresetCategoryList
& rPresetMap
)
491 String aMissedPresetIds
;
496 Reference
< XNameAccess
> xTypeAccess( getNodeAccess( xConfigProvider
, rNodePath
) );
497 if( xTypeAccess
.is() )
499 Reference
< XNameAccess
> xCategoryAccess
;
500 const OUString
aEffectsName( RTL_CONSTASCII_USTRINGPARAM( "Effects" ) );
501 const OUString
aLabelName( RTL_CONSTASCII_USTRINGPARAM( "Label" ) );
503 Sequence
< OUString
> aNames( xTypeAccess
->getElementNames() );
504 const OUString
* p
= aNames
.getConstArray();
505 sal_Int32 n
= aNames
.getLength();
508 xTypeAccess
->getByName( *p
) >>= xCategoryAccess
;
510 if( xCategoryAccess
.is() && xCategoryAccess
->hasByName( aLabelName
) && xCategoryAccess
->hasByName( aEffectsName
) )
513 xCategoryAccess
->getByName( aLabelName
) >>= aLabel
;
515 Sequence
< OUString
> aEffects
;
516 xCategoryAccess
->getByName( aEffectsName
) >>= aEffects
;
518 EffectDescriptorList aEffectsList
;
520 const OUString
* pEffectNames
= aEffects
.getConstArray();
521 sal_Int32 nEffectCount
= aEffects
.getLength();
522 while( nEffectCount
-- )
524 CustomAnimationPresetPtr pEffect
= getEffectDescriptor( *pEffectNames
);
527 aEffectsList
.push_back( pEffect
);
532 aMissedPresetIds
+= String(*pEffectNames
);
533 aMissedPresetIds
+= String( RTL_CONSTASCII_USTRINGPARAM("\n") );
538 rPresetMap
.push_back( PresetCategoryPtr( new PresetCategory( aLabel
, aEffectsList
) ) );
545 catch( Exception
& e
)
548 DBG_ERROR( "sd::CustomAnimationPresets::importPresets(), Exception catched!" );
552 if( aMissedPresetIds
.Len() )
554 ByteString
aTmp( "sd::CustomAnimationPresets::importPresets(), invalid preset id!\n" );
555 aTmp
+= ByteString( aMissedPresetIds
, RTL_TEXTENCODING_ASCII_US
);
556 DBG_ERROR( aTmp
.GetBuffer() );
561 CustomAnimationPresetPtr
CustomAnimationPresets::getEffectDescriptor( const rtl::OUString
& rPresetId
) const
563 EffectDescriptorMap::const_iterator
aIter( maEffectDiscriptorMap
.find( rPresetId
) );
565 if( aIter
!= maEffectDiscriptorMap
.end() )
567 return (*aIter
).second
;
571 return CustomAnimationPresetPtr((CustomAnimationPreset
*)0);
575 const rtl::OUString
& CustomAnimationPresets::getUINameForPresetId( const rtl::OUString
& rPresetId
) const
577 return translateName( rPresetId
, maEffectNameMap
);
580 const rtl::OUString
& CustomAnimationPresets::getUINameForProperty( const rtl::OUString
& rPresetId
) const
582 return translateName( rPresetId
, maPropertyNameMap
);
585 const rtl::OUString
& CustomAnimationPresets::translateName( const rtl::OUString
& rId
, const UStringMap
& rNameMap
) const
587 UStringMap::const_iterator
aIter( rNameMap
.find( rId
) );
589 if( aIter
!= rNameMap
.end() )
591 return (*aIter
).second
;
598 void CustomAnimationPresets::changePresetSubType( CustomAnimationEffectPtr pEffect
, const rtl::OUString
& rPresetSubType
) const
600 if( pEffect
.get() && pEffect
->getPresetSubType() != rPresetSubType
)
602 CustomAnimationPresetPtr
pDescriptor( getEffectDescriptor( pEffect
->getPresetId() ) );
604 if( pDescriptor
.get() )
606 Reference
< XAnimationNode
> xNewNode( pDescriptor
->create( rPresetSubType
) );
608 pEffect
->replaceNode( xNewNode
);
613 CustomAnimationPresets
* CustomAnimationPresets::mpCustomAnimationPresets
= 0;
615 const CustomAnimationPresets
& CustomAnimationPresets::getCustomAnimationPresets()
617 if( !mpCustomAnimationPresets
)
619 OGuard
aGuard( Application::GetSolarMutex() );
621 if( !mpCustomAnimationPresets
)
623 mpCustomAnimationPresets
= new sd::CustomAnimationPresets();
624 mpCustomAnimationPresets
->init();
628 return *mpCustomAnimationPresets
;
631 Reference
< XAnimationNode
> CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass
) const
633 Reference
< XAnimationNode
> xNode
;
635 const PresetCategoryList
* pCategoryList
= 0;
636 switch( nPresetClass
)
638 case EffectPresetClass::ENTRANCE
: pCategoryList
= &maEntrancePresets
; break;
639 case EffectPresetClass::EXIT
: pCategoryList
= &maExitPresets
; break;
640 case EffectPresetClass::EMPHASIS
: pCategoryList
= &maEmphasisPresets
; break;
641 case EffectPresetClass::MOTIONPATH
: pCategoryList
= &maMotionPathsPresets
; break;
646 if( pCategoryList
&& pCategoryList
->size() )
648 sal_Int32 nCategory
= (rand() * pCategoryList
->size() / RAND_MAX
);
650 PresetCategoryPtr pCategory
= (*pCategoryList
)[nCategory
];
651 if( pCategory
.get() && pCategory
->maEffects
.size() )
653 sal_Int32 nDescriptor
= (rand() * pCategory
->maEffects
.size() / RAND_MAX
);
654 CustomAnimationPresetPtr pPreset
= pCategory
->maEffects
[nDescriptor
];
657 UStringList aSubTypes
= pPreset
->getSubTypes();
660 if( aSubTypes
.size() )
662 sal_Int32 nSubType
= (rand() * aSubTypes
.size() / RAND_MAX
);
663 aSubType
= aSubTypes
[nSubType
];
665 xNode
= pPreset
->create( aSubType
);