bump product version to 6.4.0.3
[LibreOffice.git] / sd / source / core / EffectMigration.cxx
blob8f73d7bb8883c4af04e622f98187da03c38ccd99
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/presentation/EffectNodeType.hpp>
21 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
22 #include <com/sun/star/presentation/TextAnimationType.hpp>
23 #include <com/sun/star/presentation/ParagraphTarget.hpp>
24 #include <comphelper/processfactory.hxx>
25 #include <com/sun/star/animations/AnimationFill.hpp>
26 #include <com/sun/star/animations/XAnimate.hpp>
27 #include <com/sun/star/beans/NamedValue.hpp>
28 #include <tools/debug.hxx>
29 #include <svx/unoshape.hxx>
30 #include <svx/svdotext.hxx>
31 #include <svx/svdopath.hxx>
32 #include <svx/svdogrp.hxx>
33 #include <svx/svditer.hxx>
34 #include <drawdoc.hxx>
35 #include <sdpage.hxx>
36 #include <CustomAnimationPreset.hxx>
37 #include <TransitionPreset.hxx>
38 #include <EffectMigration.hxx>
39 #include <anminfo.hxx>
41 using namespace ::sd;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::animations;
44 using namespace ::com::sun::star::presentation;
45 using ::com::sun::star::drawing::XShape;
46 using ::com::sun::star::lang::XMultiServiceFactory;
47 using ::com::sun::star::drawing::XShape;
48 using ::com::sun::star::beans::NamedValue;
50 struct deprecated_FadeEffect_conversion_table_entry
52 FadeEffect const meFadeEffect;
53 const sal_Char* mpPresetId;
56 const deprecated_FadeEffect_conversion_table[] =
58 // OOo 1.x transitions
59 { FadeEffect_FADE_FROM_LEFT, "wipe-right" },
60 { FadeEffect_FADE_FROM_TOP, "wipe-down" },
61 { FadeEffect_FADE_FROM_RIGHT, "wipe-left" },
62 { FadeEffect_FADE_FROM_BOTTOM, "wipe-up" },
64 { FadeEffect_CLOCKWISE, "wheel-clockwise-1-spoke" },
66 { FadeEffect_UNCOVER_TO_LEFT, "uncover-left" },
67 { FadeEffect_UNCOVER_TO_UPPERLEFT, "uncover-left-up" },
68 { FadeEffect_UNCOVER_TO_TOP, "uncover-up" },
69 { FadeEffect_UNCOVER_TO_UPPERRIGHT, "uncover-right-up" },
70 { FadeEffect_UNCOVER_TO_RIGHT, "uncover-right" },
71 { FadeEffect_UNCOVER_TO_LOWERRIGHT, "uncover-right-down" },
72 { FadeEffect_UNCOVER_TO_BOTTOM, "uncover-down" },
73 { FadeEffect_UNCOVER_TO_LOWERLEFT, "uncover-left-down" },
75 { FadeEffect_VERTICAL_LINES, "random-bars-vertical" },
76 { FadeEffect_HORIZONTAL_LINES, "random-bars-horizontal" },
78 { FadeEffect_VERTICAL_CHECKERBOARD, "checkerboard-down" },
79 { FadeEffect_HORIZONTAL_CHECKERBOARD, "checkerboard-across" },
81 { FadeEffect_FADE_TO_CENTER, "box-in" },
82 { FadeEffect_FADE_FROM_CENTER, "box-out" },
84 { FadeEffect_VERTICAL_STRIPES, "venetian-blinds-vertical" },
85 { FadeEffect_HORIZONTAL_STRIPES, "venetian-blinds-horizontal" },
87 { FadeEffect_MOVE_FROM_LEFT, "cover-right" },
88 { FadeEffect_MOVE_FROM_TOP, "cover-down" },
89 { FadeEffect_MOVE_FROM_RIGHT, "cover-left" },
90 { FadeEffect_MOVE_FROM_BOTTOM, "cover-up" },
91 { FadeEffect_MOVE_FROM_UPPERLEFT, "cover-right-down" },
92 { FadeEffect_MOVE_FROM_UPPERRIGHT, "cover-left-down" },
93 { FadeEffect_MOVE_FROM_LOWERRIGHT, "cover-left-up" },
94 { FadeEffect_MOVE_FROM_LOWERLEFT, "cover-right-up" },
96 { FadeEffect_DISSOLVE, "dissolve" },
98 { FadeEffect_RANDOM, "random-transition" },
100 { FadeEffect_ROLL_FROM_LEFT, "push-right" },
101 { FadeEffect_ROLL_FROM_TOP, "push-down" },
102 { FadeEffect_ROLL_FROM_RIGHT, "push-left" },
103 { FadeEffect_ROLL_FROM_BOTTOM, "push-up" },
105 { FadeEffect_CLOSE_VERTICAL, "split-horizontal-in" },
106 { FadeEffect_CLOSE_HORIZONTAL, "split-vertical-in" },
107 { FadeEffect_OPEN_VERTICAL, "split-horizontal-out" },
108 { FadeEffect_OPEN_HORIZONTAL, "split-vertical-out" },
110 { FadeEffect_FADE_FROM_UPPERLEFT, "diagonal-squares-right-down" },
111 { FadeEffect_FADE_FROM_UPPERRIGHT, "diagonal-squares-left-down" },
112 { FadeEffect_FADE_FROM_LOWERLEFT, "diagonal-squares-right-up" },
113 { FadeEffect_FADE_FROM_LOWERRIGHT, "diagonal-squares-left-up" },
115 // OOo 1.x transitions not in OOo 2.x
116 { FadeEffect_CLOCKWISE, "clock-wipe-twelve" },
117 { FadeEffect_COUNTERCLOCKWISE, "reverse-clock-wipe-twelve" },
118 { FadeEffect_SPIRALIN_LEFT, "spiral-wipe-top-left-clockwise" },
119 { FadeEffect_SPIRALIN_RIGHT, "spiral-wipe-top-right-counter-clockwise" },
120 { FadeEffect_SPIRALOUT_LEFT, "spiral-wipe-out-to-bottom-right-clockwise" },
121 { FadeEffect_SPIRALOUT_RIGHT, "spiral-wipe-out-to-bottom-left-counter-clockwise" },
122 { FadeEffect_WAVYLINE_FROM_LEFT, "snake-wipe-top-left-vertical" },
123 { FadeEffect_WAVYLINE_FROM_TOP, "snake-wipe-top-left-horizontal" },
124 { FadeEffect_WAVYLINE_FROM_RIGHT, "snake-wipe-bottom-right-vertical" },
125 { FadeEffect_WAVYLINE_FROM_BOTTOM, "snake-wipe-bottom-right-horizontal" },
126 { FadeEffect_STRETCH_FROM_LEFT, "wipe-right" }, // todo
127 { FadeEffect_STRETCH_FROM_TOP, "wipe-down" }, // todo
128 { FadeEffect_STRETCH_FROM_RIGHT, "wipe-left" }, // todo
129 { FadeEffect_STRETCH_FROM_BOTTOM, "wipe-up" }, // todo
131 // OOo 1.x not available transitions
133 { FadeEffect_CLOCKWISE, "wheel-clockwise-2-spokes" },
134 { FadeEffect_CLOCKWISE, "wheel-clockwise-3-spokes" },
135 { FadeEffect_CLOCKWISE, "wheel-clockwise-4-spokes" },
136 { FadeEffect_CLOCKWISE, "wheel-clockwise-8-spokes" },
138 { FadeEffect_FADE_FROM_CENTER, "shape-circle" },
139 { FadeEffect_FADE_FROM_CENTER, "shape-diamond" },
140 { FadeEffect_FADE_FROM_CENTER, "shape-plus" },
142 { FadeEffect_CLOCKWISE, "wedge" },
144 { FadeEffect_DISSOLVE, "fade-through-black" },
146 { FadeEffect_CLOCKWISE, "zoom-rotate-in" },
148 { FadeEffect_HORIZONTAL_LINES, "comb-horizontal" },
149 { FadeEffect_VERTICAL_LINES, "comb-vertical" },
151 { FadeEffect_DISSOLVE, "fade-smoothly" },
153 { FadeEffect_NONE, nullptr }
156 /* todo
157 cut cut (same as NONE?)
158 cut-through-black cut toBlack
159 wedge wedge
162 void EffectMigration::SetFadeEffect( SdPage* pPage, css::presentation::FadeEffect eNewEffect)
164 deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table;
165 while( (pEntry->meFadeEffect != FadeEffect_NONE) && (pEntry->meFadeEffect != eNewEffect) )
166 pEntry++;
168 if( pEntry->mpPresetId )
170 const OUString aPresetId( OUString::createFromAscii( pEntry->mpPresetId ) );
172 const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();
174 auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(),
175 [&aPresetId](const TransitionPresetPtr& rxPreset) { return rxPreset->getPresetId() == aPresetId; });
176 if (aIt != rPresetList.end())
178 pPage->setTransitionType( (*aIt)->getTransition() );
179 pPage->setTransitionSubtype( (*aIt)->getSubtype() );
180 pPage->setTransitionDirection( (*aIt)->getDirection() );
181 pPage->setTransitionFadeColor( (*aIt)->getFadeColor() );
184 else
186 pPage->setTransitionType( 0 );
187 pPage->setTransitionSubtype( 0 );
188 pPage->setTransitionDirection( false );
189 pPage->setTransitionFadeColor( 0 );
193 FadeEffect EffectMigration::GetFadeEffect( const SdPage* pPage )
195 const TransitionPresetList & rPresetList = TransitionPreset::getTransitionPresetList();
196 auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(),
197 [&pPage](const TransitionPresetPtr& rxPreset) {
198 return (rxPreset->getTransition() == pPage->getTransitionType())
199 && (rxPreset->getSubtype() == pPage->getTransitionSubtype())
200 && (rxPreset->getDirection() == pPage->getTransitionDirection())
201 && (rxPreset->getFadeColor() == pPage->getTransitionFadeColor());
203 if (aIt != rPresetList.end())
205 const OUString& aPresetId = (*aIt)->getPresetId();
207 deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table;
208 while( (pEntry->meFadeEffect != FadeEffect_NONE) && (!aPresetId.equalsAscii( pEntry->mpPresetId ) ) )
209 pEntry++;
211 return pEntry->meFadeEffect;
213 return FadeEffect_NONE;
216 struct deprecated_AnimationEffect_conversion_table_entry
218 AnimationEffect const meEffect;
219 const sal_Char* mpPresetId;
220 const sal_Char* mpPresetSubType;
222 const deprecated_AnimationEffect_conversion_table[] =
224 // OOo 1.x entrance effects
225 { AnimationEffect_APPEAR, "ooo-entrance-appear",nullptr },
227 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-box","in" },
228 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-box","out" },
230 { AnimationEffect_VERTICAL_CHECKERBOARD, "ooo-entrance-checkerboard","downward" },
231 { AnimationEffect_HORIZONTAL_CHECKERBOARD, "ooo-entrance-checkerboard","across" },
233 { AnimationEffect_FADE_FROM_UPPERLEFT, "ooo-entrance-diagonal-squares","right-to-bottom" },
234 { AnimationEffect_FADE_FROM_UPPERRIGHT, "ooo-entrance-diagonal-squares","left-to-bottom" },
235 { AnimationEffect_FADE_FROM_LOWERLEFT, "ooo-entrance-diagonal-squares","right-to-top" },
236 { AnimationEffect_FADE_FROM_LOWERRIGHT, "ooo-entrance-diagonal-squares","left-to-top" },
238 { AnimationEffect_DISSOLVE, "ooo-entrance-dissolve-in",nullptr },
240 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
241 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in","from-top" },
242 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
243 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
244 { AnimationEffect_MOVE_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
245 { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
246 { AnimationEffect_MOVE_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },
247 { AnimationEffect_MOVE_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },
249 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in-slow", "from-bottom" },
250 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in-slow", "from-left" },
251 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in-slow", "from-right" },
252 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in-slow", "from-top" },
254 { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-peek-in","from-left" },
255 { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-peek-in","from-top" },
256 { AnimationEffect_MOVE_SHORT_FROM_RIGHT, "ooo-entrance-peek-in","from-right" },
257 { AnimationEffect_MOVE_SHORT_FROM_BOTTOM, "ooo-entrance-peek-in","from-bottom" },
259 { AnimationEffect_VERTICAL_LINES, "ooo-entrance-random-bars","horizontal" },
260 { AnimationEffect_HORIZONTAL_LINES, "ooo-entrance-random-bars","vertical" },
262 { AnimationEffect_RANDOM, "ooo-entrance-random",nullptr },
264 { AnimationEffect_CLOSE_VERTICAL, "ooo-entrance-split","horizontal-in" },
265 { AnimationEffect_CLOSE_HORIZONTAL, "ooo-entrance-split","vertical-in" },
266 { AnimationEffect_OPEN_VERTICAL, "ooo-entrance-split","horizontal-out" },
267 { AnimationEffect_OPEN_HORIZONTAL, "ooo-entrance-split","vertical-out" },
269 { AnimationEffect_VERTICAL_STRIPES, "ooo-entrance-venetian-blinds","horizontal" },
270 { AnimationEffect_HORIZONTAL_STRIPES, "ooo-entrance-venetian-blinds","vertical" },
272 { AnimationEffect_FADE_FROM_LEFT, "ooo-entrance-wipe","from-left" },
273 { AnimationEffect_FADE_FROM_TOP, "ooo-entrance-wipe","from-bottom" },
274 { AnimationEffect_FADE_FROM_RIGHT, "ooo-entrance-wipe","from-right" },
275 { AnimationEffect_FADE_FROM_BOTTOM, "ooo-entrance-wipe","from-top" },
277 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-swivel","vertical" },
278 { AnimationEffect_VERTICAL_ROTATE, "ooo-entrance-swivel","horizontal" },
280 { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy","from-left" },
281 { AnimationEffect_STRETCH_FROM_UPPERLEFT, "ooo-entrance-stretchy","from-top-left" },
282 { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy","from-top" },
283 { AnimationEffect_STRETCH_FROM_UPPERRIGHT, "ooo-entrance-stretchy","from-top-right" },
284 { AnimationEffect_STRETCH_FROM_RIGHT, "ooo-entrance-stretchy","from-right" },
285 { AnimationEffect_STRETCH_FROM_LOWERRIGHT, "ooo-entrance-stretchy","from-bottom-right" },
286 { AnimationEffect_STRETCH_FROM_BOTTOM, "ooo-entrance-stretchy","from-bottom" },
287 { AnimationEffect_STRETCH_FROM_LOWERLEFT, "ooo-entrance-stretchy","from-bottom-left" },
289 { AnimationEffect_HORIZONTAL_STRETCH, "ooo-entrance-expand", nullptr },
291 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel","1" },
292 { AnimationEffect_COUNTERCLOCKWISE, "ooo-entrance-clock-wipe","counter-clockwise" },
294 { AnimationEffect_SPIRALIN_LEFT, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" },
295 { AnimationEffect_SPIRALIN_RIGHT, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" },
296 { AnimationEffect_SPIRALOUT_LEFT, "ooo-entrance-spiral-wipe", "from-center-clockwise" },
297 { AnimationEffect_SPIRALOUT_RIGHT, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" },
299 { AnimationEffect_WAVYLINE_FROM_LEFT, "ooo-entrance-snake-wipe","from-top-left-vertical" },
300 { AnimationEffect_WAVYLINE_FROM_TOP, "ooo-entrance-snake-wipe","from-top-left-horizontal" },
301 { AnimationEffect_WAVYLINE_FROM_RIGHT, "ooo-entrance-snake-wipe","from-bottom-right-vertical" },
302 { AnimationEffect_WAVYLINE_FROM_BOTTOM, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" },
304 // ooo 1.x exit effects
305 { AnimationEffect_HIDE, "ooo-exit-disappear",nullptr },
306 { AnimationEffect_MOVE_TO_LEFT, "ooo-exit-fly-out", "from-right" },
307 { AnimationEffect_MOVE_TO_TOP, "ooo-exit-fly-out", "from-bottom" },
308 { AnimationEffect_MOVE_TO_RIGHT, "ooo-exit-fly-out", "from-left" },
309 { AnimationEffect_MOVE_TO_BOTTOM, "ooo-exit-fly-out", "from-top" },
310 { AnimationEffect_MOVE_TO_UPPERLEFT, "ooo-exit-fly-out", "from-top-right" },
311 { AnimationEffect_MOVE_TO_UPPERRIGHT, "ooo-exit-fly-out", "from-top-left" },
312 { AnimationEffect_MOVE_TO_LOWERRIGHT, "ooo-exit-fly-out", "from-bottom-left" },
313 { AnimationEffect_MOVE_TO_LOWERLEFT, "ooo-exit-fly-out", "from-bottom-right" },
314 { AnimationEffect_MOVE_SHORT_TO_LEFT, "ooo-exit-peek-out", "from-right" },
315 { AnimationEffect_MOVE_SHORT_TO_UPPERLEFT, "ooo-exit-peek-out", "from-right" },
316 { AnimationEffect_MOVE_SHORT_TO_TOP, "ooo-exit-peek-out", "from-bottom" },
317 { AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT, "ooo-exit-peek-out", "from-bottom" },
318 { AnimationEffect_MOVE_SHORT_TO_RIGHT, "ooo-exit-peek-out", "from-left" },
319 { AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT, "ooo-exit-peek-out","from-left" },
320 { AnimationEffect_MOVE_SHORT_TO_BOTTOM, "ooo-exit-peek-out", "from-top" },
321 { AnimationEffect_MOVE_SHORT_TO_LOWERLEFT, "ooo-exit-peek-out", "from-top" },
323 // no matching in OOo 2.x
324 { AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT, "ooo-entrance-peek-in","from-left" },
325 { AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT, "ooo-entrance-peek-in","from-top" },
326 { AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT, "ooo-entrance-peek-in","from-right" },
327 { AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT, "ooo-entrance-peek-in","from-bottom" },
328 { AnimationEffect_LASER_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
329 { AnimationEffect_LASER_FROM_TOP, "ooo-entrance-fly-in","from-top" },
330 { AnimationEffect_LASER_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
331 { AnimationEffect_LASER_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
332 { AnimationEffect_LASER_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
333 { AnimationEffect_LASER_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
334 { AnimationEffect_LASER_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },
335 { AnimationEffect_LASER_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },
337 // no matching in OOo 1.x
339 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-circle", "in" },
340 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-circle", "out" },
341 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-diamond", "in" },
342 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-diamond", "out" },
343 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-plus", "in" },
344 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-plus", "out" },
345 { AnimationEffect_CLOCKWISE, "ooo-entrance-wedge", nullptr },
346 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "2" },
347 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "3" },
348 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "4" },
349 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "8" },
351 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-boomerang", nullptr },
352 { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-bounce", nullptr },
353 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-curve-up", nullptr },
354 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-float", nullptr },
355 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-glide", nullptr },
356 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-magnify", nullptr },
357 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-pinwheel", nullptr },
358 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-breaks", nullptr },
359 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-sling", nullptr },
360 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-spiral-in", nullptr },
361 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-thread", nullptr },
362 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-ascend", nullptr },
363 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-center-revolve", nullptr },
364 { AnimationEffect_APPEAR, "ooo-entrance-compress", nullptr },
365 { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-descend", nullptr },
366 { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-ease-in", nullptr },
367 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-rise-up", nullptr },
368 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-spin-in", nullptr },
369 { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy", "across" },
370 { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy", "downward" },
372 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in" },
373 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-slightly" },
374 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-from-screen-center" },
375 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out" },
376 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-slightly" },
377 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-from-screen-center" },
379 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in", nullptr },
380 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-zoom", nullptr },
381 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-swivel", nullptr },
383 // still open (no matching effect: AnimationEffect_ZOOM_IN_FROM_*,
384 // AnimationEffect_ZOOM_OUT_FROM_*, AnimationEffect_PATH
386 { AnimationEffect_NONE, nullptr, nullptr }
389 static EffectSequence::iterator ImplFindEffect( MainSequencePtr const & pMainSequence, const Reference< XShape >& rShape, sal_Int16 nSubItem )
391 return std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
392 [&rShape, &nSubItem](const CustomAnimationEffectPtr& pEffect) {
393 return (pEffect->getTargetShape() == rShape)
394 && (pEffect->getTargetSubItem() == nSubItem);
398 static bool implIsInsideGroup( SdrObject const * pObj )
400 // TTTT for current state of transition, SdrObject has a parent*
401 // to a SdrObjList. That may be a SdrPage or a SdrObjGroup, both
402 // are already derived from SdrObjList. To finally check, use
403 // the method 'getSdrObjectFromSdrObjList' - if it's not a SdrPage,
404 // it will return SdrObjGroup or E3dScene -> SdrObject.
405 // For future states, test for SdrObject. Trying to get the SdrPage
406 // will in the future depend on the Object(this) to be inserted to a
407 // SdrPage, regardless of e.g. being a group member.
408 if(nullptr == pObj)
410 return false;
413 SdrObjList* pSdrObjList(pObj->getParentSdrObjListFromSdrObject());
415 if(nullptr == pSdrObjList)
417 return false;
420 return (nullptr != pSdrObjList->getSdrObjectFromSdrObjList());
423 void EffectMigration::SetAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
425 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
426 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
427 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
428 return;
430 SdrObject* pObj = pShape->GetSdrObject();
431 if( implIsInsideGroup( pObj ) )
432 return;
434 OUString aPresetId;
435 OUString aPresetSubType;
437 if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
439 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
440 return;
443 const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
445 CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );
446 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
448 if( !(pPreset.get() && pMainSequence.get()) )
449 return;
451 const Reference< XShape > xShape( pShape );
453 EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
454 EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
455 const EffectSequence::iterator aEnd( pMainSequence->getEnd() );
457 if( (aIterOnlyBackground == aEnd) && (aIterAsWhole == aEnd) )
459 bool bEffectCreated = false;
461 // check if there is already a text effect for this shape
462 EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
463 if( aIterOnlyText != aEnd )
465 // check if this is an animation text group
466 sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
467 if( nGroupId >= 0 )
469 CustomAnimationTextGroupPtr pGroup = pMainSequence->findGroup( nGroupId );
470 if( pGroup.get() )
472 // add an effect to animate the shape
473 pMainSequence->setAnimateForm( pGroup, true );
475 // find this effect
476 EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
478 if( aIter != aEnd )
480 if( ((*aIter)->getPresetId() != aPresetId) ||
481 ((*aIter)->getPresetSubType() != aPresetSubType) )
483 (*aIter)->replaceNode( pPreset->create( aPresetSubType ) );
484 pMainSequence->rebuild();
485 bEffectCreated = true;
492 if( !bEffectCreated )
494 // if there is not yet an effect that target this shape, we generate one
495 // we insert the shape effect before it
496 Reference< XAnimationNode > xNode( pPreset->create( aPresetSubType ) );
497 DBG_ASSERT( xNode.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" );
498 if( xNode.is() )
500 CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xNode ) );
501 pEffect->setTarget( makeAny( xShape ) );
502 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
503 const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PRESCHANGE_MANUAL);
504 if( !bManual )
505 pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
507 pMainSequence->append( pEffect );
509 if( ( pObj->GetObjInventor() == SdrInventor::Default ) && ( pObj->GetObjIdentifier() == OBJ_OUTLINETEXT ) )
511 // special case for outline text, effects are always mapped to text group effect
512 pMainSequence->
513 createTextGroup( pEffect, 10, bManual ? -1 : 0.0, false, false );
518 else
520 // if there is already an effect targeting this shape
521 // just replace it
522 CustomAnimationEffectPtr pEffect;
523 if( aIterAsWhole != aEnd )
525 pEffect = *aIterAsWhole;
527 else
529 pEffect = *aIterOnlyBackground;
532 if( pEffect.get() )
534 if( (pEffect->getPresetId() != aPresetId) ||
535 (pEffect->getPresetSubType() != aPresetSubType) )
537 pMainSequence->replace( pEffect, pPreset, aPresetSubType, -1.0 );
543 AnimationEffect EffectMigration::GetAnimationEffect( SvxShape* pShape )
545 OUString aPresetId;
546 OUString aPresetSubType;
548 SdrObject* pObj = pShape->GetSdrObject();
549 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
551 if( pMainSequence.get() )
553 const Reference< XShape > xShape( pShape );
555 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
556 [&xShape](const CustomAnimationEffectPtr& pEffect) {
557 return (pEffect->getTargetShape() == xShape)
558 && ((pEffect->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND)
559 || (pEffect->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE))
560 && (pEffect->getDuration() != 0.1); // ignore appear effects created from old text effect import
563 if (aIter != pMainSequence->getEnd())
565 aPresetId = (*aIter)->getPresetId();
566 aPresetSubType = (*aIter)->getPresetSubType();
570 // now find old effect
571 AnimationEffect eEffect = AnimationEffect_NONE;
573 if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
574 ConvertPreset( aPresetId, nullptr, eEffect );
576 return eEffect;
579 void EffectMigration::SetTextAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
581 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
582 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
583 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
584 return;
586 SdrObject* pObj = pShape->GetSdrObject();
587 if( implIsInsideGroup( pObj ) )
588 return;
590 // first map the deprecated AnimationEffect to a preset and subtype
591 OUString aPresetId;
592 OUString aPresetSubType;
594 if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
596 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
597 return;
600 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj );
602 // ignore old text effects on shape without text
603 if( (pTextObj == nullptr) || (!pTextObj->HasText()) )
604 return;
606 const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
608 // create an effect from this preset
609 CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );
611 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
613 if( !(pPreset.get() && pMainSequence.get()) )
614 return;
616 const Reference< XShape > xShape( pShape );
618 EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
619 const EffectSequence::iterator aEnd( pMainSequence->getEnd() );
621 CustomAnimationTextGroupPtr pGroup;
623 // is there already an animation text group for this shape?
624 if( aIterOnlyText != aEnd )
626 const sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
627 if( nGroupId >= 0 )
628 pGroup = pMainSequence->findGroup( nGroupId );
631 // if there is not yet a group, create it
632 if( pGroup.get() == nullptr )
634 CustomAnimationEffectPtr pShapeEffect;
636 EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
637 if( aIterOnlyBackground != aEnd )
639 pShapeEffect = *aIterOnlyBackground;
641 else
643 EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
644 if( aIterAsWhole != aEnd )
646 pShapeEffect = *aIterAsWhole;
648 else
650 CustomAnimationPresetPtr pShapePreset( rPresets.getEffectDescriptor( "ooo-entrance-appear" ) );
652 Reference< XAnimationNode > xNode( pPreset->create( "" ) );
653 DBG_ASSERT( xNode.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" );
654 if( xNode.is() )
656 pShapeEffect.reset( new CustomAnimationEffect( xNode ) );
657 pShapeEffect->setTarget( makeAny( xShape ) );
658 pShapeEffect->setDuration( 0.1 );
659 pMainSequence->append( pShapeEffect );
661 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
662 if( pPage && pPage->GetPresChange() != PRESCHANGE_MANUAL )
663 pShapeEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
668 if( pShapeEffect.get() )
670 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
671 const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PRESCHANGE_MANUAL);
673 // now create effects for each paragraph
674 pGroup =
675 pMainSequence->
676 createTextGroup( pShapeEffect, 10, bManual ? -1 : 0.0, true, false );
680 if( pGroup.get() != nullptr )
682 const bool bLaserEffect = (eEffect >= AnimationEffect_LASER_FROM_LEFT) && (eEffect <= AnimationEffect_LASER_FROM_LOWERRIGHT);
684 // now we have a group, so check if all effects are same as we like to have them
685 const EffectSequence& rEffects = pGroup->getEffects();
687 for( auto& rxEffect : rEffects )
689 // only work on paragraph targets
690 if( rxEffect->getTarget().getValueType() == ::cppu::UnoType<ParagraphTarget>::get() )
692 if( (rxEffect->getPresetId() != aPresetId) ||
693 (rxEffect->getPresetSubType() != aPresetSubType) )
695 rxEffect->replaceNode( pPreset->create( aPresetSubType ) );
698 if( bLaserEffect )
700 rxEffect->setIterateType( TextAnimationType::BY_LETTER );
701 rxEffect->setIterateInterval( 0.5 );// TODO:
702 // Determine
703 // interval
704 // according
705 // to
706 // total
707 // effect
708 // duration
713 pMainSequence->rebuild();
716 AnimationEffect EffectMigration::GetTextAnimationEffect( SvxShape* pShape )
718 OUString aPresetId;
719 OUString aPresetSubType;
721 SdrObject* pObj = pShape->GetSdrObject();
722 if( pObj )
724 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
726 if( pMainSequence.get() )
728 const Reference< XShape > xShape( pShape );
729 EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
730 if( aIter != pMainSequence->getEnd() )
732 aPresetId = (*aIter)->getPresetId();
733 aPresetSubType = (*aIter)->getPresetSubType();
738 // now find old effect
739 AnimationEffect eEffect = AnimationEffect_NONE;
741 if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
742 ConvertPreset( aPresetId, nullptr, eEffect );
744 return eEffect;
747 bool EffectMigration::ConvertPreset( const OUString& rPresetId, const OUString* pPresetSubType, AnimationEffect& rEffect )
749 rEffect = AnimationEffect_NONE;
750 if( !rPresetId.isEmpty() )
752 // first try a match for preset id and subtype
753 deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table;
754 while( p->mpPresetId )
756 if( rPresetId.equalsAscii( p->mpPresetId ) &&
757 (( p->mpPresetSubType == nullptr ) ||
758 ( pPresetSubType == nullptr) ||
759 ( pPresetSubType->equalsAscii( p->mpPresetSubType )) ) )
761 rEffect = p->meEffect;
762 return true;
764 p++;
766 return false;
768 else
770 // empty preset id means AnimationEffect_NONE
771 return true;
775 bool EffectMigration::ConvertAnimationEffect( const AnimationEffect& rEffect, OUString& rPresetId, OUString& rPresetSubType )
777 deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table;
778 while( p->mpPresetId )
780 if( p->meEffect == rEffect )
782 rPresetId = OUString::createFromAscii( p->mpPresetId );
783 rPresetSubType = OUString::createFromAscii( p->mpPresetSubType );
784 return true;
786 p++;
789 return false;
792 double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed )
794 double fDuration;
795 switch( eSpeed )
797 case AnimationSpeed_SLOW: fDuration = 2.0; break;
798 case AnimationSpeed_FAST: fDuration = 0.5; break;
799 default:
800 fDuration = 1.0; break;
802 return fDuration;
805 void EffectMigration::SetAnimationSpeed( SvxShape* pShape, AnimationSpeed eSpeed )
807 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
808 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
809 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
810 return;
812 SdrObject* pObj = pShape->GetSdrObject();
813 if( implIsInsideGroup( pObj ) )
814 return;
816 double fDuration = ConvertAnimationSpeed( eSpeed );
818 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
820 const Reference< XShape > xShape( pShape );
822 EffectSequence::iterator aIter;
823 bool bNeedRebuild = false;
825 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
827 CustomAnimationEffectPtr pEffect( *aIter );
828 if( pEffect->getTargetShape() == xShape )
830 if( pEffect->getDuration() != 0.1 )
831 pEffect->setDuration( fDuration );
832 bNeedRebuild = true;
836 if( bNeedRebuild )
837 pMainSequence->rebuild();
840 AnimationSpeed EffectMigration::GetAnimationSpeed( SvxShape* pShape )
842 SdrObject* pObj = pShape->GetSdrObject();
843 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
845 const Reference< XShape > xShape( pShape );
847 double fDuration = 1.0;
849 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
850 [&xShape](const CustomAnimationEffectPtr& pEffect) {
851 return (pEffect->getTargetShape() == xShape)
852 && (pEffect->getDuration() != 0.1);
854 if (aIter != pMainSequence->getEnd())
856 CustomAnimationEffectPtr pEffect( *aIter );
857 fDuration = pEffect->getDuration();
860 return ConvertDuration( fDuration );
863 AnimationSpeed EffectMigration::ConvertDuration( double fDuration )
865 AnimationSpeed eSpeed;
867 if( fDuration < 1.0 )
868 eSpeed = AnimationSpeed_FAST;
869 else if( fDuration > 1.5 )
870 eSpeed = AnimationSpeed_SLOW;
871 else
872 eSpeed = AnimationSpeed_MEDIUM;
874 return eSpeed;
877 void EffectMigration::SetDimColor( SvxShape* pShape, sal_Int32 nColor )
879 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
880 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
881 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
882 return;
884 SdrObject* pObj = pShape->GetSdrObject();
885 if( implIsInsideGroup( pObj ) )
886 return;
888 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
890 const Reference< XShape > xShape( pShape );
892 EffectSequence::iterator aIter;
893 bool bNeedRebuild = false;
895 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
897 CustomAnimationEffectPtr pEffect( *aIter );
898 if( pEffect->getTargetShape() == xShape )
900 pEffect->setHasAfterEffect( true );
901 pEffect->setDimColor( makeAny( nColor ) );
902 pEffect->setAfterEffectOnNext( true );
903 bNeedRebuild = true;
907 if( bNeedRebuild )
908 pMainSequence->rebuild();
911 sal_Int32 EffectMigration::GetDimColor( SvxShape* pShape )
913 sal_Int32 nColor = 0;
914 if( pShape )
916 SdrObject* pObj = pShape->GetSdrObject();
917 if( pObj && pObj->getSdrPageFromSdrObject() )
919 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
921 const Reference< XShape > xShape( pShape );
922 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
923 [&xShape](const CustomAnimationEffectPtr& pEffect) {
924 return (pEffect->getTargetShape() == xShape)
925 && pEffect->getDimColor().hasValue()
926 && pEffect->hasAfterEffect();
928 if (aIter != pMainSequence->getEnd())
930 CustomAnimationEffectPtr pEffect( *aIter );
931 pEffect->getDimColor() >>= nColor;
936 return nColor;
939 void EffectMigration::SetDimHide( SvxShape* pShape, bool bDimHide )
941 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
942 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
943 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
944 return;
946 SdrObject* pObj = pShape->GetSdrObject();
947 if( implIsInsideGroup( pObj ) )
948 return;
950 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
952 const Reference< XShape > xShape( pShape );
954 EffectSequence::iterator aIter;
955 bool bNeedRebuild = false;
957 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
959 CustomAnimationEffectPtr pEffect( *aIter );
960 if( pEffect->getTargetShape() == xShape )
962 pEffect->setHasAfterEffect( bDimHide );
963 if( bDimHide ) {
964 Any aEmpty;
965 pEffect->setDimColor( aEmpty );
967 pEffect->setAfterEffectOnNext( false );
968 bNeedRebuild = true;
972 if( bNeedRebuild )
973 pMainSequence->rebuild();
976 bool EffectMigration::GetDimHide( SvxShape* pShape )
978 bool bRet = false;
979 if( pShape )
981 SdrObject* pObj = pShape->GetSdrObject();
982 if( pObj && pObj->getSdrPageFromSdrObject() )
984 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
986 const Reference< XShape > xShape( pShape );
988 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
989 [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; });
990 if (aIter != pMainSequence->getEnd())
992 CustomAnimationEffectPtr pEffect( *aIter );
993 bRet = pEffect->hasAfterEffect() &&
994 !pEffect->getDimColor().hasValue() &&
995 (!pEffect->IsAfterEffectOnNext());
1000 return bRet;
1003 void EffectMigration::SetDimPrevious( SvxShape* pShape, bool bDimPrevious )
1005 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
1006 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
1007 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
1008 return;
1010 SdrObject* pObj = pShape->GetSdrObject();
1011 if( implIsInsideGroup( pObj ) )
1012 return;
1014 Any aColor;
1016 if( bDimPrevious )
1017 aColor <<= COL_LIGHTGRAY;
1019 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1021 const Reference< XShape > xShape( pShape );
1023 EffectSequence::iterator aIter;
1024 bool bNeedRebuild = false;
1026 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
1028 CustomAnimationEffectPtr pEffect( *aIter );
1029 if( pEffect->getTargetShape() == xShape )
1031 pEffect->setHasAfterEffect( bDimPrevious );
1032 if( !bDimPrevious || !pEffect->getDimColor().hasValue() )
1033 pEffect->setDimColor( aColor );
1034 pEffect->setAfterEffectOnNext( true );
1035 bNeedRebuild = true;
1039 if( bNeedRebuild )
1040 pMainSequence->rebuild();
1043 bool EffectMigration::GetDimPrevious( SvxShape* pShape )
1045 bool bRet = false;
1046 if( pShape )
1048 SdrObject* pObj = pShape->GetSdrObject();
1049 if( pObj && pObj->getSdrPageFromSdrObject() )
1051 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1053 const Reference< XShape > xShape( pShape );
1055 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
1056 [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; });
1057 if (aIter != pMainSequence->getEnd())
1059 CustomAnimationEffectPtr pEffect( *aIter );
1060 bRet = pEffect->hasAfterEffect() &&
1061 pEffect->getDimColor().hasValue() &&
1062 pEffect->IsAfterEffectOnNext();
1067 return bRet;
1070 void EffectMigration::SetPresentationOrder( SvxShape* pShape, sal_Int32 nNewPos )
1072 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
1073 return;
1075 SdrObject* pObj = pShape->GetSdrObject();
1076 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1078 EffectSequence& rSequence = pMainSequence->getSequence();
1079 sal_Int32 nPos;
1080 sal_Int32 nCurrentPos = -1;
1081 std::vector< std::vector< EffectSequence::iterator > > aEffectVector(1);
1083 if( !rSequence.empty() )
1085 Reference< XShape > xThis( pShape );
1086 Reference< XShape > xCurrent;
1088 EffectSequence::iterator aIter( rSequence.begin() );
1089 EffectSequence::iterator aEnd( rSequence.end() );
1090 for( nPos = 0; aIter != aEnd; ++aIter )
1092 CustomAnimationEffectPtr pEffect = *aIter;
1094 if( !xCurrent.is() )
1096 xCurrent = pEffect->getTargetShape();
1098 else if( pEffect->getTargetShape() != xCurrent )
1100 nPos++;
1101 xCurrent = pEffect->getTargetShape();
1102 aEffectVector.resize( nPos+1 );
1105 // is this the first effect for xThis shape?
1106 if(( nCurrentPos == -1 ) && ( xCurrent == xThis ) )
1108 nCurrentPos = nPos;
1111 aEffectVector[nPos].push_back( aIter );
1115 // check if there is at least one effect for xThis
1116 if( nCurrentPos == -1 )
1118 OSL_FAIL("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" );
1119 return;
1122 // check trivial case
1123 if( nCurrentPos == nNewPos )
1124 return;
1126 std::vector< CustomAnimationEffectPtr > aEffects;
1128 for( const auto& rIter : aEffectVector[nCurrentPos] )
1130 aEffects.push_back( *rIter );
1131 rSequence.erase( rIter );
1134 if( nNewPos > nCurrentPos )
1135 nNewPos++;
1137 if( nNewPos == static_cast<sal_Int32>(aEffectVector.size()) )
1139 std::copy(aEffects.begin(), aEffects.end(), std::back_inserter(rSequence));
1141 else
1143 EffectSequence::iterator aPos( aEffectVector[nNewPos][0] );
1144 for( const auto& rEffect : aEffects )
1146 rSequence.insert( aPos, rEffect );
1151 /** Returns the position of the given SdrObject in the Presentation order.
1152 * This function returns -1 if the SdrObject is not in the Presentation order
1153 * or if it's the path-object.
1155 sal_Int32 EffectMigration::GetPresentationOrder( SvxShape* pShape )
1157 sal_Int32 nPos = -1, nFound = -1;
1159 SdrObject* pObj = pShape->GetSdrObject();
1160 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1162 EffectSequence& rSequence = pMainSequence->getSequence();
1164 Reference< XShape > xThis( pShape );
1165 Reference< XShape > xCurrent;
1167 for( const CustomAnimationEffectPtr& pEffect : rSequence )
1169 if( !xCurrent.is() || pEffect->getTargetShape() != xCurrent )
1171 nPos++;
1172 xCurrent = pEffect->getTargetShape();
1174 // is this the first effect for xThis shape?
1175 if( xCurrent == xThis )
1177 nFound = nPos;
1178 break;
1183 return nFound;
1186 void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo const * pInfo )
1188 if( !pInfo )
1189 return;
1191 SdrObject* pObj = pShape->GetSdrObject();
1192 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1194 const Reference< XShape > xShape( pShape );
1196 EffectSequence::iterator aIter;
1197 bool bNeedRebuild = false;
1199 OUString aSoundFile;
1200 if( pInfo->mbSoundOn )
1201 aSoundFile = pInfo->maSoundFile;
1203 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
1205 CustomAnimationEffectPtr pEffect( *aIter );
1206 if( pEffect->getTargetShape() == xShape )
1208 if( !aSoundFile.isEmpty() )
1210 pEffect->createAudio( makeAny( aSoundFile ) );
1212 else
1214 pEffect->removeAudio();
1216 bNeedRebuild = true;
1220 if( bNeedRebuild )
1221 pMainSequence->rebuild();
1224 OUString EffectMigration::GetSoundFile( SvxShape* pShape )
1226 OUString aSoundFile;
1228 if( pShape )
1230 SdrObject* pObj = pShape->GetSdrObject();
1231 if( pObj && pObj->getSdrPageFromSdrObject() )
1233 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1235 const Reference< XShape > xShape( pShape );
1237 EffectSequence::iterator aIter;
1239 for( aIter = pMainSequence->getBegin();
1240 (aSoundFile.isEmpty()) && (aIter != pMainSequence->getEnd());
1241 ++aIter )
1243 CustomAnimationEffectPtr pEffect( *aIter );
1244 if( pEffect->getTargetShape() == xShape )
1246 if( pEffect->getAudio().is() )
1247 pEffect->getAudio()->getSource() >>= aSoundFile;
1252 return aSoundFile;
1255 bool EffectMigration::GetSoundOn( SvxShape* pShape )
1257 return !GetSoundFile( pShape ).isEmpty();
1260 void EffectMigration::SetAnimationPath( SvxShape* pShape, SdrPathObj const * pPathObj )
1262 if( !(pShape && pPathObj) )
1263 return;
1265 SdrObject* pObj = pShape->GetSdrObject();
1267 if( pObj )
1269 const Reference< XShape > xShape( pShape );
1270 SdPage* pPage = dynamic_cast< SdPage* >(pPathObj->getSdrPageFromSdrObject());
1271 if( pPage )
1273 std::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() );
1274 if( pMainSequence.get() )
1275 CustomAnimationEffectPtr pCreated( pMainSequence->append( *pPathObj, makeAny( xShape ), -1.0 ) );
1280 // #i42894# helper which creates the needed XAnimate for changing visibility and all the (currently) needed embeddings
1281 static void createVisibilityOnOffNode(Reference< XTimeContainer > const & rxParentContainer, SdrObject& rCandidate, bool bVisible, bool bOnClick, double fDuration)
1283 Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory());
1285 // create par container node
1286 Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW);
1288 // set begin
1289 xOuterSeqTimeContainer->setBegin(Any(0.0));
1291 // set fill
1292 xOuterSeqTimeContainer->setFill(AnimationFill::HOLD);
1294 // set named values
1295 Sequence< NamedValue > aUserDataSequence;
1296 aUserDataSequence.realloc(1);
1298 aUserDataSequence[0].Name = "node-type";
1299 aUserDataSequence[0].Value <<= bOnClick ? EffectNodeType::ON_CLICK : EffectNodeType::AFTER_PREVIOUS;
1301 xOuterSeqTimeContainer->setUserData(aUserDataSequence);
1303 // create animate set to change visibility for rCandidate
1304 Reference< XAnimationNode > xAnimateSetForLast(xMsf->createInstance("com.sun.star.animations.AnimateSet"), UNO_QUERY_THROW);
1306 // set begin
1307 xAnimateSetForLast->setBegin(Any(0.0));
1309 // set duration
1310 xAnimateSetForLast->setDuration(Any(fDuration));
1312 // set fill
1313 xAnimateSetForLast->setFill(AnimationFill::HOLD);
1315 // set target
1316 Reference< XAnimate > xAnimate(xAnimateSetForLast, UNO_QUERY);
1317 Reference< XShape > xTargetShape(rCandidate.getUnoShape(), UNO_QUERY);
1318 xAnimate->setTarget(Any(xTargetShape));
1320 // set AttributeName
1321 xAnimate->setAttributeName("Visibility");
1323 // set attribute value
1324 xAnimate->setTo(Any(bVisible));
1326 // ad set node to par node
1327 Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW);
1328 xParentContainer->appendChild(xAnimateSetForLast);
1330 // add node
1331 rxParentContainer->appendChild(xOuterSeqTimeContainer);
1334 // #i42894# older native formats supported animated group objects, that means all members of the group
1335 // were shown animated by showing one after the other. This is no longer supported, but the following
1336 // fallback will create the needed SMIL animation stuff. Unfortunately the members of the group
1337 // have to be moved directly to the page, else the (explained to be generic, thus I expected this to
1338 // work) animations will not work in slideshow
1339 void EffectMigration::CreateAnimatedGroup(SdrObjGroup const & rGroupObj, SdPage& rPage)
1341 // aw080 will give a vector immediately
1342 SdrObjListIter aIter(rGroupObj);
1344 if(!aIter.Count())
1345 return;
1347 std::shared_ptr< sd::MainSequence > pMainSequence(rPage.getMainSequence());
1349 if(!pMainSequence.get())
1350 return;
1352 std::vector< SdrObject* > aObjects;
1353 aObjects.reserve(aIter.Count());
1355 while(aIter.IsMore())
1357 // do move to page rough with old/current stuff, will be different in aw080 anyways
1358 SdrObject* pCandidate = aIter.Next();
1359 rGroupObj.GetSubList()->NbcRemoveObject(pCandidate->GetOrdNum());
1360 rPage.NbcInsertObject(pCandidate);
1361 aObjects.push_back(pCandidate);
1364 // create main node
1365 Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory());
1366 Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW);
1368 // set begin
1369 xOuterSeqTimeContainer->setBegin(Any(0.0));
1371 // prepare parent container
1372 Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW);
1374 // prepare loop over objects
1375 SdrObject* pNext = nullptr;
1376 const double fDurationShow(0.2);
1377 const double fDurationHide(0.001);
1379 for(size_t a(0); a < aObjects.size(); a++)
1381 SdrObject* pLast = pNext;
1382 pNext = aObjects[a];
1384 // create node
1385 if(pLast)
1387 createVisibilityOnOffNode(xParentContainer, *pLast, false, false, fDurationHide);
1390 if(pNext)
1392 createVisibilityOnOffNode(xParentContainer, *pNext, true, !a, fDurationShow);
1396 // create end node
1397 if(pNext)
1399 createVisibilityOnOffNode(xParentContainer, *pNext, false, false, fDurationHide);
1402 // add to main sequence and rebuild
1403 pMainSequence->createEffects(xOuterSeqTimeContainer);
1404 pMainSequence->rebuild();
1407 void EffectMigration::DocumentLoaded(SdDrawDocument & rDoc)
1409 if (DocumentType::Draw == rDoc.GetDocumentType())
1410 return; // no animations in Draw
1411 for (sal_uInt16 n = 0; n < rDoc.GetSdPageCount(PageKind::Standard); ++n)
1413 SdPage *const pPage = rDoc.GetSdPage(n, PageKind::Standard);
1414 if (pPage->hasAnimationNode())
1416 // this will force the equivalent of the MainSequence::onTimerHdl
1417 // so that the animations are present in export-able representation
1418 // *before* the import is finished
1419 pPage->getMainSequence()->getRootNode();
1422 for (sal_uInt16 n = 0; n < rDoc.GetMasterSdPageCount(PageKind::Standard); ++n)
1424 SdPage *const pPage = rDoc.GetMasterSdPage(n, PageKind::Standard);
1425 if (pPage->hasAnimationNode())
1427 pPage->getMainSequence()->getRootNode();
1432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */