1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/XComponentContext.hpp>
25*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XServiceInfo.hpp>
26*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XTypeProvider.hpp>
27*b1cdbd2cSJim Jagielski #include <com/sun/star/animations/XTargetPropertiesCreator.hpp>
28*b1cdbd2cSJim Jagielski #include <com/sun/star/animations/XIterateContainer.hpp>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/animations/TargetProperties.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/presentation/ParagraphTarget.hpp>
31*b1cdbd2cSJim Jagielski #include <com/sun/star/registry/XRegistryKey.hpp>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XInitialization.hpp>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XServiceName.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/drawing/XShape.hpp>
36*b1cdbd2cSJim Jagielski #include <com/sun/star/animations/AnimationNodeType.hpp>
37*b1cdbd2cSJim Jagielski #include <com/sun/star/animations/XAnimate.hpp>
38*b1cdbd2cSJim Jagielski #include <cppuhelper/compbase3.hxx>
39*b1cdbd2cSJim Jagielski #include <cppuhelper/factory.hxx>
40*b1cdbd2cSJim Jagielski #include <cppuhelper/implementationentry.hxx>
41*b1cdbd2cSJim Jagielski #include <comphelper/broadcasthelper.hxx>
42*b1cdbd2cSJim Jagielski #include <comphelper/sequence.hxx>
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski #include <animations/animationnodehelper.hxx>
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski #include <vector>
47*b1cdbd2cSJim Jagielski #include <hash_map>
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski #define IMPLEMENTATION_NAME "animcore::TargetPropertiesCreator"
53*b1cdbd2cSJim Jagielski #define SERVICE_NAME "com.sun.star.animations.TargetPropertiesCreator"
54*b1cdbd2cSJim Jagielski 
55*b1cdbd2cSJim Jagielski namespace animcore
56*b1cdbd2cSJim Jagielski {
57*b1cdbd2cSJim Jagielski     typedef ::cppu::WeakComponentImplHelper3< ::com::sun::star::animations::XTargetPropertiesCreator,
58*b1cdbd2cSJim Jagielski                                               lang::XServiceInfo,
59*b1cdbd2cSJim Jagielski                                               lang::XServiceName >  TargetPropertiesCreator_Base;
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski     class TargetPropertiesCreator : public ::comphelper::OBaseMutex,
62*b1cdbd2cSJim Jagielski                                     public TargetPropertiesCreator_Base
63*b1cdbd2cSJim Jagielski     {
64*b1cdbd2cSJim Jagielski     public:
createInstance(const uno::Reference<uno::XComponentContext> & xContext)65*b1cdbd2cSJim Jagielski         static uno::Reference< uno::XInterface > SAL_CALL createInstance( const uno::Reference< uno::XComponentContext >& xContext ) throw ( uno::Exception )
66*b1cdbd2cSJim Jagielski         {
67*b1cdbd2cSJim Jagielski             return uno::Reference< uno::XInterface >( static_cast<cppu::OWeakObject*>(new TargetPropertiesCreator( xContext )) );
68*b1cdbd2cSJim Jagielski         }
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski 	    /// Dispose all internal references
71*b1cdbd2cSJim Jagielski         virtual void SAL_CALL disposing();
72*b1cdbd2cSJim Jagielski 
73*b1cdbd2cSJim Jagielski         // XTargetPropertiesCreator
74*b1cdbd2cSJim Jagielski         virtual uno::Sequence< animations::TargetProperties > SAL_CALL createInitialTargetProperties( const uno::Reference< animations::XAnimationNode >& rootNode ) throw (uno::RuntimeException);
75*b1cdbd2cSJim Jagielski 
76*b1cdbd2cSJim Jagielski         // XServiceInfo
77*b1cdbd2cSJim Jagielski         virtual ::rtl::OUString SAL_CALL getImplementationName() throw( uno::RuntimeException );
78*b1cdbd2cSJim Jagielski         virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException );
79*b1cdbd2cSJim Jagielski         virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()  throw( uno::RuntimeException );
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski         // XServiceName
82*b1cdbd2cSJim Jagielski         virtual ::rtl::OUString SAL_CALL getServiceName(  ) throw (uno::RuntimeException);
83*b1cdbd2cSJim Jagielski 
84*b1cdbd2cSJim Jagielski     protected:
85*b1cdbd2cSJim Jagielski         ~TargetPropertiesCreator(); // we're a ref-counted UNO class. _We_ destroy ourselves.
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski     private:
88*b1cdbd2cSJim Jagielski         // default: disabled copy/assignment
89*b1cdbd2cSJim Jagielski         TargetPropertiesCreator(const TargetPropertiesCreator&);
90*b1cdbd2cSJim Jagielski         TargetPropertiesCreator& operator=( const TargetPropertiesCreator& );
91*b1cdbd2cSJim Jagielski 
92*b1cdbd2cSJim Jagielski         TargetPropertiesCreator( const uno::Reference< uno::XComponentContext >& rxContext );
93*b1cdbd2cSJim Jagielski     };
94*b1cdbd2cSJim Jagielski 
95*b1cdbd2cSJim Jagielski 	// --------------------------------------------------------------------
96*b1cdbd2cSJim Jagielski 
createInstance_TargetPropertiesCreator(const uno::Reference<uno::XComponentContext> & rSMgr)97*b1cdbd2cSJim Jagielski     uno::Reference< uno::XInterface > SAL_CALL createInstance_TargetPropertiesCreator( const uno::Reference< uno::XComponentContext > & rSMgr ) throw (uno::Exception)
98*b1cdbd2cSJim Jagielski     {
99*b1cdbd2cSJim Jagielski         return TargetPropertiesCreator::createInstance( rSMgr );
100*b1cdbd2cSJim Jagielski     }
101*b1cdbd2cSJim Jagielski 
getImplementationName_TargetPropertiesCreator()102*b1cdbd2cSJim Jagielski     ::rtl::OUString getImplementationName_TargetPropertiesCreator()
103*b1cdbd2cSJim Jagielski     {
104*b1cdbd2cSJim Jagielski         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
105*b1cdbd2cSJim Jagielski     }
106*b1cdbd2cSJim Jagielski 
getSupportedServiceNames_TargetPropertiesCreator(void)107*b1cdbd2cSJim Jagielski     uno::Sequence< ::rtl::OUString > getSupportedServiceNames_TargetPropertiesCreator(void)
108*b1cdbd2cSJim Jagielski     {
109*b1cdbd2cSJim Jagielski         uno::Sequence< ::rtl::OUString > aRet(1);
110*b1cdbd2cSJim Jagielski         aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
111*b1cdbd2cSJim Jagielski         return aRet;
112*b1cdbd2cSJim Jagielski     }
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski 	// --------------------------------------------------------------------
115*b1cdbd2cSJim Jagielski 
116*b1cdbd2cSJim Jagielski     namespace
117*b1cdbd2cSJim Jagielski     {
118*b1cdbd2cSJim Jagielski         // Vector containing all properties for a given shape
119*b1cdbd2cSJim Jagielski         typedef ::std::vector< beans::NamedValue > VectorOfNamedValues;
120*b1cdbd2cSJim Jagielski 
121*b1cdbd2cSJim Jagielski         /** The hash map key
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski         	This key contains both XShape reference and a paragraph
124*b1cdbd2cSJim Jagielski         	index, as we somehow have to handle shape and paragraph
125*b1cdbd2cSJim Jagielski         	targets with the same data structure.
126*b1cdbd2cSJim Jagielski          */
127*b1cdbd2cSJim Jagielski         struct ShapeHashKey
128*b1cdbd2cSJim Jagielski         {
129*b1cdbd2cSJim Jagielski             /// Shape target
130*b1cdbd2cSJim Jagielski             uno::Reference< drawing::XShape >	mxRef;
131*b1cdbd2cSJim Jagielski 
132*b1cdbd2cSJim Jagielski             /** Paragraph index.
133*b1cdbd2cSJim Jagielski 
134*b1cdbd2cSJim Jagielski             	If this is a pure shape target, mnParagraphIndex is
135*b1cdbd2cSJim Jagielski             	set to -1.
136*b1cdbd2cSJim Jagielski              */
137*b1cdbd2cSJim Jagielski             sal_Int16							mnParagraphIndex;
138*b1cdbd2cSJim Jagielski 
139*b1cdbd2cSJim Jagielski             /// Comparison needed for hash_map
operator ==animcore::__anon7875b3a30111::ShapeHashKey140*b1cdbd2cSJim Jagielski             bool operator==( const ShapeHashKey& rRHS ) const
141*b1cdbd2cSJim Jagielski             {
142*b1cdbd2cSJim Jagielski                 return mxRef == rRHS.mxRef && mnParagraphIndex == rRHS.mnParagraphIndex;
143*b1cdbd2cSJim Jagielski             }
144*b1cdbd2cSJim Jagielski         };
145*b1cdbd2cSJim Jagielski 
146*b1cdbd2cSJim Jagielski         // A hash functor for ShapeHashKey objects
147*b1cdbd2cSJim Jagielski         struct ShapeKeyHasher {
operator ()animcore::__anon7875b3a30111::ShapeKeyHasher148*b1cdbd2cSJim Jagielski 		::std::size_t operator()( const ShapeHashKey& rKey ) const
149*b1cdbd2cSJim Jagielski 		{
150*b1cdbd2cSJim Jagielski 		// TODO(P2): Maybe a better hash function would be to
151*b1cdbd2cSJim Jagielski 		// spread mnParagraphIndex to 32 bit: a0b0c0d0e0... Hakmem
152*b1cdbd2cSJim Jagielski 		// should have a formula.
153*b1cdbd2cSJim Jagielski 		//
154*b1cdbd2cSJim Jagielski 		// Yes it has:
155*b1cdbd2cSJim Jagielski 		// x = (x & 0x0000FF00) << 8) | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF;
156*b1cdbd2cSJim Jagielski 		// x = (x & 0x00F000F0) << 4) | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F;
157*b1cdbd2cSJim Jagielski 		// x = (x & 0x0C0C0C0C) << 2) | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3;
158*b1cdbd2cSJim Jagielski 		// x = (x & 0x22222222) << 1) | (x >> 1) & 0x22222222 | x & 0x99999999;
159*b1cdbd2cSJim Jagielski 		//
160*b1cdbd2cSJim Jagielski 		// Costs about 17 cycles on a RISC machine with infinite
161*b1cdbd2cSJim Jagielski 		// instruction level parallelism (~42 basic
162*b1cdbd2cSJim Jagielski 		// instructions). Thus I truly doubt this pays off...
163*b1cdbd2cSJim Jagielski 		return reinterpret_cast< ::std::size_t >(rKey.mxRef.get()) ^ (rKey.mnParagraphIndex << 16L);
164*b1cdbd2cSJim Jagielski 	    }
165*b1cdbd2cSJim Jagielski 	};
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski         // A hash map which maps a XShape to the corresponding vector of initial properties
168*b1cdbd2cSJim Jagielski         typedef ::std::hash_map< ShapeHashKey, VectorOfNamedValues, ShapeKeyHasher > XShapeHash;
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski         class NodeFunctor
171*b1cdbd2cSJim Jagielski         {
172*b1cdbd2cSJim Jagielski         public:
NodeFunctor(XShapeHash & rShapeHash)173*b1cdbd2cSJim Jagielski             explicit NodeFunctor( XShapeHash& rShapeHash ) :
174*b1cdbd2cSJim Jagielski                 mrShapeHash( rShapeHash ),
175*b1cdbd2cSJim Jagielski                 mxTargetShape(),
176*b1cdbd2cSJim Jagielski                 mnParagraphIndex( -1 )
177*b1cdbd2cSJim Jagielski             {
178*b1cdbd2cSJim Jagielski             }
179*b1cdbd2cSJim Jagielski 
NodeFunctor(XShapeHash & rShapeHash,const uno::Reference<drawing::XShape> & rTargetShape,sal_Int16 nParagraphIndex)180*b1cdbd2cSJim Jagielski             NodeFunctor( XShapeHash& 								rShapeHash,
181*b1cdbd2cSJim Jagielski                          const uno::Reference< drawing::XShape >& 	rTargetShape,
182*b1cdbd2cSJim Jagielski                          sal_Int16									nParagraphIndex ) :
183*b1cdbd2cSJim Jagielski                 mrShapeHash( rShapeHash ),
184*b1cdbd2cSJim Jagielski                 mxTargetShape( rTargetShape ),
185*b1cdbd2cSJim Jagielski                 mnParagraphIndex( nParagraphIndex )
186*b1cdbd2cSJim Jagielski             {
187*b1cdbd2cSJim Jagielski             }
188*b1cdbd2cSJim Jagielski 
operator ()(const uno::Reference<animations::XAnimationNode> & xNode) const189*b1cdbd2cSJim Jagielski             void operator()( const uno::Reference< animations::XAnimationNode >& xNode ) const
190*b1cdbd2cSJim Jagielski             {
191*b1cdbd2cSJim Jagielski                 if( !xNode.is() )
192*b1cdbd2cSJim Jagielski                 {
193*b1cdbd2cSJim Jagielski                     OSL_ENSURE( false,
194*b1cdbd2cSJim Jagielski                                 "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" );
195*b1cdbd2cSJim Jagielski                     return;
196*b1cdbd2cSJim Jagielski                 }
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski                 uno::Reference< drawing::XShape > xTargetShape( mxTargetShape );
199*b1cdbd2cSJim Jagielski                 sal_Int16						  nParagraphIndex( mnParagraphIndex );
200*b1cdbd2cSJim Jagielski 
201*b1cdbd2cSJim Jagielski                 switch( xNode->getType() )
202*b1cdbd2cSJim Jagielski                 {
203*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::ITERATE:
204*b1cdbd2cSJim Jagielski                     {
205*b1cdbd2cSJim Jagielski                         // extract target shape from iterate node
206*b1cdbd2cSJim Jagielski                         // (will override the target for all children)
207*b1cdbd2cSJim Jagielski                         // --------------------------------------------------
208*b1cdbd2cSJim Jagielski 
209*b1cdbd2cSJim Jagielski                         uno::Reference< animations::XIterateContainer > xIterNode( xNode,
210*b1cdbd2cSJim Jagielski                                                                                    uno::UNO_QUERY );
211*b1cdbd2cSJim Jagielski 
212*b1cdbd2cSJim Jagielski 	                    // TODO(E1): I'm not too sure what to expect here...
213*b1cdbd2cSJim Jagielski                         if( !xIterNode->getTarget().hasValue() )
214*b1cdbd2cSJim Jagielski                         {
215*b1cdbd2cSJim Jagielski                             OSL_ENSURE( false,
216*b1cdbd2cSJim Jagielski                                         "animcore: NodeFunctor::operator(): no target on ITERATE node" );
217*b1cdbd2cSJim Jagielski                             return;
218*b1cdbd2cSJim Jagielski                         }
219*b1cdbd2cSJim Jagielski 
220*b1cdbd2cSJim Jagielski                         xTargetShape.set( xIterNode->getTarget(),
221*b1cdbd2cSJim Jagielski                                           uno::UNO_QUERY );
222*b1cdbd2cSJim Jagielski 
223*b1cdbd2cSJim Jagielski                         if( !xTargetShape.is() )
224*b1cdbd2cSJim Jagielski                         {
225*b1cdbd2cSJim Jagielski                             ::com::sun::star::presentation::ParagraphTarget aTarget;
226*b1cdbd2cSJim Jagielski 
227*b1cdbd2cSJim Jagielski                             // no shape provided. Maybe a ParagraphTarget?
228*b1cdbd2cSJim Jagielski                             if( !(xIterNode->getTarget() >>= aTarget) )
229*b1cdbd2cSJim Jagielski                             {
230*b1cdbd2cSJim Jagielski                                 OSL_ENSURE( false,
231*b1cdbd2cSJim Jagielski                                             "animcore: NodeFunctor::operator(): could not extract any "
232*b1cdbd2cSJim Jagielski                                             "target information" );
233*b1cdbd2cSJim Jagielski                                 return;
234*b1cdbd2cSJim Jagielski                             }
235*b1cdbd2cSJim Jagielski 
236*b1cdbd2cSJim Jagielski                             xTargetShape = aTarget.Shape;
237*b1cdbd2cSJim Jagielski                             nParagraphIndex = aTarget.Paragraph;
238*b1cdbd2cSJim Jagielski 
239*b1cdbd2cSJim Jagielski                             if( !xTargetShape.is() )
240*b1cdbd2cSJim Jagielski                             {
241*b1cdbd2cSJim Jagielski                                 OSL_ENSURE( false,
242*b1cdbd2cSJim Jagielski                                             "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" );
243*b1cdbd2cSJim Jagielski                                 return;
244*b1cdbd2cSJim Jagielski                             }
245*b1cdbd2cSJim Jagielski                         }
246*b1cdbd2cSJim Jagielski                     }
247*b1cdbd2cSJim Jagielski 	                    // FALLTHROUGH intended
248*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::PAR:
249*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
250*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::SEQ:
251*b1cdbd2cSJim Jagielski                     {
252*b1cdbd2cSJim Jagielski                         NodeFunctor aFunctor( mrShapeHash,
253*b1cdbd2cSJim Jagielski                                               xTargetShape,
254*b1cdbd2cSJim Jagielski                                               nParagraphIndex );
255*b1cdbd2cSJim Jagielski                         if( !::anim::for_each_childNode( xNode,
256*b1cdbd2cSJim Jagielski                                                          aFunctor ) )
257*b1cdbd2cSJim Jagielski                         {
258*b1cdbd2cSJim Jagielski                             OSL_ENSURE( false,
259*b1cdbd2cSJim Jagielski                                         "AnimCore: NodeFunctor::operator(): child node iteration failed, "
260*b1cdbd2cSJim Jagielski                                         "or extraneous container nodes encountered" );
261*b1cdbd2cSJim Jagielski                         }
262*b1cdbd2cSJim Jagielski                     }
263*b1cdbd2cSJim Jagielski                     break;
264*b1cdbd2cSJim Jagielski 
265*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::CUSTOM:
266*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
267*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::ANIMATE:
268*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
269*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::ANIMATEMOTION:
270*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
271*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::ANIMATECOLOR:
272*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
273*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::ANIMATETRANSFORM:
274*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
275*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::TRANSITIONFILTER:
276*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
277*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::AUDIO:
278*b1cdbd2cSJim Jagielski                         // FALLTHROUGH intended
279*b1cdbd2cSJim Jagielski                     /*default:
280*b1cdbd2cSJim Jagielski                         // ignore this node, no valuable content for now.
281*b1cdbd2cSJim Jagielski                         break;*/
282*b1cdbd2cSJim Jagielski 
283*b1cdbd2cSJim Jagielski                     case animations::AnimationNodeType::SET:
284*b1cdbd2cSJim Jagielski                     {
285*b1cdbd2cSJim Jagielski                         // evaluate set node content
286*b1cdbd2cSJim Jagielski                         uno::Reference< animations::XAnimate > xAnimateNode( xNode,
287*b1cdbd2cSJim Jagielski                                                                              uno::UNO_QUERY );
288*b1cdbd2cSJim Jagielski 
289*b1cdbd2cSJim Jagielski                         if( !xAnimateNode.is() )
290*b1cdbd2cSJim Jagielski                             break; // invalid node
291*b1cdbd2cSJim Jagielski 
292*b1cdbd2cSJim Jagielski                         // determine target shape (if any)
293*b1cdbd2cSJim Jagielski                         ShapeHashKey aTarget;
294*b1cdbd2cSJim Jagielski                         if( xTargetShape.is() )
295*b1cdbd2cSJim Jagielski                         {
296*b1cdbd2cSJim Jagielski                             // override target shape with parent-supplied
297*b1cdbd2cSJim Jagielski                             aTarget.mxRef = xTargetShape;
298*b1cdbd2cSJim Jagielski                             aTarget.mnParagraphIndex = nParagraphIndex;
299*b1cdbd2cSJim Jagielski                         }
300*b1cdbd2cSJim Jagielski                         else
301*b1cdbd2cSJim Jagielski                         {
302*b1cdbd2cSJim Jagielski                             // no parent-supplied target, retrieve
303*b1cdbd2cSJim Jagielski                             // node target
304*b1cdbd2cSJim Jagielski                             if( (xAnimateNode->getTarget() >>= aTarget.mxRef) )
305*b1cdbd2cSJim Jagielski                             {
306*b1cdbd2cSJim Jagielski                                 // pure shape target - set paragraph
307*b1cdbd2cSJim Jagielski                                 // index to magic
308*b1cdbd2cSJim Jagielski                                 aTarget.mnParagraphIndex = -1;
309*b1cdbd2cSJim Jagielski                             }
310*b1cdbd2cSJim Jagielski                             else
311*b1cdbd2cSJim Jagielski                             {
312*b1cdbd2cSJim Jagielski                                 // not a pure shape target - maybe a
313*b1cdbd2cSJim Jagielski                                 // ParagraphTarget?
314*b1cdbd2cSJim Jagielski                                 presentation::ParagraphTarget aUnoTarget;
315*b1cdbd2cSJim Jagielski 
316*b1cdbd2cSJim Jagielski                                 if( !(xAnimateNode->getTarget() >>= aUnoTarget) )
317*b1cdbd2cSJim Jagielski                                 {
318*b1cdbd2cSJim Jagielski                                     OSL_ENSURE( false,
319*b1cdbd2cSJim Jagielski                                                 "AnimCore: NodeFunctor::operator(): unknown target type encountered" );
320*b1cdbd2cSJim Jagielski                                     break;
321*b1cdbd2cSJim Jagielski                                 }
322*b1cdbd2cSJim Jagielski 
323*b1cdbd2cSJim Jagielski                                 aTarget.mxRef = aUnoTarget.Shape;
324*b1cdbd2cSJim Jagielski                                 aTarget.mnParagraphIndex = aUnoTarget.Paragraph;
325*b1cdbd2cSJim Jagielski                             }
326*b1cdbd2cSJim Jagielski                         }
327*b1cdbd2cSJim Jagielski 
328*b1cdbd2cSJim Jagielski                         if( !aTarget.mxRef.is() )
329*b1cdbd2cSJim Jagielski                         {
330*b1cdbd2cSJim Jagielski                             OSL_ENSURE( false,
331*b1cdbd2cSJim Jagielski                                         "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" );
332*b1cdbd2cSJim Jagielski                             break; // invalid target XShape
333*b1cdbd2cSJim Jagielski                         }
334*b1cdbd2cSJim Jagielski 
335*b1cdbd2cSJim Jagielski                         // check whether we already have an entry for
336*b1cdbd2cSJim Jagielski                         // this target (we only take the first set
337*b1cdbd2cSJim Jagielski                         // effect for every shape)
338*b1cdbd2cSJim Jagielski                         XShapeHash::const_iterator aIter;
339*b1cdbd2cSJim Jagielski                         if( (aIter=mrShapeHash.find( aTarget )) != mrShapeHash.end() )
340*b1cdbd2cSJim Jagielski                             break; // already an entry in existence for given XShape
341*b1cdbd2cSJim Jagielski 
342*b1cdbd2cSJim Jagielski                         // if this is an appear effect, hide shape
343*b1cdbd2cSJim Jagielski                         // initially. This is currently the only place
344*b1cdbd2cSJim Jagielski                         // where a shape effect influences shape
345*b1cdbd2cSJim Jagielski                         // attributes outside it's effective duration.
346*b1cdbd2cSJim Jagielski 			sal_Bool bVisible( sal_False );
347*b1cdbd2cSJim Jagielski                         if( xAnimateNode->getAttributeName().equalsIgnoreAsciiCaseAscii("visibility") )
348*b1cdbd2cSJim Jagielski                         {
349*b1cdbd2cSJim Jagielski 
350*b1cdbd2cSJim Jagielski                             uno::Any aAny( xAnimateNode->getTo() );
351*b1cdbd2cSJim Jagielski 
352*b1cdbd2cSJim Jagielski                             // try to extract bool value
353*b1cdbd2cSJim Jagielski                             if( !(aAny >>= bVisible) )
354*b1cdbd2cSJim Jagielski                             {
355*b1cdbd2cSJim Jagielski                                 // try to extract string
356*b1cdbd2cSJim Jagielski                                 ::rtl::OUString aString;
357*b1cdbd2cSJim Jagielski                                 if( (aAny >>= aString) )
358*b1cdbd2cSJim Jagielski                                 {
359*b1cdbd2cSJim Jagielski                                     // we also take the strings "true" and "false",
360*b1cdbd2cSJim Jagielski                                     // as well as "on" and "off" here
361*b1cdbd2cSJim Jagielski                                     if( aString.equalsIgnoreAsciiCaseAscii("true") ||
362*b1cdbd2cSJim Jagielski                                         aString.equalsIgnoreAsciiCaseAscii("on") )
363*b1cdbd2cSJim Jagielski                                     {
364*b1cdbd2cSJim Jagielski                                         bVisible = sal_True;
365*b1cdbd2cSJim Jagielski                                     }
366*b1cdbd2cSJim Jagielski                                     if( aString.equalsIgnoreAsciiCaseAscii("false") ||
367*b1cdbd2cSJim Jagielski                                         aString.equalsIgnoreAsciiCaseAscii("off") )
368*b1cdbd2cSJim Jagielski                                     {
369*b1cdbd2cSJim Jagielski                                         bVisible = sal_False;
370*b1cdbd2cSJim Jagielski                                     }
371*b1cdbd2cSJim Jagielski                                 }
372*b1cdbd2cSJim Jagielski                             }
373*b1cdbd2cSJim Jagielski 
374*b1cdbd2cSJim Jagielski                             /*if( bVisible )
375*b1cdbd2cSJim Jagielski                             {
376*b1cdbd2cSJim Jagielski                                 // target is set to 'visible' at the
377*b1cdbd2cSJim Jagielski                                 // first relevant effect. Thus, target
378*b1cdbd2cSJim Jagielski                                 // must be initially _hidden_, for the
379*b1cdbd2cSJim Jagielski                                 // effect to have visible impact.
380*b1cdbd2cSJim Jagielski                                 */
381*b1cdbd2cSJim Jagielski 				}
382*b1cdbd2cSJim Jagielski 						    // target is set the 'visible' value,
383*b1cdbd2cSJim Jagielski 							// so we should record the opposite value
384*b1cdbd2cSJim Jagielski 				mrShapeHash.insert(
385*b1cdbd2cSJim Jagielski                                     XShapeHash::value_type(
386*b1cdbd2cSJim Jagielski                                         aTarget,
387*b1cdbd2cSJim Jagielski                                         VectorOfNamedValues(
388*b1cdbd2cSJim Jagielski                                             1,
389*b1cdbd2cSJim Jagielski                                             beans::NamedValue(
390*b1cdbd2cSJim Jagielski                                                 //xAnimateNode->getAttributeName(),
391*b1cdbd2cSJim Jagielski 						::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("visibility")),
392*b1cdbd2cSJim Jagielski                                                 uno::makeAny( !bVisible ) ) ) ) );
393*b1cdbd2cSJim Jagielski                             //}
394*b1cdbd2cSJim Jagielski                         //}
395*b1cdbd2cSJim Jagielski                     }
396*b1cdbd2cSJim Jagielski                     break;
397*b1cdbd2cSJim Jagielski                 }
398*b1cdbd2cSJim Jagielski             }
399*b1cdbd2cSJim Jagielski 
400*b1cdbd2cSJim Jagielski         private:
401*b1cdbd2cSJim Jagielski             XShapeHash& 						mrShapeHash;
402*b1cdbd2cSJim Jagielski             uno::Reference< drawing::XShape > 	mxTargetShape;
403*b1cdbd2cSJim Jagielski             sal_Int16							mnParagraphIndex;
404*b1cdbd2cSJim Jagielski         };
405*b1cdbd2cSJim Jagielski     }
406*b1cdbd2cSJim Jagielski 
407*b1cdbd2cSJim Jagielski 	// --------------------------------------------------------------------
408*b1cdbd2cSJim Jagielski 
TargetPropertiesCreator(const uno::Reference<uno::XComponentContext> &)409*b1cdbd2cSJim Jagielski     TargetPropertiesCreator::TargetPropertiesCreator( const uno::Reference< uno::XComponentContext >&  ) :
410*b1cdbd2cSJim Jagielski         TargetPropertiesCreator_Base( m_aMutex )
411*b1cdbd2cSJim Jagielski     {
412*b1cdbd2cSJim Jagielski     }
413*b1cdbd2cSJim Jagielski 
~TargetPropertiesCreator()414*b1cdbd2cSJim Jagielski     TargetPropertiesCreator::~TargetPropertiesCreator()
415*b1cdbd2cSJim Jagielski     {
416*b1cdbd2cSJim Jagielski     }
417*b1cdbd2cSJim Jagielski 
disposing()418*b1cdbd2cSJim Jagielski 	void SAL_CALL TargetPropertiesCreator::disposing()
419*b1cdbd2cSJim Jagielski 	{
420*b1cdbd2cSJim Jagielski         ::osl::MutexGuard aGuard( m_aMutex );
421*b1cdbd2cSJim Jagielski 	}
422*b1cdbd2cSJim Jagielski 
423*b1cdbd2cSJim Jagielski     // XTargetPropertiesCreator
createInitialTargetProperties(const uno::Reference<animations::XAnimationNode> & xRootNode)424*b1cdbd2cSJim Jagielski     uno::Sequence< animations::TargetProperties > SAL_CALL TargetPropertiesCreator::createInitialTargetProperties
425*b1cdbd2cSJim Jagielski     	(
426*b1cdbd2cSJim Jagielski             const uno::Reference< animations::XAnimationNode >& xRootNode
427*b1cdbd2cSJim Jagielski         ) throw (uno::RuntimeException)
428*b1cdbd2cSJim Jagielski     {
429*b1cdbd2cSJim Jagielski         ::osl::MutexGuard aGuard( m_aMutex );
430*b1cdbd2cSJim Jagielski 
431*b1cdbd2cSJim Jagielski         // scan all nodes for visibility changes, and record first
432*b1cdbd2cSJim Jagielski         // 'visibility=true' for each shape
433*b1cdbd2cSJim Jagielski         XShapeHash aShapeHash( 101 );
434*b1cdbd2cSJim Jagielski 
435*b1cdbd2cSJim Jagielski         NodeFunctor aFunctor( aShapeHash );
436*b1cdbd2cSJim Jagielski 
437*b1cdbd2cSJim Jagielski         // TODO(F1): Maybe limit functor application to main sequence
438*b1cdbd2cSJim Jagielski         // alone (CL said something that shape visibility is only
439*b1cdbd2cSJim Jagielski         // affected by effects in the main sequence for PPT).
440*b1cdbd2cSJim Jagielski         //
441*b1cdbd2cSJim Jagielski         // OTOH, client code can pass us only the main sequence (which
442*b1cdbd2cSJim Jagielski         // it actually does right now, for the slideshow implementation).
443*b1cdbd2cSJim Jagielski         aFunctor( xRootNode );
444*b1cdbd2cSJim Jagielski 
445*b1cdbd2cSJim Jagielski 
446*b1cdbd2cSJim Jagielski         // output to result sequence
447*b1cdbd2cSJim Jagielski         // ----------------------------------------------------------------------
448*b1cdbd2cSJim Jagielski 
449*b1cdbd2cSJim Jagielski         uno::Sequence< animations::TargetProperties > aRes( aShapeHash.size() );
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski         ::std::size_t						nCurrIndex(0);
452*b1cdbd2cSJim Jagielski         XShapeHash::const_iterator 			aCurr( aShapeHash.begin() );
453*b1cdbd2cSJim Jagielski         const XShapeHash::const_iterator	aEnd ( aShapeHash.end()   );
454*b1cdbd2cSJim Jagielski         while( aCurr != aEnd )
455*b1cdbd2cSJim Jagielski         {
456*b1cdbd2cSJim Jagielski             animations::TargetProperties& rCurrProps( aRes[ nCurrIndex++ ] );
457*b1cdbd2cSJim Jagielski 
458*b1cdbd2cSJim Jagielski             if( aCurr->first.mnParagraphIndex == -1 )
459*b1cdbd2cSJim Jagielski             {
460*b1cdbd2cSJim Jagielski                 rCurrProps.Target = uno::makeAny( aCurr->first.mxRef );
461*b1cdbd2cSJim Jagielski             }
462*b1cdbd2cSJim Jagielski             else
463*b1cdbd2cSJim Jagielski             {
464*b1cdbd2cSJim Jagielski                 rCurrProps.Target = uno::makeAny(
465*b1cdbd2cSJim Jagielski                     presentation::ParagraphTarget(
466*b1cdbd2cSJim Jagielski                         aCurr->first.mxRef,
467*b1cdbd2cSJim Jagielski                         aCurr->first.mnParagraphIndex ) );
468*b1cdbd2cSJim Jagielski             }
469*b1cdbd2cSJim Jagielski 
470*b1cdbd2cSJim Jagielski             rCurrProps.Properties = ::comphelper::containerToSequence( aCurr->second );
471*b1cdbd2cSJim Jagielski 
472*b1cdbd2cSJim Jagielski             ++aCurr;
473*b1cdbd2cSJim Jagielski         }
474*b1cdbd2cSJim Jagielski 
475*b1cdbd2cSJim Jagielski         return aRes;
476*b1cdbd2cSJim Jagielski     }
477*b1cdbd2cSJim Jagielski 
478*b1cdbd2cSJim Jagielski     // XServiceInfo
getImplementationName()479*b1cdbd2cSJim Jagielski     ::rtl::OUString SAL_CALL TargetPropertiesCreator::getImplementationName() throw( uno::RuntimeException )
480*b1cdbd2cSJim Jagielski     {
481*b1cdbd2cSJim Jagielski         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
482*b1cdbd2cSJim Jagielski     }
483*b1cdbd2cSJim Jagielski 
supportsService(const::rtl::OUString & ServiceName)484*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL TargetPropertiesCreator::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
485*b1cdbd2cSJim Jagielski     {
486*b1cdbd2cSJim Jagielski         return ServiceName.equalsIgnoreAsciiCaseAscii( SERVICE_NAME );
487*b1cdbd2cSJim Jagielski     }
488*b1cdbd2cSJim Jagielski 
getSupportedServiceNames()489*b1cdbd2cSJim Jagielski     uno::Sequence< ::rtl::OUString > SAL_CALL TargetPropertiesCreator::getSupportedServiceNames()  throw( uno::RuntimeException )
490*b1cdbd2cSJim Jagielski     {
491*b1cdbd2cSJim Jagielski         uno::Sequence< ::rtl::OUString > aRet(1);
492*b1cdbd2cSJim Jagielski         aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
493*b1cdbd2cSJim Jagielski 
494*b1cdbd2cSJim Jagielski         return aRet;
495*b1cdbd2cSJim Jagielski     }
496*b1cdbd2cSJim Jagielski 
497*b1cdbd2cSJim Jagielski     // XServiceName
getServiceName()498*b1cdbd2cSJim Jagielski     ::rtl::OUString SAL_CALL TargetPropertiesCreator::getServiceName(  ) throw (uno::RuntimeException)
499*b1cdbd2cSJim Jagielski     {
500*b1cdbd2cSJim Jagielski         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
501*b1cdbd2cSJim Jagielski     }
502*b1cdbd2cSJim Jagielski 
503*b1cdbd2cSJim Jagielski } // namespace animcore
504