tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / slideshow / source / engine / shapes / drawinglayeranimation.cxx
blob6713f3ab95c924725616da1afcdbb29ed1acae9a
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 .
21 #include <comphelper/diagnose_ex.hxx>
22 #include <tools/gen.hxx>
23 #include <tools/helpers.hxx>
24 #include <canvas/elapsedtime.hxx>
25 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <utility>
28 #include <vcl/canvastools.hxx>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/TextAnimationKind.hpp>
31 #include <com/sun/star/drawing/TextAnimationDirection.hpp>
33 #include <activity.hxx>
34 #include <wakeupevent.hxx>
35 #include <eventqueue.hxx>
36 #include "drawinglayeranimation.hxx"
37 #include "drawshapesubsetting.hxx"
38 #include "drawshape.hxx"
39 #include <shapeattributelayerholder.hxx>
40 #include <slideshowcontext.hxx>
41 #include <subsettableshapemanager.hxx>
42 #include <tools.hxx>
43 #include "gdimtftools.hxx"
44 #include <intrinsicanimationeventhandler.hxx>
46 #include <vector>
47 #include <memory>
49 using namespace com::sun::star;
50 using namespace ::slideshow::internal;
52 namespace {
54 class ScrollTextAnimNode
56 sal_uInt32 mnDuration; // single duration
57 sal_uInt32 mnRepeat; // 0 -> endless
58 double mfStart;
59 double mfStop;
60 sal_uInt32 mnFrequency; // in ms
61 // forth and back change at mnRepeat%2:
62 bool mbAlternate;
64 public:
65 ScrollTextAnimNode(
66 sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop,
67 sal_uInt32 nFrequency, bool bAlternate)
68 : mnDuration(nDuration),
69 mnRepeat(nRepeat),
70 mfStart(fStart),
71 mfStop(fStop),
72 mnFrequency(nFrequency),
73 mbAlternate(bAlternate)
76 sal_uInt32 GetRepeat() const { return mnRepeat; }
77 sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; }
78 double GetStop() const { return mfStop; }
79 sal_uInt32 GetFrequency() const { return mnFrequency; }
80 bool DoAlternate() const { return mbAlternate; }
82 double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const;
85 double ScrollTextAnimNode::GetStateAtRelativeTime(
86 sal_uInt32 nRelativeTime) const
88 // Avoid division by zero.
89 if( mnDuration == 0 )
90 return mfStop;
92 if(mnRepeat)
94 // ending
95 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
96 sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration));
98 if(DoAlternate() && (nRepeatCount + 1) % 2L)
99 nFrameTime = mnDuration - nFrameTime;
101 return mfStart + ((mfStop - mfStart) *
102 (double(nFrameTime) / mnDuration));
104 else
106 // endless
107 sal_uInt32 nFrameTime(nRelativeTime % mnDuration);
109 if(DoAlternate())
111 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
113 if((nRepeatCount + 1) % 2L)
114 nFrameTime = mnDuration - nFrameTime;
117 return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration));
121 class ActivityImpl : public Activity
123 public:
124 ActivityImpl(
125 SlideShowContext const& rContext,
126 std::shared_ptr<WakeupEvent> pWakeupEvent,
127 std::shared_ptr<DrawShape> const& pDrawShape );
129 ActivityImpl(const ActivityImpl&) = delete;
130 ActivityImpl& operator=(const ActivityImpl&) = delete;
132 bool enableAnimations();
134 // Disposable:
135 virtual void dispose() override;
136 // Activity:
137 virtual double calcTimeLag() const override;
138 virtual bool perform() override;
139 virtual bool isActive() const override;
140 virtual void dequeued() override;
141 virtual void end() override;
143 private:
144 void updateShapeAttributes( double fTime,
145 basegfx::B2DRectangle const& parentBounds );
147 // scroll horizontal? if sal_False, scroll is vertical.
148 bool ScrollHorizontal() const {
149 return (drawing::TextAnimationDirection_LEFT == meDirection ||
150 drawing::TextAnimationDirection_RIGHT == meDirection);
153 // Access to StepWidth in logical units
154 sal_uInt32 GetStepWidthLogic() const;
156 // is the animation direction opposite?
157 bool DoScrollForward() const {
158 return (drawing::TextAnimationDirection_RIGHT == meDirection ||
159 drawing::TextAnimationDirection_DOWN == meDirection);
162 // do alternate text directions?
163 bool DoAlternate() const { return mbAlternate; }
165 // do scroll in?
166 bool DoScrollIn() const { return mbScrollIn; }
168 // Scroll helper methods
169 void ImpForceScrollTextAnimNodes();
170 ScrollTextAnimNode* ImpGetScrollTextAnimNode(
171 sal_uInt32 nTime, sal_uInt32& rRelativeTime );
172 sal_uInt32 ImpRegisterAgainScrollTextMixerState(
173 sal_uInt32 nTime);
175 // calculate the MixerState value for given time
176 double GetMixerState(sal_uInt32 nTime);
179 SlideShowContext maContext;
180 std::shared_ptr<WakeupEvent> mpWakeupEvent;
181 std::weak_ptr<DrawShape> mpParentDrawShape;
182 DrawShapeSharedPtr mpDrawShape;
183 ShapeAttributeLayerHolder maShapeAttrLayer;
184 GDIMetaFileSharedPtr mpMetaFile;
185 IntrinsicAnimationEventHandlerSharedPtr mpListener;
186 canvas::tools::ElapsedTime maTimer;
187 double mfRotationAngle;
188 bool mbIsShapeAnimated;
189 bool mbIsDisposed;
190 bool mbIsActive;
191 drawing::TextAnimationKind meAnimKind;
193 // The blink frequency in ms
194 sal_uInt32 mnFrequency;
196 // The repeat count, init to 0L which means endless
197 sal_uInt32 mnRepeat;
199 // Flag to decide if text will be shown when animation has ended
200 bool mbVisibleWhenStopped;
201 bool mbVisibleWhenStarted;
203 // Flag decides if TextScroll alternates. Default is sal_False.
204 bool mbAlternate;
206 // Flag to remember if this is a simple scrolling text
207 bool mbScrollIn;
209 // The AnimationDirection
210 drawing::TextAnimationDirection meDirection;
212 // Get width per Step. Negative means pixel, positive logical units
213 sal_Int32 mnStepWidth;
215 // The single anim steps
216 std::vector< ScrollTextAnimNode > maVector;
218 // the scroll rectangle
219 tools::Rectangle maScrollRectangleLogic;
221 // the paint rectangle
222 tools::Rectangle maPaintRectangleLogic;
226 class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler
228 public:
229 explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) :
230 mrActivity( rActivity )
233 IntrinsicAnimationListener(const IntrinsicAnimationListener&) = delete;
234 IntrinsicAnimationListener& operator=(const IntrinsicAnimationListener&) = delete;
236 private:
238 virtual bool enableAnimations() override { return mrActivity.enableAnimations(); }
239 virtual bool disableAnimations() override { mrActivity.end(); return true; }
241 ActivityImpl& mrActivity;
245 double ActivityImpl::GetMixerState( sal_uInt32 nTime )
247 if( meAnimKind == drawing::TextAnimationKind_BLINK )
249 // from AInfoBlinkText:
250 double fRetval(0.0);
251 bool bDone(false);
252 const sal_uInt32 nLoopTime(2 * mnFrequency);
254 if(mnRepeat)
256 const sal_uInt32 nEndTime(mnRepeat * nLoopTime);
258 if(nTime >= nEndTime)
260 if(mbVisibleWhenStopped)
261 fRetval = 0.0;
262 else
263 fRetval = 1.0;
265 bDone = true;
269 if(!bDone)
271 sal_uInt32 nTimeInLoop(nTime % nLoopTime);
272 fRetval = double(nTimeInLoop) / nLoopTime;
275 return fRetval;
277 else
279 // from AInfoScrollText:
280 double fRetval(0.0);
281 ImpForceScrollTextAnimNodes();
283 if(!maVector.empty())
285 sal_uInt32 nRelativeTime;
286 ScrollTextAnimNode* pNode =
287 ImpGetScrollTextAnimNode(nTime, nRelativeTime);
289 if(pNode)
291 // use node
292 fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
294 else
296 // end of animation, take last entry's end
297 fRetval = maVector[maVector.size() - 1].GetStop();
301 return fRetval;
305 // Access to StepWidth in logical units
306 sal_uInt32 ActivityImpl::GetStepWidthLogic() const
308 // #i69847# Assuming higher DPI
309 constexpr sal_uInt32 PIXEL_TO_LOGIC = 30;
311 sal_uInt32 nRetval(0);
313 if(mnStepWidth < 0)
315 // is in pixels, convert to logical units
316 nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
318 else if(mnStepWidth > 0)
320 // is in logical units
321 nRetval = mnStepWidth;
324 if(0 == nRetval)
326 // step 1 pixel, canned value
328 // with very high DPIs like in PDF export, this can
329 // still get zero. for that cases, set a default, too (taken
330 // from ainfoscrolltext.cxx)
331 nRetval = 100;
334 return nRetval;
337 void ActivityImpl::ImpForceScrollTextAnimNodes()
339 if(!maVector.empty())
340 return;
342 // prepare values
343 sal_uInt32 nLoopTime;
344 double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic;
345 double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0;
346 double fZeroRelative, fOneRelative, fInitRelative;
348 if(ScrollHorizontal())
350 if(DoAlternate())
352 if(maPaintRectangleLogic.GetWidth() >
353 maScrollRectangleLogic.GetWidth())
355 fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
356 fOneLogicAlternate = maScrollRectangleLogic.Left();
358 else
360 fZeroLogicAlternate = maScrollRectangleLogic.Left();
361 fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
365 fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth();
366 fOneLogic = maScrollRectangleLogic.Right();
367 fInitLogic = maPaintRectangleLogic.Left();
369 else
371 if(DoAlternate())
373 if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight())
375 fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
376 fOneLogicAlternate = maScrollRectangleLogic.Top();
378 else
380 fZeroLogicAlternate = maScrollRectangleLogic.Top();
381 fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
385 fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight();
386 fOneLogic = maScrollRectangleLogic.Bottom();
387 fInitLogic = maPaintRectangleLogic.Top();
390 fDistanceLogic = fOneLogic - fZeroLogic;
391 fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic;
393 if(DoAlternate())
395 fZeroRelative =
396 (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic;
397 fOneRelative =
398 (fOneLogicAlternate - fZeroLogic) / fDistanceLogic;
400 else
402 fZeroRelative = 0.0;
403 fOneRelative = 1.0;
406 if(mbVisibleWhenStarted)
408 double fRelativeStartValue, fRelativeEndValue,fRelativeDistance;
410 if(DoScrollForward())
412 fRelativeStartValue = fInitRelative;
413 fRelativeEndValue = fOneRelative;
414 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
416 else
418 fRelativeStartValue = fInitRelative;
419 fRelativeEndValue = fZeroRelative;
420 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
423 const double fNumberSteps =
424 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
425 nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
427 // init loop
428 ScrollTextAnimNode aInitNode(
429 nLoopTime, 1,
430 fRelativeStartValue, fRelativeEndValue,
431 mnFrequency, false);
432 maVector.push_back(aInitNode);
435 // prepare main loop values
437 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
439 if(DoScrollForward())
441 fRelativeStartValue = fZeroRelative;
442 fRelativeEndValue = fOneRelative;
443 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
445 else
447 fRelativeStartValue = fOneRelative;
448 fRelativeEndValue = fZeroRelative;
449 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
452 const double fNumberSteps =
453 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
454 nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
456 if(0 == mnRepeat)
458 if(!DoScrollIn())
460 // endless main loop
461 ScrollTextAnimNode aMainNode(
462 nLoopTime, 0,
463 fRelativeStartValue, fRelativeEndValue,
464 mnFrequency, DoAlternate());
465 maVector.push_back(aMainNode);
468 else
470 sal_uInt32 nNumRepeat(mnRepeat);
472 if(DoAlternate() && (nNumRepeat + 1) % 2L)
473 nNumRepeat += 1;
475 // ending main loop
476 ScrollTextAnimNode aMainNode(
477 nLoopTime, nNumRepeat,
478 fRelativeStartValue, fRelativeEndValue,
479 mnFrequency, DoAlternate());
480 maVector.push_back(aMainNode);
484 if(!mbVisibleWhenStopped)
485 return;
487 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
489 if(DoScrollForward())
491 fRelativeStartValue = fZeroRelative;
492 fRelativeEndValue = fInitRelative;
493 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
495 else
497 fRelativeStartValue = fOneRelative;
498 fRelativeEndValue = fInitRelative;
499 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
502 const double fNumberSteps =
503 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
504 nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
506 // exit loop
507 ScrollTextAnimNode aExitNode(
508 nLoopTime, 1,
509 fRelativeStartValue, fRelativeEndValue, mnFrequency, false);
510 maVector.push_back(aExitNode);
513 ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode(
514 sal_uInt32 nTime, sal_uInt32& rRelativeTime )
516 ScrollTextAnimNode* pRetval = nullptr;
517 ImpForceScrollTextAnimNodes();
519 if(!maVector.empty())
521 rRelativeTime = nTime;
523 for(ScrollTextAnimNode & rNode: maVector)
525 if(!rNode.GetRepeat())
527 // endless loop, use it
528 pRetval = &rNode;
530 else if(rNode.GetFullTime() > rRelativeTime)
532 // ending node
533 pRetval = &rNode;
535 else
537 // look at next
538 rRelativeTime -= rNode.GetFullTime();
543 return pRetval;
546 sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)
548 sal_uInt32 nRetval(0);
549 ImpForceScrollTextAnimNodes();
551 if(!maVector.empty())
553 sal_uInt32 nRelativeTime;
554 ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime);
556 if(pNode)
558 // take register time
559 nRetval = pNode->GetFrequency();
562 else
564 // #i38135# not initialized, return default
565 nRetval = mnFrequency;
568 return nRetval;
571 void ActivityImpl::updateShapeAttributes(
572 double fTime, basegfx::B2DRectangle const& parentBounds )
574 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
575 if( meAnimKind == drawing::TextAnimationKind_NONE )
576 return;
578 double const fMixerState = GetMixerState(
579 static_cast<sal_uInt32>(fTime * 1000.0) );
581 if( meAnimKind == drawing::TextAnimationKind_BLINK )
583 // show/hide text:
584 maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 );
586 else if(mpMetaFile) // scroll mode:
589 // keep care: the below code is highly sensible to changes...
592 // rectangle of the pure text:
593 double const fPaintWidth = maPaintRectangleLogic.GetWidth();
594 double const fPaintHeight = maPaintRectangleLogic.GetHeight();
595 // rectangle where the scrolling takes place (-> clipping):
596 double const fScrollWidth = maScrollRectangleLogic.GetWidth();
597 double const fScrollHeight = maScrollRectangleLogic.GetHeight();
599 basegfx::B2DPoint pos, clipPos;
601 if(ScrollHorizontal())
603 double const fOneEquiv( fScrollWidth );
604 double const fZeroEquiv( -fPaintWidth );
606 pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
608 clipPos.setX( -pos.getX() );
609 clipPos.setY( -pos.getY() );
611 // #i69844# Compensation for text-wider-than-shape case
612 if( fPaintWidth > fScrollWidth )
613 pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 );
615 else
617 // scroll vertical:
618 double const fOneEquiv( fScrollHeight );
619 double const fZeroEquiv( -fPaintHeight );
621 pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
623 clipPos.setX( -pos.getX() );
624 clipPos.setY( -pos.getY() );
626 // #i69844# Compensation for text-higher-than-shape case
627 if( fPaintHeight > fScrollHeight )
628 pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
631 basegfx::B2DPolygon clipPoly(
632 basegfx::utils::createPolygonFromRect(
633 basegfx::B2DRectangle( clipPos.getX(),
634 clipPos.getY(),
635 clipPos.getX() + fScrollWidth,
636 clipPos.getY() + fScrollHeight ) ) );
638 if( !::basegfx::fTools::equalZero( mfRotationAngle ))
640 maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
641 double const fRotate = basegfx::deg2rad(mfRotationAngle);
642 basegfx::B2DHomMatrix aTransform;
643 // position:
644 aTransform.rotate( fRotate );
645 pos *= aTransform;
648 pos += parentBounds.getCenter();
649 maShapeAttrLayer.get()->setPosition( pos );
650 maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) );
654 bool ActivityImpl::perform()
656 if( !isActive() )
657 return false;
659 ENSURE_OR_RETURN_FALSE(
660 mpDrawShape,
661 "ActivityImpl::perform(): still active, but NULL draw shape" );
663 DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape );
664 if( !pParentDrawShape )
665 return false; // parent has vanished
667 if( pParentDrawShape->isVisible() )
669 if( !mbIsShapeAnimated )
671 mpDrawShape->setVisibility(true); // shape may be initially hidden
672 maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape );
673 maTimer.reset();
674 mbIsShapeAnimated = true;
676 // update attributes related to current time:
677 basegfx::B2DRectangle const parentBounds(
678 pParentDrawShape->getBounds() );
680 const double nCurrTime( maTimer.getElapsedTime() );
681 updateShapeAttributes( nCurrTime, parentBounds );
683 const sal_uInt32 nFrequency(
684 ImpRegisterAgainScrollTextMixerState(
685 static_cast<sal_uInt32>(nCurrTime * 1000.0)) );
687 if(nFrequency)
689 mpWakeupEvent->start();
690 mpWakeupEvent->setNextTimeout(
691 std::max(0.1,nFrequency/1000.0) );
692 maContext.mrEventQueue.addEvent( mpWakeupEvent );
694 if( mpDrawShape->isContentChanged() )
695 maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape );
697 // else: finished, not need to wake up again.
699 else
701 // busy-wait, until parent shape gets visible
702 mpWakeupEvent->start();
703 mpWakeupEvent->setNextTimeout( 2.0 );
706 // don't reinsert, WakeupEvent will perform that after the given timeout:
707 return false;
710 ActivityImpl::ActivityImpl(
711 SlideShowContext const& rContext,
712 std::shared_ptr<WakeupEvent> pWakeupEvent,
713 std::shared_ptr<DrawShape> const& pParentDrawShape )
714 : maContext(rContext),
715 mpWakeupEvent(std::move(pWakeupEvent)),
716 mpParentDrawShape(pParentDrawShape),
717 mpListener( std::make_shared<IntrinsicAnimationListener>(*this) ),
718 maTimer(rContext.mrEventQueue.getTimer()),
719 mfRotationAngle(0.0),
720 mbIsShapeAnimated(false),
721 mbIsDisposed(false),
722 mbIsActive(true),
723 meAnimKind(drawing::TextAnimationKind_NONE),
724 mbVisibleWhenStopped(false),
725 mbVisibleWhenStarted(false),
726 mnStepWidth(0)
728 // get doctreenode:
729 sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes(
730 DocTreeNode::NodeType::LogicalParagraph );
732 DocTreeNode scrollTextNode(
733 pParentDrawShape->getTreeNode(
734 0, DocTreeNode::NodeType::LogicalParagraph ));
735 // xxx todo: remove this hack
736 if( nNodes > 1 )
737 scrollTextNode.setEndIndex(
738 pParentDrawShape->getTreeNode(
739 nNodes - 1,
740 DocTreeNode::NodeType::LogicalParagraph ).getEndIndex());
742 // TODO(Q3): Doing this manually, instead of using
743 // ShapeSubset. This is because of lifetime issues (ShapeSubset
744 // generates circular references to parent shape)
745 mpDrawShape = std::dynamic_pointer_cast<DrawShape>(
746 maContext.mpSubsettableShapeManager->getSubsetShape(
747 pParentDrawShape,
748 scrollTextNode ));
750 mpMetaFile = mpDrawShape->forceScrollTextMetaFile();
752 // make scroll text invisible for slide transition bitmaps
753 mpDrawShape->setVisibility(false);
755 basegfx::B2DRectangle aScrollRect, aPaintRect;
756 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
757 aPaintRect,
758 mpMetaFile ),
759 "ActivityImpl::ActivityImpl(): Could not extract "
760 "scroll anim rectangles from mtf" );
762 maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
763 aScrollRect );
764 maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
765 aPaintRect );
767 maShapeAttrLayer.createAttributeLayer(mpDrawShape);
769 uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() );
770 uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW );
772 getPropertyValue( meAnimKind, xProps, u"TextAnimationKind"_ustr );
773 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
774 mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
775 mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
777 // adopted from in AInfoBlinkText::ImplInit():
778 sal_Int16 nRepeat(0);
779 getPropertyValue( nRepeat, xProps, u"TextAnimationCount"_ustr );
780 mnRepeat = nRepeat;
782 if(mbAlternate)
784 // force visible when started for scroll-forth-and-back, because
785 // slide has been coming in with visible text in the middle:
786 mbVisibleWhenStarted = true;
788 else
790 getPropertyValue( mbVisibleWhenStarted, xProps,
791 u"TextAnimationStartInside"_ustr );
794 // set visible when stopped
795 getPropertyValue( mbVisibleWhenStopped, xProps,
796 u"TextAnimatiogonStopInside"_ustr );
797 // rotation:
798 getPropertyValue( mfRotationAngle, xProps,
799 u"RotateAngle"_ustr );
800 mfRotationAngle /= -100.0; // (switching direction)
802 // set frequency
803 sal_Int16 nDelay(0);
804 getPropertyValue( nDelay, xProps, u"TextAnimationDelay"_ustr );
805 // set delay if not automatic
806 mnFrequency = (nDelay ? nDelay :
807 // default:
808 meAnimKind == drawing::TextAnimationKind_BLINK
809 ? 250 : 50 );
811 // adopted from in AInfoScrollText::ImplInit():
813 // If it is a simple m_bScrollIn, reset some parameters
814 if( DoScrollIn() )
816 // most parameters are set correctly from the dialog logic, but
817 // eg VisibleWhenStopped is grayed out and needs to be corrected here.
818 mbVisibleWhenStopped = true;
819 mbVisibleWhenStarted = false;
820 mnRepeat = 0;
823 // Get animation direction
824 getPropertyValue( meDirection, xProps, u"TextAnimationDirection"_ustr );
826 // Get step width. Negative means pixel, positive logical units
827 getPropertyValue( mnStepWidth, xProps, u"TextAnimationAmount"_ustr );
829 maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
830 mpListener );
833 bool ActivityImpl::enableAnimations()
835 mbIsActive = true;
836 return maContext.mrActivitiesQueue.addActivity( std::dynamic_pointer_cast<Activity>(shared_from_this()) );
839 void ActivityImpl::dispose()
841 if( mbIsDisposed )
842 return;
844 end();
846 // only remove subset here, since end() is called on slide end
847 // (and we must not spoil the slide preview bitmap with scroll
848 // text)
849 maShapeAttrLayer.reset();
850 if( mpDrawShape )
852 // TODO(Q3): Doing this manually, instead of using
853 // ShapeSubset. This is because of lifetime issues
854 // (ShapeSubset generates circular references to parent
855 // shape)
856 DrawShapeSharedPtr pParent( mpParentDrawShape.lock() );
857 if( pParent )
858 maContext.mpSubsettableShapeManager->revokeSubset(
859 pParent,
860 mpDrawShape );
863 mpMetaFile.reset();
864 mpDrawShape.reset();
865 mpParentDrawShape.reset();
866 mpWakeupEvent.reset();
867 maContext.dispose();
868 mbIsDisposed = true;
870 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
871 mpListener );
874 double ActivityImpl::calcTimeLag() const
876 return 0.0;
879 bool ActivityImpl::isActive() const
881 return mbIsActive;
884 void ActivityImpl::dequeued()
886 // not used here
889 void ActivityImpl::end()
891 // not used here
892 mbIsActive = false;
894 if( mbIsShapeAnimated )
896 maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape );
897 mbIsShapeAnimated = false;
901 } // anon namespace
903 namespace slideshow::internal {
905 std::shared_ptr<Activity> createDrawingLayerAnimActivity(
906 SlideShowContext const& rContext,
907 std::shared_ptr<DrawShape> const& pDrawShape )
909 std::shared_ptr<Activity> pActivity;
913 auto const pWakeupEvent = std::make_shared<WakeupEvent>( rContext.mrEventQueue.getTimer(),
914 rContext.mrActivitiesQueue );
915 pActivity = std::make_shared<ActivityImpl>( rContext, pWakeupEvent, pDrawShape );
916 pWakeupEvent->setActivity( pActivity );
918 catch( uno::RuntimeException& )
920 throw;
922 catch( uno::Exception& )
924 // translate any error into empty factory product.
925 TOOLS_WARN_EXCEPTION( "slideshow", "" );
928 return pActivity;
931 } // namespace presentation
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */