1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/util/XCloneable.hpp>
21 #include <com/sun/star/util/theMacroExpander.hpp>
22 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
23 #include <com/sun/star/container/XNameAccess.hpp>
24 #include <com/sun/star/configuration/theDefaultProvider.hpp>
25 #include <com/sun/star/xml/sax/InputSource.hpp>
26 #include <com/sun/star/xml/sax/Parser.hpp>
27 #include <com/sun/star/xml/sax/SAXParseException.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <com/sun/star/presentation/EffectPresetClass.hpp>
30 #include <com/sun/star/beans/NamedValue.hpp>
31 #include <unotools/streamwrap.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/string.hxx>
34 #include <unotools/pathoptions.hxx>
35 #include <tools/stream.hxx>
37 #include <tools/debug.hxx>
38 #include <rtl/uri.hxx>
39 #include <rtl/strbuf.hxx>
40 #include <vcl/svapp.hxx>
41 #include <osl/mutex.hxx>
42 #include <unotools/ucbstreamhelper.hxx>
43 #include <CustomAnimationPreset.hxx>
47 using namespace ::com::sun::star
;
48 using namespace ::com::sun::star::uno
;
49 using namespace ::com::sun::star::animations
;
50 using namespace ::com::sun::star::presentation
;
52 using ::com::sun::star::io::XInputStream
;
53 using ::com::sun::star::lang::XMultiServiceFactory
;
54 using ::com::sun::star::container::XNameAccess
;
55 using ::com::sun::star::beans::PropertyValue
;
56 using ::com::sun::star::util::XCloneable
;
57 using ::com::sun::star::beans::NamedValue
;
61 static Reference
< XNameAccess
> getNodeAccess( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
)
63 Reference
< XNameAccess
> xConfigAccess
;
67 Sequence
< Any
> aArgs( 1 );
68 PropertyValue aPropValue
;
69 aPropValue
.Name
= "nodepath";
70 aPropValue
.Value
<<= rNodePath
;
71 aArgs
[0] <<= aPropValue
;
73 xConfigAccess
= Reference
< XNameAccess
>::query(
74 xConfigProvider
->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess" ,
77 catch (const Exception
&)
79 OSL_FAIL( "sd::getNodeAccess(), Exception caught!" );
85 void implImportLabels( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
, UStringMap
& rStringMap
)
89 Reference
< XNameAccess
> xConfigAccess( getNodeAccess( xConfigProvider
, rNodePath
) );
90 if( xConfigAccess
.is() )
92 OUString
aLabel( "Label" );
93 Reference
< XNameAccess
> xNameAccess
;
94 Sequence
< OUString
> aNames( xConfigAccess
->getElementNames() );
95 const OUString
* p
= aNames
.getConstArray();
96 sal_Int32 n
= aNames
.getLength();
99 xConfigAccess
->getByName( *p
) >>= xNameAccess
;
100 if( xNameAccess
.is() )
103 xNameAccess
->getByName( aLabel
) >>= aUIName
;
104 if( !aUIName
.isEmpty() )
106 rStringMap
[ *p
] = aUIName
;
114 catch (const lang::WrappedTargetException
&)
116 OSL_FAIL( "sd::implImportLabels(), WrappedTargetException caught!" );
118 catch (const Exception
&)
120 OSL_FAIL( "sd::implImportLabels(), Exception caught!" );
124 CustomAnimationPreset::CustomAnimationPreset( CustomAnimationEffectPtr pEffect
)
126 maPresetId
= pEffect
->getPresetId();
127 maProperty
= pEffect
->getProperty();
128 mnPresetClass
= pEffect
->getPresetClass();
132 mfDuration
= pEffect
->getDuration();
133 maDefaultSubTyp
= pEffect
->getPresetSubType();
135 mbIsTextOnly
= false;
137 Sequence
< NamedValue
> aUserData( pEffect
->getNode()->getUserData() );
138 sal_Int32 nLength
= aUserData
.getLength();
139 const NamedValue
* p
= aUserData
.getConstArray();
143 if ( p
->Name
== "text-only" )
153 void CustomAnimationPreset::add( CustomAnimationEffectPtr pEffect
)
155 maSubTypes
[ pEffect
->getPresetSubType() ] = pEffect
;
158 UStringList
CustomAnimationPreset::getSubTypes()
160 UStringList aSubTypes
;
162 if( maSubTypes
.size() > 1 )
164 EffectsSubTypeMap::iterator
aIter( maSubTypes
.begin() );
165 const EffectsSubTypeMap::iterator
aEnd( maSubTypes
.end() );
166 while( aIter
!= aEnd
)
167 aSubTypes
.push_back( (*aIter
++).first
);
173 Reference
< XAnimationNode
> CustomAnimationPreset::create( const OUString
& rstrSubType
)
177 OUString
strSubType( rstrSubType
);
178 if( strSubType
.isEmpty() )
179 strSubType
= maDefaultSubTyp
;
181 CustomAnimationEffectPtr pEffect
= maSubTypes
[strSubType
];
184 Reference
< XCloneable
> xCloneable( pEffect
->getNode(), UNO_QUERY_THROW
);
185 Reference
< XAnimationNode
> xNode( xCloneable
->createClone(), UNO_QUERY_THROW
);
189 catch (const Exception
&)
191 OSL_FAIL( "sd::CustomAnimationPresets::create(), exception caught!" );
194 Reference
< XAnimationNode
> xNode
;
198 UStringList
CustomAnimationPreset::getProperties() const
200 String
aProperties( maProperty
);
201 sal_uInt16 nTokens
= comphelper::string::getTokenCount(aProperties
, ';');
203 UStringList aPropertyList
;
204 for( nToken
= 0; nToken
< nTokens
; nToken
++ )
205 aPropertyList
.push_back( aProperties
.GetToken( nToken
) );
207 return aPropertyList
;
211 bool CustomAnimationPreset::hasProperty( const OUString
& rProperty
)const
213 String
aProperties( maProperty
);
214 String
aProperty( rProperty
);
215 sal_uInt16 nTokens
= comphelper::string::getTokenCount(aProperties
, ';');
217 for( nToken
= 0; nToken
< nTokens
; nToken
++ )
219 if( aProperties
.GetToken( nToken
) == aProperty
)
226 CustomAnimationPresets::CustomAnimationPresets()
230 CustomAnimationPresets::~CustomAnimationPresets()
234 void CustomAnimationPresets::init()
239 Reference
< XAnimationNode
> implImportEffects( const Reference
< XMultiServiceFactory
>& xServiceFactory
, const OUString
& rPath
)
241 Reference
< XAnimationNode
> xRootNode
;
246 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( rPath
, STREAM_READ
);
247 Reference
<XInputStream
> xInputStream( new utl::OInputStreamWrapper( pIStm
, sal_True
) );
249 // prepare ParserInputSrouce
250 xml::sax::InputSource aParserInput
;
251 aParserInput
.sSystemId
= rPath
;
252 aParserInput
.aInputStream
= xInputStream
;
255 Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( comphelper::getComponentContext(xServiceFactory
) );
258 Reference
< xml::sax::XDocumentHandler
> xFilter( xServiceFactory
->createInstance("com.sun.star.comp.Xmloff.AnimationsImport" ), UNO_QUERY
);
260 DBG_ASSERT( xFilter
.is(), "Can't instantiate filter component." );
264 // connect parser and filter
265 xParser
->setDocumentHandler( xFilter
);
267 // finally, parser the stream
268 xParser
->parseStream( aParserInput
);
270 Reference
< XAnimationNodeSupplier
> xAnimationNodeSupplier( xFilter
, UNO_QUERY
);
271 if( xAnimationNodeSupplier
.is() )
272 xRootNode
= xAnimationNodeSupplier
->getAnimationNode();
274 catch (const xml::sax::SAXParseException
&)
276 OSL_FAIL( "sd::implImportEffects(), SAXParseException caught!" );
278 catch (const xml::sax::SAXException
&)
280 OSL_FAIL( "sd::implImportEffects(), SAXException caught!" );
282 catch (const io::IOException
&)
284 OSL_FAIL( "sd::implImportEffects(), IOException caught!" );
286 catch (const Exception
&)
288 OSL_FAIL( "sd::importEffects(), Exception caught!" );
294 #define EXPAND_PROTOCOL "vnd.sun.star.expand:"
296 void CustomAnimationPresets::importEffects()
300 uno::Reference
< uno::XComponentContext
> xContext(
301 comphelper::getProcessComponentContext() );
302 Reference
< XMultiServiceFactory
> xServiceFactory(
303 xContext
->getServiceManager(), UNO_QUERY_THROW
);
305 uno::Reference
< util::XMacroExpander
> xMacroExpander
=
306 util::theMacroExpander::get(xContext
);
308 Reference
< XMultiServiceFactory
> xConfigProvider
=
309 configuration::theDefaultProvider::get( xContext
);
311 // read path to transition effects files from config
312 Any propValue
= uno::makeAny(
313 beans::PropertyValue(
315 uno::makeAny( OUString( "/org.openoffice.Office.Impress/Misc" )),
316 beans::PropertyState_DIRECT_VALUE
) );
318 Reference
<container::XNameAccess
> xNameAccess(
319 xConfigProvider
->createInstanceWithArguments(
320 "com.sun.star.configuration.ConfigurationAccess",
321 Sequence
<Any
>( &propValue
, 1 ) ), UNO_QUERY_THROW
);
322 uno::Sequence
< OUString
> aFiles
;
323 xNameAccess
->getByName( "EffectFiles" ) >>= aFiles
;
325 for( sal_Int32 i
=0; i
<aFiles
.getLength(); ++i
)
327 OUString aURL
= aFiles
[i
];
328 if( aURL
.startsWith( EXPAND_PROTOCOL
) )
331 OUString
aMacro( aURL
.copy( sizeof ( EXPAND_PROTOCOL
) -1 ) );
332 // decode uric class chars
333 aMacro
= rtl::Uri::decode( aMacro
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
);
334 // expand macro string
335 aURL
= xMacroExpander
->expandMacros( aMacro
);
338 mxRootNode
= implImportEffects( xServiceFactory
, aURL
);
340 if( mxRootNode
.is() )
342 Reference
< XTimeContainer
> xRootContainer( mxRootNode
, UNO_QUERY_THROW
);
343 EffectSequenceHelper
aSequence( xRootContainer
);
345 EffectSequence::iterator
aIter( aSequence
.getBegin() );
346 const EffectSequence::iterator
aEnd( aSequence
.getEnd() );
348 while( aIter
!= aEnd
)
350 CustomAnimationEffectPtr pEffect
= (*aIter
);
352 const OUString
aPresetId( pEffect
->getPresetId() );
353 CustomAnimationPresetPtr pDescriptor
= getEffectDescriptor( aPresetId
);
354 if( pDescriptor
.get() )
355 pDescriptor
->add( pEffect
);
358 pDescriptor
.reset( new CustomAnimationPreset( pEffect
) );
359 pDescriptor
->maLabel
= getUINameForPresetId( pEffect
->getPresetId() );
360 maEffectDiscriptorMap
[aPresetId
] = pDescriptor
;
368 catch (const xml::sax::SAXParseException
&)
370 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), SAXParseException caught!" );
372 catch (const xml::sax::SAXException
&)
374 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), SAXException caught!" );
376 catch (const io::IOException
&)
378 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), IOException caught!" );
380 catch (const Exception
&)
382 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), Exception caught!" );
386 void CustomAnimationPresets::importResources()
390 // Get service factory
391 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
393 Reference
< XMultiServiceFactory
> xConfigProvider
=
394 configuration::theDefaultProvider::get( xContext
);
396 const OUString
aPropertyPath("/org.openoffice.Office.UI.Effects/UserInterface/Properties" );
397 implImportLabels( xConfigProvider
, aPropertyPath
, maPropertyNameMap
);
399 const OUString
aEffectsPath( "/org.openoffice.Office.UI.Effects/UserInterface/Effects" );
400 implImportLabels( xConfigProvider
, aEffectsPath
, maEffectNameMap
);
404 const OUString
aEntrancePath( "/org.openoffice.Office.UI.Effects/Presets/Entrance" );
405 importPresets( xConfigProvider
, aEntrancePath
, maEntrancePresets
);
407 const OUString
aEmphasisPath( "/org.openoffice.Office.UI.Effects/Presets/Emphasis" );
408 importPresets( xConfigProvider
, aEmphasisPath
, maEmphasisPresets
);
410 const OUString
aExitPath( "/org.openoffice.Office.UI.Effects/Presets/Exit" );
411 importPresets( xConfigProvider
, aExitPath
, maExitPresets
);
413 const OUString
aMotionPathsPath( "/org.openoffice.Office.UI.Effects/Presets/MotionPaths" );
414 importPresets( xConfigProvider
, aMotionPathsPath
, maMotionPathsPresets
);
416 const OUString
aMiscPath( "/org.openoffice.Office.UI.Effects/Presets/Misc" );
417 importPresets( xConfigProvider
, aMiscPath
, maMiscPresets
);
419 catch (const lang::WrappedTargetException
&)
421 OSL_FAIL( "sd::CustomAnimationPresets::importResources(), WrappedTargetException caught!" );
423 catch (const Exception
&)
425 OSL_FAIL( "sd::CustomAnimationPresets::importResources(), Exception caught!" );
429 void CustomAnimationPresets::importPresets( const Reference
< XMultiServiceFactory
>& xConfigProvider
, const OUString
& rNodePath
, PresetCategoryList
& rPresetMap
)
432 String aMissedPresetIds
;
437 Reference
< XNameAccess
> xTypeAccess( getNodeAccess( xConfigProvider
, rNodePath
) );
438 if( xTypeAccess
.is() )
440 Reference
< XNameAccess
> xCategoryAccess
;
441 const OUString
aEffectsName( "Effects" );
442 const OUString
aLabelName( "Label" );
444 Sequence
< OUString
> aNames( xTypeAccess
->getElementNames() );
445 const OUString
* p
= aNames
.getConstArray();
446 sal_Int32 n
= aNames
.getLength();
449 xTypeAccess
->getByName( *p
) >>= xCategoryAccess
;
451 if( xCategoryAccess
.is() && xCategoryAccess
->hasByName( aLabelName
) && xCategoryAccess
->hasByName( aEffectsName
) )
454 xCategoryAccess
->getByName( aLabelName
) >>= aLabel
;
456 Sequence
< OUString
> aEffects
;
457 xCategoryAccess
->getByName( aEffectsName
) >>= aEffects
;
459 EffectDescriptorList aEffectsList
;
461 const OUString
* pEffectNames
= aEffects
.getConstArray();
462 sal_Int32 nEffectCount
= aEffects
.getLength();
463 while( nEffectCount
-- )
465 CustomAnimationPresetPtr pEffect
= getEffectDescriptor( *pEffectNames
);
468 aEffectsList
.push_back( pEffect
);
473 aMissedPresetIds
+= String(*pEffectNames
);
474 aMissedPresetIds
+= String( RTL_CONSTASCII_USTRINGPARAM("\n") );
479 rPresetMap
.push_back( PresetCategoryPtr( new PresetCategory( aLabel
, aEffectsList
) ) );
486 catch (const Exception
&)
488 OSL_FAIL( "sd::CustomAnimationPresets::importPresets(), Exception caught!" );
492 if( aMissedPresetIds
.Len() )
494 OStringBuffer
aTmp(RTL_CONSTASCII_STRINGPARAM("sd::CustomAnimationPresets::importPresets(), invalid preset id!\n"));
495 aTmp
.append(OUStringToOString(aMissedPresetIds
,
496 RTL_TEXTENCODING_ASCII_US
));
497 OSL_FAIL(aTmp
.getStr());
502 CustomAnimationPresetPtr
CustomAnimationPresets::getEffectDescriptor( const OUString
& rPresetId
) const
504 EffectDescriptorMap::const_iterator
aIter( maEffectDiscriptorMap
.find( rPresetId
) );
506 if( aIter
!= maEffectDiscriptorMap
.end() )
508 return (*aIter
).second
;
512 return CustomAnimationPresetPtr((CustomAnimationPreset
*)0);
516 const OUString
& CustomAnimationPresets::getUINameForPresetId( const OUString
& rPresetId
) const
518 return translateName( rPresetId
, maEffectNameMap
);
521 const OUString
& CustomAnimationPresets::getUINameForProperty( const OUString
& rPresetId
) const
523 return translateName( rPresetId
, maPropertyNameMap
);
526 const OUString
& CustomAnimationPresets::translateName( const OUString
& rId
, const UStringMap
& rNameMap
) const
528 UStringMap::const_iterator
aIter( rNameMap
.find( rId
) );
530 if( aIter
!= rNameMap
.end() )
532 return (*aIter
).second
;
539 void CustomAnimationPresets::changePresetSubType( CustomAnimationEffectPtr pEffect
, const OUString
& rPresetSubType
) const
541 if( pEffect
.get() && pEffect
->getPresetSubType() != rPresetSubType
)
543 CustomAnimationPresetPtr
pDescriptor( getEffectDescriptor( pEffect
->getPresetId() ) );
545 if( pDescriptor
.get() )
547 Reference
< XAnimationNode
> xNewNode( pDescriptor
->create( rPresetSubType
) );
549 pEffect
->replaceNode( xNewNode
);
554 CustomAnimationPresets
* CustomAnimationPresets::mpCustomAnimationPresets
= 0;
556 const CustomAnimationPresets
& CustomAnimationPresets::getCustomAnimationPresets()
558 if( !mpCustomAnimationPresets
)
560 SolarMutexGuard aGuard
;
562 if( !mpCustomAnimationPresets
)
564 mpCustomAnimationPresets
= new sd::CustomAnimationPresets();
565 mpCustomAnimationPresets
->init();
569 return *mpCustomAnimationPresets
;
572 Reference
< XAnimationNode
> CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass
) const
574 Reference
< XAnimationNode
> xNode
;
576 const PresetCategoryList
* pCategoryList
= 0;
577 switch( nPresetClass
)
579 case EffectPresetClass::ENTRANCE
: pCategoryList
= &maEntrancePresets
; break;
580 case EffectPresetClass::EXIT
: pCategoryList
= &maExitPresets
; break;
581 case EffectPresetClass::EMPHASIS
: pCategoryList
= &maEmphasisPresets
; break;
582 case EffectPresetClass::MOTIONPATH
: pCategoryList
= &maMotionPathsPresets
; break;
587 if( pCategoryList
&& pCategoryList
->size() )
589 sal_Int32 nCategory
= (rand() * pCategoryList
->size() / RAND_MAX
);
591 PresetCategoryPtr pCategory
= (*pCategoryList
)[nCategory
];
592 if( pCategory
.get() && !pCategory
->maEffects
.empty() )
594 sal_Int32 nDescriptor
= (rand() * pCategory
->maEffects
.size() / RAND_MAX
);
595 CustomAnimationPresetPtr pPreset
= pCategory
->maEffects
[nDescriptor
];
598 UStringList aSubTypes
= pPreset
->getSubTypes();
601 if( !aSubTypes
.empty() )
603 sal_Int32 nSubType
= (rand() * aSubTypes
.size() / RAND_MAX
);
604 aSubType
= aSubTypes
[nSubType
];
606 xNode
= pPreset
->create( aSubType
);
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */