Use o3tl::convert in Math
[LibreOffice.git] / slideshow / source / engine / animationnodes / basenode.cxx
blobcf732f89701fca7bf59682035dabd81ff23e6742
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 <com/sun/star/animations/XAnimate.hpp>
22 #include <com/sun/star/presentation/ParagraphTarget.hpp>
23 #include <com/sun/star/animations/AnimationFill.hpp>
24 #include <com/sun/star/animations/AnimationRestart.hpp>
25 #include <com/sun/star/presentation/EffectNodeType.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <basenode.hxx>
29 #include <eventmultiplexer.hxx>
30 #include <basecontainernode.hxx>
31 #include <eventqueue.hxx>
32 #include <delayevent.hxx>
33 #include <tools.hxx>
34 #include "nodetools.hxx"
35 #include "generateevent.hxx"
37 #include <sal/log.hxx>
39 #include <vector>
40 #include <algorithm>
42 using namespace ::com::sun::star;
44 namespace slideshow::internal {
46 namespace {
48 typedef int StateTransitionTable[17];
50 // State transition tables
51 // =========================================================================
53 const int* getStateTransitionTable( sal_Int16 nRestartMode,
54 sal_Int16 nFillMode )
56 // TODO(F2): restart issues in below tables
58 // transition table for restart=NEVER, fill=REMOVE
59 static const StateTransitionTable stateTransitionTable_Never_Remove = {
60 AnimationNode::INVALID,
61 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
62 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
63 AnimationNode::INVALID,
64 AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
65 AnimationNode::INVALID,
66 AnimationNode::INVALID,
67 AnimationNode::INVALID,
68 AnimationNode::INVALID, // active successors for FROZEN: this state is unreachable here
69 AnimationNode::INVALID,
70 AnimationNode::INVALID,
71 AnimationNode::INVALID,
72 AnimationNode::INVALID,
73 AnimationNode::INVALID,
74 AnimationNode::INVALID,
75 AnimationNode::INVALID,
76 AnimationNode::ENDED // active successors for ENDED: this state is a sink here (cannot restart)
79 // transition table for restart=WHEN_NOT_ACTIVE, fill=REMOVE
80 static const StateTransitionTable stateTransitionTable_NotActive_Remove = {
81 AnimationNode::INVALID,
82 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
83 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
84 AnimationNode::INVALID,
85 AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
86 AnimationNode::INVALID,
87 AnimationNode::INVALID,
88 AnimationNode::INVALID,
89 AnimationNode::INVALID, // active successors for FROZEN:
90 // this state is unreachable here
91 AnimationNode::INVALID,
92 AnimationNode::INVALID,
93 AnimationNode::INVALID,
94 AnimationNode::INVALID,
95 AnimationNode::INVALID,
96 AnimationNode::INVALID,
97 AnimationNode::INVALID,
98 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
99 // restart possible when ended
102 // transition table for restart=ALWAYS, fill=REMOVE
103 static const StateTransitionTable stateTransitionTable_Always_Remove = {
104 AnimationNode::INVALID,
105 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
106 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
107 AnimationNode::INVALID,
108 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE: restart
109 AnimationNode::INVALID,
110 AnimationNode::INVALID,
111 AnimationNode::INVALID,
112 AnimationNode::INVALID, // active successors for FROZEN:
113 // this state is unreachable here
114 AnimationNode::INVALID,
115 AnimationNode::INVALID,
116 AnimationNode::INVALID,
117 AnimationNode::INVALID,
118 AnimationNode::INVALID,
119 AnimationNode::INVALID,
120 AnimationNode::INVALID,
121 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
124 // transition table for restart=NEVER, fill=FREEZE
125 static const StateTransitionTable stateTransitionTable_Never_Freeze = {
126 AnimationNode::INVALID,
127 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
128 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
129 AnimationNode::INVALID,
130 AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
131 AnimationNode::INVALID,
132 AnimationNode::INVALID,
133 AnimationNode::INVALID,
134 AnimationNode::ENDED, // active successors for FROZEN: end
135 AnimationNode::INVALID,
136 AnimationNode::INVALID,
137 AnimationNode::INVALID,
138 AnimationNode::INVALID,
139 AnimationNode::INVALID,
140 AnimationNode::INVALID,
141 AnimationNode::INVALID,
142 AnimationNode::ENDED, // active successors for ENDED: this state is a sink here (cannot restart)
145 // transition table for restart=WHEN_NOT_ACTIVE, fill=FREEZE
146 static const StateTransitionTable stateTransitionTable_NotActive_Freeze = {
147 AnimationNode::INVALID,
148 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
149 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
150 AnimationNode::INVALID,
151 AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
152 AnimationNode::INVALID,
153 AnimationNode::INVALID,
154 AnimationNode::INVALID,
155 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN:
156 // restart possible when ended
157 AnimationNode::INVALID,
158 AnimationNode::INVALID,
159 AnimationNode::INVALID,
160 AnimationNode::INVALID,
161 AnimationNode::INVALID,
162 AnimationNode::INVALID,
163 AnimationNode::INVALID,
164 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
165 // restart possible when ended
168 // transition table for restart=ALWAYS, fill=FREEZE
169 static const StateTransitionTable stateTransitionTable_Always_Freeze = {
170 AnimationNode::INVALID,
171 AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
172 AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
173 AnimationNode::INVALID,
174 AnimationNode::FROZEN|AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE:
175 // end object, restart
176 AnimationNode::INVALID,
177 AnimationNode::INVALID,
178 AnimationNode::INVALID,
179 AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN: restart possible
180 AnimationNode::INVALID,
181 AnimationNode::INVALID,
182 AnimationNode::INVALID,
183 AnimationNode::INVALID,
184 AnimationNode::INVALID,
185 AnimationNode::INVALID,
186 AnimationNode::INVALID,
187 AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
190 static const StateTransitionTable* tableGuide[] = {
191 &stateTransitionTable_Never_Remove,
192 &stateTransitionTable_NotActive_Remove,
193 &stateTransitionTable_Always_Remove,
194 &stateTransitionTable_Never_Freeze,
195 &stateTransitionTable_NotActive_Freeze,
196 &stateTransitionTable_Always_Freeze
199 int nRestartValue;
200 switch( nRestartMode ) {
201 default:
202 case animations::AnimationRestart::DEFAULT:
203 // same value: animations::AnimationRestart::INHERIT:
204 OSL_FAIL(
205 "getStateTransitionTable(): unexpected case for restart" );
206 [[fallthrough]];
207 case animations::AnimationRestart::NEVER:
208 nRestartValue = 0;
209 break;
210 case animations::AnimationRestart::WHEN_NOT_ACTIVE:
211 nRestartValue = 1;
212 break;
213 case animations::AnimationRestart::ALWAYS:
214 nRestartValue = 2;
215 break;
218 int nFillValue;
219 switch( nFillMode ) {
220 default:
221 case animations::AnimationFill::AUTO:
222 case animations::AnimationFill::DEFAULT:
223 // same value: animations::AnimationFill::INHERIT:
224 OSL_FAIL(
225 "getStateTransitionTable(): unexpected case for fill" );
226 [[fallthrough]];
227 case animations::AnimationFill::REMOVE:
228 nFillValue = 0;
229 break;
230 case animations::AnimationFill::FREEZE:
231 case animations::AnimationFill::HOLD:
232 case animations::AnimationFill::TRANSITION:
233 nFillValue = 1;
234 break;
237 return *tableGuide[ 3*nFillValue + nRestartValue ];
240 /// Little helper predicate, to detect main sequence root node
241 bool isMainSequenceRootNode_(
242 const uno::Reference< animations::XAnimationNode >& xNode )
244 // detect main sequence root node (need that for
245 // end-of-mainsequence signalling below)
246 beans::NamedValue const aSearchKey(
247 "node-type",
248 uno::makeAny( presentation::EffectNodeType::MAIN_SEQUENCE ) );
250 uno::Sequence<beans::NamedValue> const userData(xNode->getUserData());
251 return findNamedValue( userData, aSearchKey );
254 } // anon namespace
256 // BaseNode implementation
257 //=========================================================================
259 /** state transition handling
261 class BaseNode::StateTransition
263 public:
264 enum class Options { NONE, FORCE };
266 explicit StateTransition( BaseNode * pNode )
267 : mpNode(pNode), meToState(INVALID) {}
269 ~StateTransition() {
270 clear();
273 StateTransition(const StateTransition&) = delete;
274 StateTransition& operator=(const StateTransition&) = delete;
276 bool enter( NodeState eToState, Options options = Options::NONE )
278 OSL_ENSURE( meToState == INVALID,
279 "### commit() before enter()ing again!" );
280 if (meToState != INVALID)
281 return false;
282 bool const bForce = options == Options::FORCE;
283 if (!bForce && !mpNode->isTransition( mpNode->meCurrState, eToState ))
284 return false;
285 // recursion detection:
286 if ((mpNode->meCurrentStateTransition & eToState) != 0)
287 return false; // already in wanted transition
288 // mark transition:
289 mpNode->meCurrentStateTransition |= eToState;
290 meToState = eToState;
291 return true; // in transition
294 void commit() {
295 OSL_ENSURE( meToState != INVALID, "### nothing to commit!" );
296 if (meToState != INVALID) {
297 mpNode->meCurrState = meToState;
298 clear();
302 void clear() {
303 if (meToState != INVALID) {
304 OSL_ASSERT( (mpNode->meCurrentStateTransition & meToState) != 0 );
305 mpNode->meCurrentStateTransition &= ~meToState;
306 meToState = INVALID;
310 private:
311 BaseNode *const mpNode;
312 NodeState meToState;
315 BaseNode::BaseNode( const uno::Reference< animations::XAnimationNode >& xNode,
316 const BaseContainerNodeSharedPtr& rParent,
317 const NodeContext& rContext ) :
318 maContext( rContext.maContext ),
319 maDeactivatingListeners(),
320 mxAnimationNode( xNode ),
321 mpParent( rParent ),
322 mpSelf(),
323 mpStateTransitionTable( nullptr ),
324 mnStartDelay( rContext.mnStartDelay ),
325 meCurrState( UNRESOLVED ),
326 meCurrentStateTransition( 0 ),
327 mpCurrentEvent(),
328 mbIsMainSequenceRootNode( isMainSequenceRootNode_( xNode ) )
330 ENSURE_OR_THROW( mxAnimationNode.is(),
331 "BaseNode::BaseNode(): Invalid XAnimationNode" );
333 // setup state transition table
334 mpStateTransitionTable = getStateTransitionTable( getRestartMode(),
335 getFillMode() );
338 void BaseNode::dispose()
340 meCurrState = INVALID;
342 // discharge a loaded event, if any:
343 if (mpCurrentEvent) {
344 mpCurrentEvent->dispose();
345 mpCurrentEvent.reset();
347 maDeactivatingListeners.clear();
348 mxAnimationNode.clear();
349 mpParent.reset();
350 mpSelf.reset();
351 maContext.dispose();
355 sal_Int16 BaseNode::getRestartMode()
357 const sal_Int16 nTmp( mxAnimationNode->getRestart() );
358 return nTmp != animations::AnimationRestart::DEFAULT
359 ? nTmp : getRestartDefaultMode();
362 sal_Int16 BaseNode::getFillMode()
364 const sal_Int16 nTmp( mxAnimationNode->getFill() );
365 const sal_Int16 nFill(nTmp != animations::AnimationFill::DEFAULT
366 ? nTmp : getFillDefaultMode());
368 // For AUTO fill mode, SMIL specifies that fill mode is FREEZE,
369 // if no explicit active duration is given
370 // (no duration, end, repeatCount or repeatDuration given),
371 // and REMOVE otherwise
372 if( nFill == animations::AnimationFill::AUTO ) {
373 return (isIndefiniteTiming( mxAnimationNode->getDuration() ) &&
374 isIndefiniteTiming( mxAnimationNode->getEnd() ) &&
375 !mxAnimationNode->getRepeatCount().hasValue() &&
376 isIndefiniteTiming( mxAnimationNode->getRepeatDuration() ))
377 ? animations::AnimationFill::FREEZE
378 : animations::AnimationFill::REMOVE;
380 else {
381 return nFill;
385 sal_Int16 BaseNode::getFillDefaultMode() const
387 sal_Int16 nFillDefault = mxAnimationNode->getFillDefault();
388 if (nFillDefault == animations::AnimationFill::DEFAULT) {
389 nFillDefault = (mpParent != nullptr
390 ? mpParent->getFillDefaultMode()
391 : animations::AnimationFill::AUTO);
393 return nFillDefault;
396 sal_Int16 BaseNode::getRestartDefaultMode() const
398 sal_Int16 nRestartDefaultMode = mxAnimationNode->getRestartDefault();
399 if (nRestartDefaultMode == animations::AnimationRestart::DEFAULT) {
400 nRestartDefaultMode = (mpParent != nullptr
401 ? mpParent->getRestartDefaultMode()
402 : animations::AnimationRestart::ALWAYS);
404 return nRestartDefaultMode;
407 uno::Reference<animations::XAnimationNode> BaseNode::getXAnimationNode() const
409 return mxAnimationNode;
412 bool BaseNode::init()
414 if (! checkValidNode())
415 return false;
416 meCurrState = UNRESOLVED;
417 // discharge a loaded event, if any:
418 if (mpCurrentEvent) {
419 mpCurrentEvent->dispose();
420 mpCurrentEvent.reset();
422 return init_st(); // may call derived class
425 bool BaseNode::init_st()
427 return true;
430 bool BaseNode::resolve()
432 if (! checkValidNode())
433 return false;
435 OSL_ASSERT( meCurrState != RESOLVED );
436 if (inStateOrTransition( RESOLVED ))
437 return true;
439 StateTransition st(this);
440 if (st.enter( RESOLVED ) &&
441 isTransition( RESOLVED, ACTIVE ) &&
442 resolve_st() /* may call derived class */)
444 st.commit(); // changing state
446 // discharge a loaded event, if any:
447 if (mpCurrentEvent)
448 mpCurrentEvent->dispose();
450 // schedule activation event:
452 // This method takes the NodeContext::mnStartDelay value into account,
453 // to cater for iterate container time shifts. We cannot put different
454 // iterations of the iterate container's children into different
455 // subcontainer (such as a 'DelayContainer', which delays resolving its
456 // children by a fixed amount), since all iterations' nodes must be
457 // resolved at the same time (otherwise, the delayed subset creation
458 // will not work, i.e. deactivate the subsets too late in the master
459 // shape).
460 uno::Any const aBegin( mxAnimationNode->getBegin() );
461 if (aBegin.hasValue()) {
462 auto self(mpSelf);
463 mpCurrentEvent = generateEvent(
464 aBegin, [self] () { self->activate(); },
465 maContext, mnStartDelay );
467 else {
468 // For some leaf nodes, PPT import yields empty begin time,
469 // although semantically, it should be 0.0
470 // TODO(F3): That should really be provided by the PPT import
472 // schedule delayed activation event. Take iterate node
473 // timeout into account
474 auto self(mpSelf);
475 mpCurrentEvent = makeDelay(
476 [self] () { self->activate(); },
477 mnStartDelay,
478 "AnimationNode::activate with delay");
479 maContext.mrEventQueue.addEvent( mpCurrentEvent );
482 return true;
484 return false;
487 bool BaseNode::resolve_st()
489 return true;
493 void BaseNode::activate()
495 if (! checkValidNode())
496 return;
498 OSL_ASSERT( meCurrState != ACTIVE );
499 if (inStateOrTransition( ACTIVE ))
500 return;
502 StateTransition st(this);
503 if (st.enter( ACTIVE )) {
505 activate_st(); // calling derived class
507 st.commit(); // changing state
509 maContext.mrEventMultiplexer.notifyAnimationStart( mpSelf );
513 void BaseNode::activate_st()
515 scheduleDeactivationEvent();
518 void BaseNode::scheduleDeactivationEvent( EventSharedPtr const& pEvent )
520 if (mpCurrentEvent) {
521 mpCurrentEvent->dispose();
522 mpCurrentEvent.reset();
524 if (pEvent) {
525 if (maContext.mrEventQueue.addEvent( pEvent ))
526 mpCurrentEvent = pEvent;
528 else {
529 // This method need not take the
530 // NodeContext::mnStartDelay value into account,
531 // because the deactivation event is only scheduled
532 // when the effect is started: the timeout is then
533 // already respected.
535 // xxx todo:
536 // think about set node, anim base node!
537 // if anim base node has no activity, this is called to schedule deactivation,
538 // but what if it does not schedule anything?
540 auto self(mpSelf);
541 if (mxAnimationNode->getEnd().hasValue())
543 // TODO: We may need to calculate the duration if the end value is numeric.
544 // We expect that the end value contains EventTrigger::ON_NEXT here.
545 // LibreOffice does not generate numeric values, so we can leave it
546 // until we find a test case.
547 mpCurrentEvent = generateEvent(
548 mxAnimationNode->getEnd(),
549 [self] () { self->deactivate(); },
550 maContext, 0.0 );
553 else
555 mpCurrentEvent = generateEvent(
556 mxAnimationNode->getDuration(),
557 [self] () { self->deactivate(); },
558 maContext, 0.0 );
563 void BaseNode::deactivate()
565 if (inStateOrTransition( ENDED | FROZEN ) || !checkValidNode())
566 return;
568 if (isTransition( meCurrState, FROZEN, false /* no OSL_ASSERT */ )) {
569 // do transition to FROZEN:
570 StateTransition st(this);
571 if (st.enter( FROZEN, StateTransition::Options::FORCE )) {
573 deactivate_st( FROZEN );
574 st.commit();
576 notifyEndListeners();
578 // discharge a loaded event, before going on:
579 if (mpCurrentEvent) {
580 mpCurrentEvent->dispose();
581 mpCurrentEvent.reset();
585 else {
586 // use end instead:
587 end();
589 // state has changed either to FROZEN or ENDED
592 void BaseNode::deactivate_st( NodeState )
596 void BaseNode::end()
598 bool const bIsFrozenOrInTransitionToFrozen = inStateOrTransition( FROZEN );
599 if (inStateOrTransition( ENDED ) || !checkValidNode())
600 return;
602 // END must always be reachable. If not, that's an error in the
603 // transition tables
604 OSL_ENSURE( isTransition( meCurrState, ENDED ),
605 "end state not reachable in transition table" );
607 StateTransition st(this);
608 if (!st.enter( ENDED, StateTransition::Options::FORCE ))
609 return;
611 deactivate_st( ENDED );
612 st.commit(); // changing state
614 // if is FROZEN or is to be FROZEN, then
615 // will/already notified deactivating listeners
616 if (!bIsFrozenOrInTransitionToFrozen)
617 notifyEndListeners();
619 // discharge a loaded event, before going on:
620 if (mpCurrentEvent) {
621 mpCurrentEvent->dispose();
622 mpCurrentEvent.reset();
626 void BaseNode::notifyDeactivating( const AnimationNodeSharedPtr& rNotifier )
628 OSL_ASSERT( rNotifier->getState() == FROZEN ||
629 rNotifier->getState() == ENDED );
630 // TODO(F1): for end sync functionality, this might indeed be used some day
633 void BaseNode::notifyEndListeners() const
635 // notify all listeners
636 for( const auto& rListener : maDeactivatingListeners )
637 rListener->notifyDeactivating( mpSelf );
639 // notify state change
640 maContext.mrEventMultiplexer.notifyAnimationEnd( mpSelf );
642 // notify main sequence end (iff we're the main
643 // sequence root node). This is because the main
644 // sequence determines the active duration of the
645 // slide. All other sequences are secondary, in that
646 // they don't prevent a slide change from happening,
647 // even if they have not been completed. In other
648 // words, all sequences except the main sequence are
649 // optional for the slide lifetime.
650 if (isMainSequenceRootNode())
651 maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
654 AnimationNode::NodeState BaseNode::getState() const
656 return meCurrState;
659 bool BaseNode::registerDeactivatingListener(
660 const AnimationNodeSharedPtr& rNotifee )
662 if (! checkValidNode())
663 return false;
665 ENSURE_OR_RETURN_FALSE(
666 rNotifee,
667 "BaseNode::registerDeactivatingListener(): invalid notifee" );
668 maDeactivatingListeners.push_back( rNotifee );
670 return true;
673 void BaseNode::setSelf( const BaseNodeSharedPtr& rSelf )
675 ENSURE_OR_THROW( rSelf.get() == this,
676 "BaseNode::setSelf(): got ptr to different object" );
677 ENSURE_OR_THROW( !mpSelf,
678 "BaseNode::setSelf(): called multiple times" );
680 mpSelf = rSelf;
683 // Debug
686 #if defined(DBG_UTIL)
687 void BaseNode::showState() const
689 const AnimationNode::NodeState eNodeState( getState() );
691 if( eNodeState == AnimationNode::INVALID )
692 SAL_INFO("slideshow.verbose", "Node state: n" <<
693 debugGetNodeName(this) <<
694 " [label=\"" <<
695 getDescription() <<
696 "\",style=filled, fillcolor=\"0.5,0.2,0.5\"]");
697 else
698 SAL_INFO("slideshow.verbose", "Node state: n" <<
699 debugGetNodeName(this) <<
700 " [label=\"" <<
701 getDescription() <<
702 "fillcolor=\"" <<
703 log(double(getState()))/4.0 <<
704 ",1.0,1.0\"]");
706 // determine additional node information
707 uno::Reference<animations::XAnimate> const xAnimate( mxAnimationNode,
708 uno::UNO_QUERY );
709 if( !xAnimate.is() )
710 return;
712 uno::Reference< drawing::XShape > xTargetShape( xAnimate->getTarget(),
713 uno::UNO_QUERY );
715 if( !xTargetShape.is() )
717 css::presentation::ParagraphTarget aTarget;
719 // no shape provided. Maybe a ParagraphTarget?
720 if( xAnimate->getTarget() >>= aTarget )
721 xTargetShape = aTarget.Shape;
724 if( !xTargetShape.is() )
725 return;
727 uno::Reference< beans::XPropertySet > xPropSet( xTargetShape,
728 uno::UNO_QUERY );
730 // read shape name
731 OUString aName;
732 if( xPropSet->getPropertyValue("Name") >>= aName )
734 SAL_INFO("slideshow.verbose", "Node info: n" <<
735 debugGetNodeName(this) <<
736 ", name \"" <<
737 aName <<
738 "\"");
742 const char* BaseNode::getDescription() const
744 return "BaseNode";
747 #endif
749 } // namespace slideshow
751 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */