update credits
[LibreOffice.git] / sd / source / core / CustomAnimationPreset.cxx
blob91b0836a9aafa42228aa0d4fbfc0cd352643d8f1
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/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>
45 #include <algorithm>
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;
59 namespace sd {
61 static Reference< XNameAccess > getNodeAccess( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath )
63 Reference< XNameAccess > xConfigAccess;
65 try
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" ,
75 aArgs ));
77 catch (const Exception&)
79 OSL_FAIL( "sd::getNodeAccess(), Exception caught!" );
82 return xConfigAccess;
85 void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap )
87 try
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();
97 while(n--)
99 xConfigAccess->getByName( *p ) >>= xNameAccess;
100 if( xNameAccess.is() )
102 OUString aUIName;
103 xNameAccess->getByName( aLabel ) >>= aUIName;
104 if( !aUIName.isEmpty() )
106 rStringMap[ *p ] = aUIName;
110 p++;
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();
130 add( pEffect );
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();
141 while( nLength-- )
143 if ( p->Name == "text-only" )
145 mbIsTextOnly = true;
146 break;
148 p++;
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 );
170 return aSubTypes;
173 Reference< XAnimationNode > CustomAnimationPreset::create( const OUString& rstrSubType )
177 OUString strSubType( rstrSubType );
178 if( strSubType.isEmpty() )
179 strSubType = maDefaultSubTyp;
181 CustomAnimationEffectPtr pEffect = maSubTypes[strSubType];
182 if( pEffect.get() )
184 Reference< XCloneable > xCloneable( pEffect->getNode(), UNO_QUERY_THROW );
185 Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW );
186 return xNode;
189 catch (const Exception&)
191 OSL_FAIL( "sd::CustomAnimationPresets::create(), exception caught!" );
194 Reference< XAnimationNode > xNode;
195 return xNode;
198 UStringList CustomAnimationPreset::getProperties() const
200 String aProperties( maProperty );
201 sal_uInt16 nTokens = comphelper::string::getTokenCount(aProperties, ';');
202 sal_uInt16 nToken;
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, ';');
216 sal_uInt16 nToken;
217 for( nToken = 0; nToken < nTokens; nToken++ )
219 if( aProperties.GetToken( nToken ) == aProperty )
220 return true;
223 return false;
226 CustomAnimationPresets::CustomAnimationPresets()
230 CustomAnimationPresets::~CustomAnimationPresets()
234 void CustomAnimationPresets::init()
236 importResources();
239 Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xServiceFactory, const OUString& rPath )
241 Reference< XAnimationNode > xRootNode;
245 // create stream
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;
254 // get parser
255 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( comphelper::getComponentContext(xServiceFactory) );
257 // get filter
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." );
261 if( !xFilter.is() )
262 return xRootNode;
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!" );
291 return xRootNode;
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(
314 "nodepath", -1,
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 ) )
330 // cut 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 );
356 else
358 pDescriptor.reset( new CustomAnimationPreset( pEffect ) );
359 pDescriptor->maLabel = getUINameForPresetId( pEffect->getPresetId() );
360 maEffectDiscriptorMap[aPresetId] = pDescriptor;
363 ++aIter;
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 );
402 importEffects();
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 )
431 #ifdef DEBUG
432 String aMissedPresetIds;
433 #endif
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();
447 while(n--)
449 xTypeAccess->getByName( *p ) >>= xCategoryAccess;
451 if( xCategoryAccess.is() && xCategoryAccess->hasByName( aLabelName ) && xCategoryAccess->hasByName( aEffectsName ) )
453 OUString aLabel;
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 );
466 if( pEffect.get() )
468 aEffectsList.push_back( pEffect );
470 #ifdef DEBUG
471 else
473 aMissedPresetIds += String(*pEffectNames);
474 aMissedPresetIds += String( RTL_CONSTASCII_USTRINGPARAM("\n") );
476 #endif
477 pEffectNames++;
479 rPresetMap.push_back( PresetCategoryPtr( new PresetCategory( aLabel, aEffectsList ) ) );
482 p++;
486 catch (const Exception&)
488 OSL_FAIL( "sd::CustomAnimationPresets::importPresets(), Exception caught!" );
491 #ifdef DEBUG
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());
499 #endif
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;
510 else
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;
534 else
536 return rId;
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 ) );
548 if( xNewNode.is() )
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;
583 default:
584 pCategoryList = 0;
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];
596 if( pPreset.get() )
598 UStringList aSubTypes = pPreset->getSubTypes();
600 OUString aSubType;
601 if( !aSubTypes.empty() )
603 sal_Int32 nSubType = (rand() * aSubTypes.size() / RAND_MAX);
604 aSubType = aSubTypes[nSubType];
606 xNode = pPreset->create( aSubType );
611 return xNode;
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */