1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 #include <canvas/debug.hxx> 32 #include <tools/diagnose_ex.h> 33 #include <canvas/verbosetrace.hxx> 34 35 #include "drawshapesubsetting.hxx" 36 #include "subsettableshapemanager.hxx" 37 #include "eventqueue.hxx" 38 #include "eventmultiplexer.hxx" 39 #include "intrinsicanimationactivity.hxx" 40 #include "intrinsicanimationeventhandler.hxx" 41 42 #include <boost/noncopyable.hpp> 43 #include <boost/enable_shared_from_this.hpp> 44 #include <boost/weak_ptr.hpp> 45 46 namespace slideshow 47 { 48 namespace internal 49 { 50 /** Activity for intrinsic shape animations 51 52 This is an Activity interface implementation for intrinsic 53 shape animations. Intrinsic shape animations are 54 animations directly within a shape, e.g. drawing layer 55 animations, or GIF animations. 56 */ 57 class IntrinsicAnimationActivity : public Activity, 58 public boost::enable_shared_from_this<IntrinsicAnimationActivity>, 59 private boost::noncopyable 60 { 61 public: 62 /** Create an IntrinsicAnimationActivity. 63 64 @param rContext 65 Common slideshow objects 66 67 @param rDrawShape 68 Shape to control the intrinsic animation for 69 70 @param rWakeupEvent 71 Externally generated wakeup event, to set this 72 activity to sleep during inter-frame intervals. Must 73 come frome the outside, since wakeup event and this 74 object have mutual references to each other. 75 76 @param rTimeouts 77 Vector of timeout values, to wait before the next 78 frame is shown. 79 */ 80 IntrinsicAnimationActivity( const SlideShowContext& rContext, 81 const DrawShapeSharedPtr& rDrawShape, 82 const WakeupEventSharedPtr& rWakeupEvent, 83 const ::std::vector<double>& rTimeouts, 84 ::std::size_t nNumLoops, 85 CycleMode eCycleMode ); 86 87 virtual void dispose(); 88 virtual double calcTimeLag() const; 89 virtual bool perform(); 90 virtual bool isActive() const; 91 virtual void dequeued(); 92 virtual void end(); 93 94 bool enableAnimations(); 95 96 private: 97 SlideShowContext maContext; 98 boost::weak_ptr<DrawShape> mpDrawShape; 99 WakeupEventSharedPtr mpWakeupEvent; 100 IntrinsicAnimationEventHandlerSharedPtr mpListener; 101 ::std::vector<double> maTimeouts; 102 CycleMode meCycleMode; 103 ::std::size_t mnCurrIndex; 104 ::std::size_t mnNumLoops; 105 ::std::size_t mnLoopCount; 106 bool mbIsActive; 107 }; 108 109 ////////////////////////////////////////////////////////////////////// 110 111 class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler, 112 private boost::noncopyable 113 { 114 public: 115 explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) : 116 mrActivity( rActivity ) 117 {} 118 119 private: 120 121 virtual bool enableAnimations() { return mrActivity.enableAnimations(); } 122 virtual bool disableAnimations() { mrActivity.end(); return true; } 123 124 IntrinsicAnimationActivity& mrActivity; 125 }; 126 127 ////////////////////////////////////////////////////////////////////// 128 129 IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& rContext, 130 const DrawShapeSharedPtr& rDrawShape, 131 const WakeupEventSharedPtr& rWakeupEvent, 132 const ::std::vector<double>& rTimeouts, 133 ::std::size_t nNumLoops, 134 CycleMode eCycleMode ) : 135 maContext( rContext ), 136 mpDrawShape( rDrawShape ), 137 mpWakeupEvent( rWakeupEvent ), 138 mpListener( new IntrinsicAnimationListener(*this) ), 139 maTimeouts( rTimeouts ), 140 meCycleMode( eCycleMode ), 141 mnCurrIndex(0), 142 mnNumLoops(nNumLoops), 143 mnLoopCount(0), 144 mbIsActive(false) 145 { 146 ENSURE_OR_THROW( rContext.mpSubsettableShapeManager, 147 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" ); 148 ENSURE_OR_THROW( rDrawShape, 149 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" ); 150 ENSURE_OR_THROW( rWakeupEvent, 151 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" ); 152 ENSURE_OR_THROW( !rTimeouts.empty(), 153 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" ); 154 155 maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler( 156 mpListener ); 157 } 158 159 void IntrinsicAnimationActivity::dispose() 160 { 161 end(); 162 163 if( mpWakeupEvent ) 164 mpWakeupEvent->dispose(); 165 166 maContext.dispose(); 167 mpDrawShape.reset(); 168 mpWakeupEvent.reset(); 169 maTimeouts.clear(); 170 mnCurrIndex = 0; 171 172 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler( 173 mpListener ); 174 } 175 176 double IntrinsicAnimationActivity::calcTimeLag() const 177 { 178 return 0.0; 179 } 180 181 bool IntrinsicAnimationActivity::perform() 182 { 183 if( !isActive() ) 184 return false; 185 186 DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() ); 187 if( !pDrawShape || !mpWakeupEvent ) 188 { 189 // event or draw shape vanished, no sense living on -> 190 // commit suicide. 191 dispose(); 192 return false; 193 } 194 195 // mnNumLoops == 0 means infinite looping 196 if( mnNumLoops != 0 && 197 mnLoopCount >= mnNumLoops ) 198 { 199 // #i55294# After finishing the loops, display the first frame 200 pDrawShape->setIntrinsicAnimationFrame( 0 ); 201 maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape ); 202 203 end(); 204 205 return false; 206 } 207 208 ::std::size_t nNewIndex = 0; 209 const ::std::size_t nNumFrames(maTimeouts.size()); 210 switch( meCycleMode ) 211 { 212 case CYCLE_LOOP: 213 { 214 pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex ); 215 216 mpWakeupEvent->start(); 217 mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] ); 218 219 mnLoopCount += (mnCurrIndex + 1) / nNumFrames; 220 nNewIndex = (mnCurrIndex + 1) % nNumFrames; 221 break; 222 } 223 224 case CYCLE_PINGPONGLOOP: 225 { 226 ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ? 227 mnCurrIndex : 228 2*nNumFrames - mnCurrIndex - 1 ); 229 pDrawShape->setIntrinsicAnimationFrame( nTrueIndex ); 230 231 mpWakeupEvent->start(); 232 mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] ); 233 234 mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames); 235 nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames; 236 break; 237 } 238 } 239 240 maContext.mrEventQueue.addEvent( mpWakeupEvent ); 241 maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape ); 242 mnCurrIndex = nNewIndex; 243 244 return false; // don't reinsert, WakeupEvent will perform 245 // that after the given timeout 246 } 247 248 bool IntrinsicAnimationActivity::isActive() const 249 { 250 return mbIsActive; 251 } 252 253 void IntrinsicAnimationActivity::dequeued() 254 { 255 // not used here 256 } 257 258 void IntrinsicAnimationActivity::end() 259 { 260 // there is no dedicated end state, just become inactive: 261 mbIsActive = false; 262 } 263 264 bool IntrinsicAnimationActivity::enableAnimations() 265 { 266 mbIsActive = true; 267 return maContext.mrActivitiesQueue.addActivity( 268 shared_from_this() ); 269 } 270 271 ////////////////////////////////////////////////////////////////////// 272 273 ActivitySharedPtr createIntrinsicAnimationActivity( 274 const SlideShowContext& rContext, 275 const DrawShapeSharedPtr& rDrawShape, 276 const WakeupEventSharedPtr& rWakeupEvent, 277 const ::std::vector<double>& rTimeouts, 278 ::std::size_t nNumLoops, 279 CycleMode eCycleMode ) 280 { 281 return ActivitySharedPtr( 282 new IntrinsicAnimationActivity(rContext, 283 rDrawShape, 284 rWakeupEvent, 285 rTimeouts, 286 nNumLoops, 287 eCycleMode) ); 288 } 289 } 290 } 291