bump product version to 6.4.0.3
[LibreOffice.git] / sd / source / core / CustomAnimationPreset.cxx
blobe54c67d95b5c1cb0671c18e1ae48f9ee10348170
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 <sal/config.h>
22 #include <com/sun/star/io/IOException.hpp>
23 #include <com/sun/star/util/XCloneable.hpp>
24 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
25 #include <com/sun/star/container/XNameAccess.hpp>
26 #include <com/sun/star/configuration/theDefaultProvider.hpp>
27 #include <com/sun/star/xml/sax/InputSource.hpp>
28 #include <com/sun/star/xml/sax/Parser.hpp>
29 #include <com/sun/star/xml/sax/SAXParseException.hpp>
30 #include <com/sun/star/presentation/EffectPresetClass.hpp>
31 #include <com/sun/star/beans/NamedValue.hpp>
32 #include <osl/diagnose.h>
33 #include <unotools/streamwrap.hxx>
34 #include <comphelper/getexpandeduri.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/propertysequence.hxx>
37 #include <comphelper/random.hxx>
38 #include <comphelper/lok.hxx>
39 #include <unotools/syslocaleoptions.hxx>
40 #include <tools/stream.hxx>
42 #include <tools/debug.hxx>
43 #include <vcl/svapp.hxx>
44 #include <unotools/ucbstreamhelper.hxx>
45 #include <CustomAnimationPreset.hxx>
47 #include <algorithm>
48 #include <vector>
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::animations;
53 using namespace ::com::sun::star::presentation;
55 using ::com::sun::star::io::XInputStream;
56 using ::com::sun::star::lang::XMultiServiceFactory;
57 using ::com::sun::star::container::XNameAccess;
58 using ::com::sun::star::util::XCloneable;
59 using ::com::sun::star::beans::NamedValue;
61 namespace sd {
63 static Reference< XNameAccess > getNodeAccess( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath )
65 Reference< XNameAccess > xConfigAccess;
67 try
69 Sequence<Any> aArgs(comphelper::InitAnyPropertySequence(
71 {"nodepath", uno::Any(rNodePath)}
72 }));
74 xConfigAccess.set(
75 xConfigProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", aArgs ),
76 UNO_QUERY);
78 catch (const Exception&)
80 OSL_FAIL( "sd::getNodeAccess(), Exception caught!" );
83 return xConfigAccess;
86 void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap )
88 try
90 Reference< XNameAccess > xConfigAccess( getNodeAccess( xConfigProvider, rNodePath ) );
91 if( xConfigAccess.is() )
93 Reference< XNameAccess > xNameAccess;
94 const Sequence< OUString > aNames( xConfigAccess->getElementNames() );
95 for(const OUString& rName : aNames)
97 xConfigAccess->getByName( rName ) >>= xNameAccess;
98 if( xNameAccess.is() )
100 OUString aUIName;
101 xNameAccess->getByName( "Label" ) >>= aUIName;
102 if( !aUIName.isEmpty() )
104 rStringMap[ rName ] = aUIName;
110 catch (const lang::WrappedTargetException&)
112 OSL_FAIL( "sd::implImportLabels(), WrappedTargetException caught!" );
114 catch (const Exception&)
116 OSL_FAIL( "sd::implImportLabels(), Exception caught!" );
120 CustomAnimationPreset::CustomAnimationPreset( const CustomAnimationEffectPtr& pEffect )
122 maPresetId = pEffect->getPresetId();
123 maProperty = pEffect->getProperty();
125 add( pEffect );
127 mfDuration = pEffect->getDuration();
128 maDefaultSubTyp = pEffect->getPresetSubType();
130 Sequence< NamedValue > aUserData( pEffect->getNode()->getUserData() );
132 mbIsTextOnly = std::any_of(aUserData.begin(), aUserData.end(),
133 [](const NamedValue& rProp) { return rProp.Name == "text-only"; });
136 void CustomAnimationPreset::add( const CustomAnimationEffectPtr& pEffect )
138 maSubTypes[ pEffect->getPresetSubType() ] = pEffect;
141 std::vector<OUString> CustomAnimationPreset::getSubTypes()
143 std::vector<OUString> aSubTypes;
145 if( maSubTypes.size() > 1 )
147 std::transform(maSubTypes.begin(), maSubTypes.end(), std::back_inserter(aSubTypes),
148 [](EffectsSubTypeMap::value_type& rEntry) -> OUString { return rEntry.first; });
151 return aSubTypes;
154 Reference< XAnimationNode > CustomAnimationPreset::create( const OUString& rstrSubType )
158 OUString strSubType( rstrSubType );
159 if( strSubType.isEmpty() )
160 strSubType = maDefaultSubTyp;
162 CustomAnimationEffectPtr pEffect = maSubTypes[strSubType];
163 if( pEffect.get() )
165 Reference< XCloneable > xCloneable( pEffect->getNode(), UNO_QUERY_THROW );
166 Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW );
167 return xNode;
170 catch (const Exception&)
172 OSL_FAIL( "sd::CustomAnimationPresets::create(), exception caught!" );
175 Reference< XAnimationNode > xNode;
176 return xNode;
179 std::vector<OUString> CustomAnimationPreset::getProperties() const
181 std::vector<OUString> aPropertyList;
182 if (!maProperty.isEmpty())
184 sal_Int32 nPos = 0;
187 aPropertyList.push_back(maProperty.getToken(0, ';', nPos));
189 while (nPos >= 0);
191 return aPropertyList;
194 bool CustomAnimationPreset::hasProperty( const OUString& rProperty )const
196 if (maProperty.isEmpty())
197 return false;
199 sal_Int32 nPos = 0;
202 if (maProperty.getToken(0, ';', nPos) == rProperty)
203 return true;
205 while (nPos >= 0);
207 return false;
210 CustomAnimationPresets::CustomAnimationPresets()
214 CustomAnimationPresets::~CustomAnimationPresets()
218 Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xServiceFactory, const OUString& rPath )
220 Reference< XAnimationNode > xRootNode;
224 // create stream
225 std::unique_ptr<SvStream> pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, StreamMode::READ );
226 Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( std::move(pIStm) ) );
228 // prepare ParserInputSrouce
229 xml::sax::InputSource aParserInput;
230 aParserInput.sSystemId = rPath;
231 aParserInput.aInputStream = xInputStream;
233 // get parser
234 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( comphelper::getComponentContext(xServiceFactory) );
236 // get filter
237 Reference< xml::sax::XDocumentHandler > xFilter( xServiceFactory->createInstance("com.sun.star.comp.Xmloff.AnimationsImport" ), UNO_QUERY );
239 DBG_ASSERT( xFilter.is(), "Can't instantiate filter component." );
240 if( !xFilter.is() )
241 return xRootNode;
243 // connect parser and filter
244 xParser->setDocumentHandler( xFilter );
246 // finally, parser the stream
247 xParser->parseStream( aParserInput );
249 Reference< XAnimationNodeSupplier > xAnimationNodeSupplier( xFilter, UNO_QUERY );
250 if( xAnimationNodeSupplier.is() )
251 xRootNode = xAnimationNodeSupplier->getAnimationNode();
253 catch (const xml::sax::SAXParseException&)
255 OSL_FAIL( "sd::implImportEffects(), SAXParseException caught!" );
257 catch (const xml::sax::SAXException&)
259 OSL_FAIL( "sd::implImportEffects(), SAXException caught!" );
261 catch (const io::IOException&)
263 OSL_FAIL( "sd::implImportEffects(), IOException caught!" );
265 catch (const Exception&)
267 OSL_FAIL( "sd::importEffects(), Exception caught!" );
270 return xRootNode;
273 void CustomAnimationPresets::importEffects()
277 uno::Reference< uno::XComponentContext > xContext(
278 comphelper::getProcessComponentContext() );
279 Reference< XMultiServiceFactory > xServiceFactory(
280 xContext->getServiceManager(), UNO_QUERY_THROW );
282 Reference< XMultiServiceFactory > xConfigProvider =
283 configuration::theDefaultProvider::get( xContext );
285 // read path to transition effects files from config
286 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
288 {"nodepath", uno::Any(OUString("/org.openoffice.Office.Impress/Misc"))}
289 }));
290 Reference<container::XNameAccess> xNameAccess(
291 xConfigProvider->createInstanceWithArguments(
292 "com.sun.star.configuration.ConfigurationAccess",
293 aArgs ), UNO_QUERY_THROW );
294 uno::Sequence< OUString > aFiles;
295 xNameAccess->getByName( "EffectFiles" ) >>= aFiles;
297 for( const auto& rFile : std::as_const(aFiles) )
299 OUString aURL = comphelper::getExpandedUri(xContext, rFile);
301 mxRootNode = implImportEffects( xServiceFactory, aURL );
303 if( mxRootNode.is() )
305 Reference< XTimeContainer > xRootContainer( mxRootNode, UNO_QUERY_THROW );
306 EffectSequenceHelper aSequence( xRootContainer );
308 EffectSequence::iterator aIter( aSequence.getBegin() );
309 const EffectSequence::iterator aEnd( aSequence.getEnd() );
311 while( aIter != aEnd )
313 CustomAnimationEffectPtr pEffect = *aIter;
315 const OUString aPresetId( pEffect->getPresetId() );
316 CustomAnimationPresetPtr pDescriptor = getEffectDescriptor( aPresetId );
317 if( pDescriptor.get() )
318 pDescriptor->add( pEffect );
319 else
321 pDescriptor.reset( new CustomAnimationPreset( pEffect ) );
322 pDescriptor->maLabel = getUINameForPresetId( pEffect->getPresetId() );
323 maEffectDiscriptorMap[aPresetId] = pDescriptor;
326 ++aIter;
331 catch (const xml::sax::SAXParseException&)
333 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), SAXParseException caught!" );
335 catch (const xml::sax::SAXException&)
337 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), SAXException caught!" );
339 catch (const io::IOException&)
341 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), IOException caught!" );
343 catch (const Exception&)
345 OSL_FAIL( "sd::CustomAnimationPresets::importEffects(), Exception caught!" );
349 void CustomAnimationPresets::importResources()
353 // Get service factory
354 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
356 Reference< XMultiServiceFactory > xConfigProvider =
357 configuration::theDefaultProvider::get( xContext );
359 const OUString aPropertyPath("/org.openoffice.Office.UI.Effects/UserInterface/Properties" );
360 implImportLabels( xConfigProvider, aPropertyPath, maPropertyNameMap );
362 const OUString aEffectsPath( "/org.openoffice.Office.UI.Effects/UserInterface/Effects" );
363 implImportLabels( xConfigProvider, aEffectsPath, maEffectNameMap );
365 importEffects();
367 const OUString aEntrancePath( "/org.openoffice.Office.UI.Effects/Presets/Entrance" );
368 importPresets( xConfigProvider, aEntrancePath, maEntrancePresets );
370 const OUString aEmphasisPath( "/org.openoffice.Office.UI.Effects/Presets/Emphasis" );
371 importPresets( xConfigProvider, aEmphasisPath, maEmphasisPresets );
373 const OUString aExitPath( "/org.openoffice.Office.UI.Effects/Presets/Exit" );
374 importPresets( xConfigProvider, aExitPath, maExitPresets );
376 const OUString aMotionPathsPath( "/org.openoffice.Office.UI.Effects/Presets/MotionPaths" );
377 importPresets( xConfigProvider, aMotionPathsPath, maMotionPathsPresets );
379 const OUString aMiscPath( "/org.openoffice.Office.UI.Effects/Presets/Misc" );
380 importPresets( xConfigProvider, aMiscPath, maMiscPresets );
382 catch (const lang::WrappedTargetException&)
384 OSL_FAIL( "sd::CustomAnimationPresets::importResources(), WrappedTargetException caught!" );
386 catch (const Exception&)
388 OSL_FAIL( "sd::CustomAnimationPresets::importResources(), Exception caught!" );
392 void CustomAnimationPresets::importPresets( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, PresetCategoryList& rPresetMap )
394 #ifdef DEBUG
395 OUString aMissedPresetIds;
396 #endif
400 Reference< XNameAccess > xTypeAccess( getNodeAccess( xConfigProvider, rNodePath ) );
401 if( xTypeAccess.is() )
403 Reference< XNameAccess > xCategoryAccess;
405 const Sequence< OUString > aNames( xTypeAccess->getElementNames() );
406 for(const OUString& rName : aNames)
408 xTypeAccess->getByName( rName ) >>= xCategoryAccess;
410 if( xCategoryAccess.is() && xCategoryAccess->hasByName( "Label" ) && xCategoryAccess->hasByName( "Effects" ) )
412 OUString aLabel;
413 xCategoryAccess->getByName( "Label" ) >>= aLabel;
415 Sequence< OUString > aEffects;
416 xCategoryAccess->getByName( "Effects" ) >>= aEffects;
418 EffectDescriptorList aEffectsList;
420 for( const OUString& rEffectName : std::as_const(aEffects) )
422 CustomAnimationPresetPtr pEffect = getEffectDescriptor( rEffectName );
423 if( pEffect.get() )
425 aEffectsList.push_back( pEffect );
427 #ifdef DEBUG
428 else
430 aMissedPresetIds += OUString(rEffectName);
431 aMissedPresetIds += "\n";
433 #endif
435 rPresetMap.push_back( std::make_shared<PresetCategory>( aLabel, aEffectsList ) );
440 catch (const Exception&)
442 OSL_FAIL( "sd::CustomAnimationPresets::importPresets(), Exception caught!" );
445 #ifdef DEBUG
446 SAL_WARN_IF(!aMissedPresetIds.isEmpty(), "sd", "sd::CustomAnimationPresets::importPresets(), invalid preset id: "
447 << aMissedPresetIds);
448 #endif
451 CustomAnimationPresetPtr CustomAnimationPresets::getEffectDescriptor( const OUString& rPresetId ) const
453 EffectDescriptorMap::const_iterator aIter( maEffectDiscriptorMap.find( rPresetId ) );
455 if( aIter != maEffectDiscriptorMap.end() )
457 return (*aIter).second;
459 else
461 return CustomAnimationPresetPtr(nullptr);
465 const OUString& CustomAnimationPresets::getUINameForPresetId( const OUString& rPresetId ) const
467 return translateName( rPresetId, maEffectNameMap );
470 const OUString& CustomAnimationPresets::getUINameForProperty( const OUString& rPresetId ) const
472 return translateName( rPresetId, maPropertyNameMap );
475 const OUString& CustomAnimationPresets::translateName( const OUString& rId, const UStringMap& rNameMap )
477 UStringMap::const_iterator aIter( rNameMap.find( rId ) );
479 if( aIter != rNameMap.end() )
481 return (*aIter).second;
483 else
485 return rId;
488 void CustomAnimationPresets::changePresetSubType( const CustomAnimationEffectPtr& pEffect, const OUString& rPresetSubType ) const
490 if( pEffect.get() && pEffect->getPresetSubType() != rPresetSubType )
492 CustomAnimationPresetPtr pDescriptor( getEffectDescriptor( pEffect->getPresetId() ) );
494 if( pDescriptor.get() )
496 Reference< XAnimationNode > xNewNode( pDescriptor->create( rPresetSubType ) );
497 if( xNewNode.is() )
498 pEffect->replaceNode( xNewNode );
503 std::map<OUString, CustomAnimationPresets> CustomAnimationPresets::mPresetsMap;
505 const CustomAnimationPresets& CustomAnimationPresets::getCustomAnimationPresets()
507 // Support localization per-view. Currently not useful for Desktop
508 // but very much critical for LOK. The cache now is per-language.
509 const OUString aLang = comphelper::LibreOfficeKit::isActive()
510 ? comphelper::LibreOfficeKit::getLanguageTag().getLanguage()
511 : SvtSysLocaleOptions().GetLanguageTag().getLanguage();
513 SolarMutexGuard aGuard;
514 const auto it = mPresetsMap.find(aLang);
515 if (it != mPresetsMap.end())
516 return it->second;
518 CustomAnimationPresets& rPresets = mPresetsMap[aLang];
519 rPresets.importResources();
520 return rPresets;
523 Reference< XAnimationNode > CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass ) const
525 Reference< XAnimationNode > xNode;
527 const PresetCategoryList* pCategoryList = nullptr;
528 switch( nPresetClass )
530 case EffectPresetClass::ENTRANCE: pCategoryList = &maEntrancePresets; break;
531 case EffectPresetClass::EXIT: pCategoryList = &maExitPresets; break;
532 case EffectPresetClass::EMPHASIS: pCategoryList = &maEmphasisPresets; break;
533 case EffectPresetClass::MOTIONPATH: pCategoryList = &maMotionPathsPresets; break;
534 default:
535 pCategoryList = nullptr;
538 if( pCategoryList && !pCategoryList->empty() )
540 sal_Int32 nCategory = comphelper::rng::uniform_size_distribution(0, pCategoryList->size()-1);
542 PresetCategoryPtr pCategory = (*pCategoryList)[nCategory];
543 if( pCategory.get() && !pCategory->maEffects.empty() )
545 sal_Int32 nDescriptor = comphelper::rng::uniform_size_distribution(0, pCategory->maEffects.size()-1);
546 CustomAnimationPresetPtr pPreset = pCategory->maEffects[nDescriptor];
547 if( pPreset.get() )
549 std::vector<OUString> aSubTypes = pPreset->getSubTypes();
551 OUString aSubType;
552 if( !aSubTypes.empty() )
554 size_t nSubType = comphelper::rng::uniform_size_distribution(0, aSubTypes.size()-1);
555 aSubType = aSubTypes[nSubType];
557 xNode = pPreset->create( aSubType );
562 return xNode;
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */