xmlsecurity: fix --without-system-nss build
[LibreOffice.git] / sd / source / core / CustomAnimationPreset.cxx
blobb20dc5e8357fa2f979518695dcda3cd0413a42ca
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/util/XCloneable.hpp>
23 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/xml/sax/InputSource.hpp>
27 #include <com/sun/star/xml/sax/XFastParser.hpp>
28 #include <com/sun/star/presentation/EffectPresetClass.hpp>
29 #include <com/sun/star/beans/NamedValue.hpp>
30 #include <unotools/streamwrap.hxx>
31 #include <comphelper/getexpandeduri.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertysequence.hxx>
34 #include <comphelper/random.hxx>
35 #include <comphelper/lok.hxx>
36 #include <unotools/syslocaleoptions.hxx>
37 #include <tools/stream.hxx>
38 #include <comphelper/diagnose_ex.hxx>
39 #include <o3tl/string_view.hxx>
40 #include <officecfg/Office/Impress.hxx>
42 #include <vcl/svapp.hxx>
43 #include <unotools/ucbstreamhelper.hxx>
44 #include <CustomAnimationPreset.hxx>
46 #include <algorithm>
47 #include <vector>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::animations;
52 using namespace ::com::sun::star::presentation;
54 using ::com::sun::star::lang::XMultiServiceFactory;
55 using ::com::sun::star::container::XNameAccess;
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(comphelper::InitAnyPropertySequence(
69 {"nodepath", uno::Any(rNodePath)}
70 }));
72 xConfigAccess.set(
73 xConfigProvider->createInstanceWithArguments( u"com.sun.star.configuration.ConfigurationAccess"_ustr, aArgs ),
74 UNO_QUERY);
76 catch (const Exception&)
78 TOOLS_WARN_EXCEPTION( "sd", "sd::getNodeAccess()" );
81 return xConfigAccess;
84 void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap )
86 try
88 Reference< XNameAccess > xConfigAccess( getNodeAccess( xConfigProvider, rNodePath ) );
89 if( xConfigAccess.is() )
91 Reference< XNameAccess > xNameAccess;
92 const Sequence< OUString > aNames( xConfigAccess->getElementNames() );
93 for(const OUString& rName : aNames)
95 xConfigAccess->getByName( rName ) >>= xNameAccess;
96 if( xNameAccess.is() )
98 OUString aUIName;
99 xNameAccess->getByName( u"Label"_ustr ) >>= aUIName;
100 if( !aUIName.isEmpty() )
102 rStringMap[ rName ] = aUIName;
108 catch (const Exception&)
110 TOOLS_WARN_EXCEPTION( "sd", "sd::implImportLabels()" );
114 CustomAnimationPreset::CustomAnimationPreset( const CustomAnimationEffectPtr& pEffect )
116 maPresetId = pEffect->getPresetId();
117 maProperty = pEffect->getProperty();
119 add( pEffect );
121 mfDuration = pEffect->getDuration();
122 maDefaultSubTyp = pEffect->getPresetSubType();
124 const Sequence< NamedValue > aUserData( pEffect->getNode()->getUserData() );
126 mbIsTextOnly = std::any_of(aUserData.begin(), aUserData.end(),
127 [](const NamedValue& rProp) { return rProp.Name == "text-only"; });
130 void CustomAnimationPreset::add( const CustomAnimationEffectPtr& pEffect )
132 maSubTypes[ pEffect->getPresetSubType() ] = pEffect;
135 std::vector<OUString> CustomAnimationPreset::getSubTypes()
137 std::vector<OUString> aSubTypes;
139 if( maSubTypes.size() > 1 )
141 std::transform(maSubTypes.begin(), maSubTypes.end(), std::back_inserter(aSubTypes),
142 [](EffectsSubTypeMap::value_type& rEntry) -> OUString { return rEntry.first; });
145 return aSubTypes;
148 Reference< XAnimationNode > CustomAnimationPreset::create( const OUString& rstrSubType )
152 OUString strSubType( rstrSubType );
153 if( strSubType.isEmpty() )
154 strSubType = maDefaultSubTyp;
156 CustomAnimationEffectPtr pEffect = maSubTypes[strSubType];
157 if( pEffect )
159 Reference< XCloneable > xCloneable( pEffect->getNode(), UNO_QUERY_THROW );
160 Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW );
161 return xNode;
164 catch (const Exception&)
166 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPresets::create()" );
169 Reference< XAnimationNode > xNode;
170 return xNode;
173 std::vector<OUString> CustomAnimationPreset::getProperties() const
175 std::vector<OUString> aPropertyList;
176 if (!maProperty.isEmpty())
178 sal_Int32 nPos = 0;
181 aPropertyList.push_back(maProperty.getToken(0, ';', nPos));
183 while (nPos >= 0);
185 return aPropertyList;
188 bool CustomAnimationPreset::hasProperty( std::u16string_view rProperty )const
190 if (maProperty.isEmpty())
191 return false;
193 sal_Int32 nPos = 0;
196 if (o3tl::getToken(maProperty, 0, ';', nPos) == rProperty)
197 return true;
199 while (nPos >= 0);
201 return false;
204 CustomAnimationPresets::CustomAnimationPresets()
208 CustomAnimationPresets::~CustomAnimationPresets()
212 Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xServiceFactory, const OUString& rPath )
214 Reference< XAnimationNode > xRootNode;
218 // create stream
219 std::unique_ptr<SvStream> pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, StreamMode::READ );
221 // prepare ParserInputSource
222 xml::sax::InputSource aParserInput;
223 aParserInput.sSystemId = rPath;
224 aParserInput.aInputStream.set(new utl::OInputStreamWrapper(std::move(pIStm)));
226 // get filter
227 Reference< xml::sax::XFastParser > xFilter( xServiceFactory->createInstance(u"com.sun.star.comp.Xmloff.AnimationsImport"_ustr ), UNO_QUERY_THROW );
229 xFilter->parseStream( aParserInput );
231 Reference< XAnimationNodeSupplier > xAnimationNodeSupplier( xFilter, UNO_QUERY_THROW );
232 xRootNode = xAnimationNodeSupplier->getAnimationNode();
234 catch (const Exception&)
236 TOOLS_WARN_EXCEPTION("sd", "");
239 return xRootNode;
242 void CustomAnimationPresets::importEffects()
246 const uno::Reference< uno::XComponentContext >& xContext(
247 comphelper::getProcessComponentContext() );
248 Reference< XMultiServiceFactory > xServiceFactory(
249 xContext->getServiceManager(), UNO_QUERY_THROW );
251 Reference< XMultiServiceFactory > xConfigProvider =
252 configuration::theDefaultProvider::get( xContext );
254 // read path to transition effects files from config
255 uno::Sequence< OUString > aFiles;
256 aFiles = officecfg::Office::Impress::Misc::EffectFiles::get();
257 for (const auto& rFile : aFiles)
259 OUString aURL = comphelper::getExpandedUri(xContext, rFile);
261 mxRootNode = implImportEffects( xServiceFactory, aURL );
263 if( mxRootNode.is() )
265 Reference< XTimeContainer > xRootContainer( mxRootNode, UNO_QUERY_THROW );
266 EffectSequenceHelper aSequence( xRootContainer );
268 EffectSequence::iterator aIter( aSequence.getBegin() );
269 const EffectSequence::iterator aEnd( aSequence.getEnd() );
271 while( aIter != aEnd )
273 CustomAnimationEffectPtr pEffect = *aIter;
275 const OUString aPresetId( pEffect->getPresetId() );
276 CustomAnimationPresetPtr pDescriptor = getEffectDescriptor( aPresetId );
277 if( pDescriptor )
278 pDescriptor->add( pEffect );
279 else
281 pDescriptor = std::make_shared<CustomAnimationPreset>( pEffect );
282 pDescriptor->maLabel = getUINameForPresetId( pEffect->getPresetId() );
283 maEffectDescriptorMap[aPresetId] = std::move(pDescriptor);
286 ++aIter;
291 catch (const Exception&)
293 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPresets::importEffects()" );
297 void CustomAnimationPresets::importResources()
301 // Get service factory
302 const Reference< XComponentContext >& xContext( comphelper::getProcessComponentContext() );
304 Reference< XMultiServiceFactory > xConfigProvider =
305 configuration::theDefaultProvider::get( xContext );
307 implImportLabels( xConfigProvider, u"/org.openoffice.Office.UI.Effects/UserInterface/Properties"_ustr, maPropertyNameMap );
309 implImportLabels( xConfigProvider, u"/org.openoffice.Office.UI.Effects/UserInterface/Effects"_ustr, maEffectNameMap );
311 importEffects();
313 importPresets( xConfigProvider, u"/org.openoffice.Office.UI.Effects/Presets/Entrance"_ustr, maEntrancePresets );
315 importPresets( xConfigProvider, u"/org.openoffice.Office.UI.Effects/Presets/Emphasis"_ustr, maEmphasisPresets );
317 importPresets( xConfigProvider, u"/org.openoffice.Office.UI.Effects/Presets/Exit"_ustr, maExitPresets );
319 importPresets( xConfigProvider, u"/org.openoffice.Office.UI.Effects/Presets/MotionPaths"_ustr, maMotionPathsPresets );
321 importPresets( xConfigProvider, u"/org.openoffice.Office.UI.Effects/Presets/Misc"_ustr, maMiscPresets );
323 catch (const Exception&)
325 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPresets::importResources()" );
329 void CustomAnimationPresets::importPresets( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, PresetCategoryList& rPresetMap )
331 #if OSL_DEBUG_LEVEL >= 2
332 OUString aMissedPresetIds;
333 #endif
337 Reference< XNameAccess > xTypeAccess( getNodeAccess( xConfigProvider, rNodePath ) );
338 if( xTypeAccess.is() )
340 Reference< XNameAccess > xCategoryAccess;
342 const Sequence< OUString > aNames( xTypeAccess->getElementNames() );
343 for(const OUString& rName : aNames)
345 xTypeAccess->getByName( rName ) >>= xCategoryAccess;
347 if( xCategoryAccess.is() && xCategoryAccess->hasByName( u"Label"_ustr ) && xCategoryAccess->hasByName( u"Effects"_ustr ) )
349 OUString aLabel;
350 xCategoryAccess->getByName( u"Label"_ustr ) >>= aLabel;
352 Sequence< OUString > aEffects;
353 xCategoryAccess->getByName( u"Effects"_ustr ) >>= aEffects;
355 EffectDescriptorList aEffectsList;
357 for (const OUString& rEffectName : aEffects)
359 CustomAnimationPresetPtr pEffect = getEffectDescriptor( rEffectName );
360 if( pEffect )
362 aEffectsList.push_back( pEffect );
364 #if OSL_DEBUG_LEVEL >= 2
365 else
367 aMissedPresetIds += OUString(rEffectName);
368 aMissedPresetIds += "\n";
370 #endif
372 rPresetMap.push_back( std::make_shared<PresetCategory>( aLabel, std::move(aEffectsList) ) );
377 catch (const Exception&)
379 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPresets::importPresets()" );
382 #if OSL_DEBUG_LEVEL >= 2
383 SAL_WARN_IF(!aMissedPresetIds.isEmpty(), "sd", "sd::CustomAnimationPresets::importPresets(), invalid preset id: "
384 << aMissedPresetIds);
385 #endif
388 CustomAnimationPresetPtr CustomAnimationPresets::getEffectDescriptor( const OUString& rPresetId ) const
390 EffectDescriptorMap::const_iterator aIter( maEffectDescriptorMap.find( rPresetId ) );
392 if( aIter != maEffectDescriptorMap.end() )
394 return (*aIter).second;
396 else
398 return CustomAnimationPresetPtr(nullptr);
402 const OUString& CustomAnimationPresets::getUINameForPresetId( const OUString& rPresetId ) const
404 return translateName( rPresetId, maEffectNameMap );
407 const OUString& CustomAnimationPresets::getUINameForProperty( const OUString& rPresetId ) const
409 return translateName( rPresetId, maPropertyNameMap );
412 const OUString& CustomAnimationPresets::translateName( const OUString& rId, const UStringMap& rNameMap )
414 UStringMap::const_iterator aIter( rNameMap.find( rId ) );
416 if( aIter != rNameMap.end() )
418 return (*aIter).second;
420 else
422 return rId;
425 void CustomAnimationPresets::changePresetSubType( const CustomAnimationEffectPtr& pEffect, const OUString& rPresetSubType ) const
427 if( pEffect && pEffect->getPresetSubType() != rPresetSubType )
429 CustomAnimationPresetPtr pDescriptor( getEffectDescriptor( pEffect->getPresetId() ) );
431 if( pDescriptor )
433 Reference< XAnimationNode > xNewNode( pDescriptor->create( rPresetSubType ) );
434 if( xNewNode.is() )
435 pEffect->replaceNode( xNewNode );
440 std::map<OUString, CustomAnimationPresets> CustomAnimationPresets::mPresetsMap;
442 const CustomAnimationPresets& CustomAnimationPresets::getCustomAnimationPresets()
444 // Support localization per-view. Currently not useful for Desktop
445 // but very much critical for LOK. The cache now is per-language.
446 const OUString aLang = comphelper::LibreOfficeKit::isActive()
447 ? comphelper::LibreOfficeKit::getLanguageTag().getBcp47()
448 : SvtSysLocaleOptions().GetLanguageTag().getBcp47();
450 SolarMutexGuard aGuard;
451 const auto it = mPresetsMap.find(aLang);
452 if (it != mPresetsMap.end())
453 return it->second;
455 CustomAnimationPresets& rPresets = mPresetsMap[aLang];
456 rPresets.importResources();
457 return rPresets;
460 Reference< XAnimationNode > CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass ) const
462 Reference< XAnimationNode > xNode;
464 const PresetCategoryList* pCategoryList = nullptr;
465 switch( nPresetClass )
467 case EffectPresetClass::ENTRANCE: pCategoryList = &maEntrancePresets; break;
468 case EffectPresetClass::EXIT: pCategoryList = &maExitPresets; break;
469 case EffectPresetClass::EMPHASIS: pCategoryList = &maEmphasisPresets; break;
470 case EffectPresetClass::MOTIONPATH: pCategoryList = &maMotionPathsPresets; break;
471 default:
472 pCategoryList = nullptr;
475 if( pCategoryList && !pCategoryList->empty() )
477 sal_Int32 nCategory = comphelper::rng::uniform_size_distribution(0, pCategoryList->size()-1);
479 PresetCategoryPtr pCategory = (*pCategoryList)[nCategory];
480 if( pCategory && !pCategory->maEffects.empty() )
482 sal_Int32 nDescriptor = comphelper::rng::uniform_size_distribution(0, pCategory->maEffects.size()-1);
483 CustomAnimationPresetPtr pPreset = pCategory->maEffects[nDescriptor];
484 if( pPreset )
486 std::vector<OUString> aSubTypes = pPreset->getSubTypes();
488 OUString aSubType;
489 if( !aSubTypes.empty() )
491 size_t nSubType = comphelper::rng::uniform_size_distribution(0, aSubTypes.size()-1);
492 aSubType = aSubTypes[nSubType];
494 xNode = pPreset->create( aSubType );
499 return xNode;
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */