merge the formfield patch from ooo-build
[ooovba.git] / animations / source / animcore / targetpropertiescreator.cxx
blobd29b1ae2c022a4d5c27b22b49831c9bbbcc8a9ce
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: targetpropertiescreator.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <com/sun/star/uno/XComponentContext.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/lang/XTypeProvider.hpp>
34 #include <com/sun/star/animations/XTargetPropertiesCreator.hpp>
35 #include <com/sun/star/animations/XIterateContainer.hpp>
36 #include <com/sun/star/animations/TargetProperties.hpp>
37 #include <com/sun/star/presentation/ParagraphTarget.hpp>
38 #include <com/sun/star/registry/XRegistryKey.hpp>
39 #include <com/sun/star/lang/XInitialization.hpp>
40 #include <com/sun/star/lang/XServiceName.hpp>
41 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <com/sun/star/drawing/XShape.hpp>
43 #include <com/sun/star/animations/AnimationNodeType.hpp>
44 #include <com/sun/star/animations/XAnimate.hpp>
45 #include <cppuhelper/compbase3.hxx>
46 #include <cppuhelper/factory.hxx>
47 #include <cppuhelper/implementationentry.hxx>
48 #include <comphelper/optionalvalue.hxx>
49 #include <comphelper/broadcasthelper.hxx>
50 #include <comphelper/sequence.hxx>
52 #include <animations/animationnodehelper.hxx>
54 #include <vector>
55 #include <hash_map>
58 using namespace ::com::sun::star;
60 #define IMPLEMENTATION_NAME "animcore::TargetPropertiesCreator"
61 #define SERVICE_NAME "com.sun.star.animations.TargetPropertiesCreator"
63 namespace animcore
65 typedef ::cppu::WeakComponentImplHelper3< ::com::sun::star::animations::XTargetPropertiesCreator,
66 lang::XServiceInfo,
67 lang::XServiceName > TargetPropertiesCreator_Base;
69 class TargetPropertiesCreator : public ::comphelper::OBaseMutex,
70 public TargetPropertiesCreator_Base
72 public:
73 static uno::Reference< uno::XInterface > SAL_CALL createInstance( const uno::Reference< uno::XComponentContext >& xContext ) throw ( uno::Exception )
75 return uno::Reference< uno::XInterface >( static_cast<cppu::OWeakObject*>(new TargetPropertiesCreator( xContext )) );
78 /// Dispose all internal references
79 virtual void SAL_CALL disposing();
81 // XTargetPropertiesCreator
82 virtual uno::Sequence< animations::TargetProperties > SAL_CALL createInitialTargetProperties( const uno::Reference< animations::XAnimationNode >& rootNode ) throw (uno::RuntimeException);
84 // XServiceInfo
85 virtual ::rtl::OUString SAL_CALL getImplementationName() throw( uno::RuntimeException );
86 virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException );
87 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( uno::RuntimeException );
89 // XServiceName
90 virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (uno::RuntimeException);
92 protected:
93 ~TargetPropertiesCreator(); // we're a ref-counted UNO class. _We_ destroy ourselves.
95 private:
96 // default: disabled copy/assignment
97 TargetPropertiesCreator(const TargetPropertiesCreator&);
98 TargetPropertiesCreator& operator=( const TargetPropertiesCreator& );
100 TargetPropertiesCreator( const uno::Reference< uno::XComponentContext >& rxContext );
103 // --------------------------------------------------------------------
105 uno::Reference< uno::XInterface > SAL_CALL createInstance_TargetPropertiesCreator( const uno::Reference< uno::XComponentContext > & rSMgr ) throw (uno::Exception)
107 return TargetPropertiesCreator::createInstance( rSMgr );
110 ::rtl::OUString getImplementationName_TargetPropertiesCreator()
112 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
115 uno::Sequence< ::rtl::OUString > getSupportedServiceNames_TargetPropertiesCreator(void)
117 uno::Sequence< ::rtl::OUString > aRet(1);
118 aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
119 return aRet;
122 // --------------------------------------------------------------------
124 namespace
126 // Vector containing all properties for a given shape
127 typedef ::std::vector< beans::NamedValue > VectorOfNamedValues;
129 /** The hash map key
131 This key contains both XShape reference and a paragraph
132 index, as we somehow have to handle shape and paragraph
133 targets with the same data structure.
135 struct ShapeHashKey
137 /// Shape target
138 uno::Reference< drawing::XShape > mxRef;
140 /** Paragraph index.
142 If this is a pure shape target, mnParagraphIndex is
143 set to -1.
145 sal_Int16 mnParagraphIndex;
147 /// Comparison needed for hash_map
148 bool operator==( const ShapeHashKey& rRHS ) const
150 return mxRef == rRHS.mxRef && mnParagraphIndex == rRHS.mnParagraphIndex;
154 // A hash map which maps a XShape to the corresponding vector of initial properties
155 typedef ::std::hash_map< ShapeHashKey,
156 VectorOfNamedValues,
157 ::std::size_t (*)(const ShapeHashKey&) > XShapeHash;
159 ::std::size_t refhasher( const ShapeHashKey& rKey )
161 // TODO(P2): Maybe a better hash function would be to
162 // spread mnParagraphIndex to 32 bit: a0b0c0d0e0... Hakmem
163 // should have a formula.
165 // Yes it has:
166 // x = (x & 0x0000FF00) << 8) | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF;
167 // x = (x & 0x00F000F0) << 4) | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F;
168 // x = (x & 0x0C0C0C0C) << 2) | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3;
169 // x = (x & 0x22222222) << 1) | (x >> 1) & 0x22222222 | x & 0x99999999;
171 // Costs about 17 cycles on a RISC machine with infinite
172 // instruction level parallelism (~42 basic
173 // instructions). Thus I truly doubt this pays off...
174 return reinterpret_cast< ::std::size_t >(rKey.mxRef.get()) ^ (rKey.mnParagraphIndex << 16L);
178 class NodeFunctor
180 public:
181 explicit NodeFunctor( XShapeHash& rShapeHash ) :
182 mrShapeHash( rShapeHash ),
183 mxTargetShape(),
184 mnParagraphIndex( -1 )
188 NodeFunctor( XShapeHash& rShapeHash,
189 const uno::Reference< drawing::XShape >& rTargetShape,
190 sal_Int16 nParagraphIndex ) :
191 mrShapeHash( rShapeHash ),
192 mxTargetShape( rTargetShape ),
193 mnParagraphIndex( nParagraphIndex )
197 void operator()( const uno::Reference< animations::XAnimationNode >& xNode ) const
199 if( !xNode.is() )
201 OSL_ENSURE( false,
202 "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" );
203 return;
206 uno::Reference< drawing::XShape > xTargetShape( mxTargetShape );
207 sal_Int16 nParagraphIndex( mnParagraphIndex );
209 switch( xNode->getType() )
211 case animations::AnimationNodeType::ITERATE:
213 // extract target shape from iterate node
214 // (will override the target for all children)
215 // --------------------------------------------------
217 uno::Reference< animations::XIterateContainer > xIterNode( xNode,
218 uno::UNO_QUERY );
220 // TODO(E1): I'm not too sure what to expect here...
221 if( !xIterNode->getTarget().hasValue() )
223 OSL_ENSURE( false,
224 "animcore: NodeFunctor::operator(): no target on ITERATE node" );
225 return;
228 xTargetShape.set( xIterNode->getTarget(),
229 uno::UNO_QUERY );
231 if( !xTargetShape.is() )
233 ::com::sun::star::presentation::ParagraphTarget aTarget;
235 // no shape provided. Maybe a ParagraphTarget?
236 if( !(xIterNode->getTarget() >>= aTarget) )
238 OSL_ENSURE( false,
239 "animcore: NodeFunctor::operator(): could not extract any "
240 "target information" );
241 return;
244 xTargetShape = aTarget.Shape;
245 nParagraphIndex = aTarget.Paragraph;
247 if( !xTargetShape.is() )
249 OSL_ENSURE( false,
250 "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" );
251 return;
255 // FALLTHROUGH intended
256 case animations::AnimationNodeType::PAR:
257 // FALLTHROUGH intended
258 case animations::AnimationNodeType::SEQ:
260 NodeFunctor aFunctor( mrShapeHash,
261 xTargetShape,
262 nParagraphIndex );
263 if( !::anim::for_each_childNode( xNode,
264 aFunctor ) )
266 OSL_ENSURE( false,
267 "AnimCore: NodeFunctor::operator(): child node iteration failed, "
268 "or extraneous container nodes encountered" );
271 break;
273 case animations::AnimationNodeType::CUSTOM:
274 // FALLTHROUGH intended
275 case animations::AnimationNodeType::ANIMATE:
276 // FALLTHROUGH intended
277 case animations::AnimationNodeType::ANIMATEMOTION:
278 // FALLTHROUGH intended
279 case animations::AnimationNodeType::ANIMATECOLOR:
280 // FALLTHROUGH intended
281 case animations::AnimationNodeType::ANIMATETRANSFORM:
282 // FALLTHROUGH intended
283 case animations::AnimationNodeType::TRANSITIONFILTER:
284 // FALLTHROUGH intended
285 case animations::AnimationNodeType::AUDIO:
286 // FALLTHROUGH intended
287 default:
288 // ignore this node, no valuable content for now.
289 break;
291 case animations::AnimationNodeType::SET:
293 // evaluate set node content
294 uno::Reference< animations::XAnimate > xAnimateNode( xNode,
295 uno::UNO_QUERY );
297 if( !xAnimateNode.is() )
298 break; // invalid node
300 // determine target shape (if any)
301 ShapeHashKey aTarget;
302 if( xTargetShape.is() )
304 // override target shape with parent-supplied
305 aTarget.mxRef = xTargetShape;
306 aTarget.mnParagraphIndex = nParagraphIndex;
308 else
310 // no parent-supplied target, retrieve
311 // node target
312 if( (xAnimateNode->getTarget() >>= aTarget.mxRef) )
314 // pure shape target - set paragraph
315 // index to magic
316 aTarget.mnParagraphIndex = -1;
318 else
320 // not a pure shape target - maybe a
321 // ParagraphTarget?
322 presentation::ParagraphTarget aUnoTarget;
324 if( !(xAnimateNode->getTarget() >>= aUnoTarget) )
326 OSL_ENSURE( false,
327 "AnimCore: NodeFunctor::operator(): unknown target type encountered" );
328 break;
331 aTarget.mxRef = aUnoTarget.Shape;
332 aTarget.mnParagraphIndex = aUnoTarget.Paragraph;
336 if( !aTarget.mxRef.is() )
338 OSL_ENSURE( false,
339 "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" );
340 break; // invalid target XShape
343 // check whether we already have an entry for
344 // this target (we only take the first set
345 // effect for every shape)
346 XShapeHash::const_iterator aIter;
347 if( (aIter=mrShapeHash.find( aTarget )) != mrShapeHash.end() )
348 break; // already an entry in existence for given XShape
350 // if this is an appear effect, hide shape
351 // initially. This is currently the only place
352 // where a shape effect influences shape
353 // attributes outside it's effective duration.
354 if( xAnimateNode->getAttributeName().equalsIgnoreAsciiCaseAscii("visibility") )
356 sal_Bool bVisible( sal_False );
358 uno::Any aAny( xAnimateNode->getTo() );
360 // try to extract bool value
361 if( !(aAny >>= bVisible) )
363 // try to extract string
364 ::rtl::OUString aString;
365 if( (aAny >>= aString) )
367 // we also take the strings "true" and "false",
368 // as well as "on" and "off" here
369 if( aString.equalsIgnoreAsciiCaseAscii("true") ||
370 aString.equalsIgnoreAsciiCaseAscii("on") )
372 bVisible = sal_True;
374 if( aString.equalsIgnoreAsciiCaseAscii("false") ||
375 aString.equalsIgnoreAsciiCaseAscii("off") )
377 bVisible = sal_False;
382 if( bVisible )
384 // target is set to 'visible' at the
385 // first relevant effect. Thus, target
386 // must be initially _hidden_, for the
387 // effect to have visible impact.
388 mrShapeHash.insert(
389 XShapeHash::value_type(
390 aTarget,
391 VectorOfNamedValues(
393 beans::NamedValue(
394 xAnimateNode->getAttributeName(),
395 uno::makeAny( sal_False ) ) ) ) );
399 break;
403 private:
404 XShapeHash& mrShapeHash;
405 uno::Reference< drawing::XShape > mxTargetShape;
406 sal_Int16 mnParagraphIndex;
410 // --------------------------------------------------------------------
412 TargetPropertiesCreator::TargetPropertiesCreator( const uno::Reference< uno::XComponentContext >& ) :
413 TargetPropertiesCreator_Base( m_aMutex )
417 TargetPropertiesCreator::~TargetPropertiesCreator()
421 void SAL_CALL TargetPropertiesCreator::disposing()
423 ::osl::MutexGuard aGuard( m_aMutex );
426 // XTargetPropertiesCreator
427 uno::Sequence< animations::TargetProperties > SAL_CALL TargetPropertiesCreator::createInitialTargetProperties
429 const uno::Reference< animations::XAnimationNode >& xRootNode
430 ) throw (uno::RuntimeException)
432 ::osl::MutexGuard aGuard( m_aMutex );
434 // scan all nodes for visibility changes, and record first
435 // 'visibility=true' for each shape
436 XShapeHash aShapeHash( 101,
437 &refhasher );
439 NodeFunctor aFunctor( aShapeHash );
441 // TODO(F1): Maybe limit functor application to main sequence
442 // alone (CL said something that shape visibility is only
443 // affected by effects in the main sequence for PPT).
445 // OTOH, client code can pass us only the main sequence (which
446 // it actually does right now, for the slideshow implementation).
447 aFunctor( xRootNode );
450 // output to result sequence
451 // ----------------------------------------------------------------------
453 uno::Sequence< animations::TargetProperties > aRes( aShapeHash.size() );
455 ::std::size_t nCurrIndex(0);
456 XShapeHash::const_iterator aCurr( aShapeHash.begin() );
457 const XShapeHash::const_iterator aEnd ( aShapeHash.end() );
458 while( aCurr != aEnd )
460 animations::TargetProperties& rCurrProps( aRes[ nCurrIndex++ ] );
462 if( aCurr->first.mnParagraphIndex == -1 )
464 rCurrProps.Target = uno::makeAny( aCurr->first.mxRef );
466 else
468 rCurrProps.Target = uno::makeAny(
469 presentation::ParagraphTarget(
470 aCurr->first.mxRef,
471 aCurr->first.mnParagraphIndex ) );
474 rCurrProps.Properties = ::comphelper::containerToSequence( aCurr->second );
476 ++aCurr;
479 return aRes;
482 // XServiceInfo
483 ::rtl::OUString SAL_CALL TargetPropertiesCreator::getImplementationName() throw( uno::RuntimeException )
485 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
488 sal_Bool SAL_CALL TargetPropertiesCreator::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
490 return ServiceName.equalsIgnoreAsciiCaseAscii( SERVICE_NAME );
493 uno::Sequence< ::rtl::OUString > SAL_CALL TargetPropertiesCreator::getSupportedServiceNames() throw( uno::RuntimeException )
495 uno::Sequence< ::rtl::OUString > aRet(1);
496 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
498 return aRet;
501 // XServiceName
502 ::rtl::OUString SAL_CALL TargetPropertiesCreator::getServiceName( ) throw (uno::RuntimeException)
504 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
507 } // namespace animcore