1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2010 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package spark.transitions 13{ 14 15import flash.display.BlendMode; 16import flash.display.DisplayObjectContainer; 17import flash.events.Event; 18import flash.geom.Point; 19 20import mx.core.UIComponent; 21import mx.core.mx_internal; 22import mx.effects.Fade; 23import mx.effects.IEffect; 24import mx.effects.Parallel; 25 26import spark.components.Group; 27import spark.effects.Scale; 28import spark.primitives.BitmapImage; 29 30use namespace mx_internal; 31 32/** 33 * The ZoomViewTransition class performs a zoom in or out transition for views. 34 * It performs its transition by zooming out the existing view to reveal 35 * the new view, or by zooming in the new view to cover the existing view. 36 * 37 * <p>The default duration of a ZoomViewTransition is 350ms. 38 * Also, by default it transitions the control bar and view content 39 * as one as if <code>transitionControlsWithContent</code> is <code>true</code>. </p> 40 * 41 * <p><strong>Note:</strong>Create and configure view transitions in ActionScript; 42 * you cannot create them in MXML.</p> 43 * 44 * @see ZoomViewTransitionMode 45 * 46 * @langversion 3.0 47 * @playerversion AIR 2.5 48 * @productversion Flex 4.5 49 */ 50[Deprecated(since="4.6")] 51public class ZoomViewTransition extends ViewTransitionBase 52{ 53 //-------------------------------------------------------------------------- 54 // 55 // Constructor 56 // 57 //-------------------------------------------------------------------------- 58 59 /** 60 * Constructor. 61 * 62 * @langversion 3.0 63 * @playerversion AIR 2.5 64 * @productversion Flex 4.5 65 */ 66 public function ZoomViewTransition() 67 { 68 super(); 69 70 // Default duration of 350 yields a smoother result. 71 duration = 350; 72 73 // Default to transitioning control bars with our views. 74 transitionControlsWithContent = true; 75 } 76 77 //-------------------------------------------------------------------------- 78 // 79 // Variables 80 // 81 //-------------------------------------------------------------------------- 82 83 /** 84 * @private 85 * Property bag used to save any start view properties that 86 * are then restored after the transition is complete. 87 */ 88 private var startViewProps:Object; 89 90 /** 91 * @private 92 * Property bag used to save any end view properties that 93 * are then restored after the transition is complete. 94 */ 95 private var endViewProps:Object; 96 97 /** 98 * @private 99 */ 100 private var transitionGroup:Group; 101 102 /** 103 * @private 104 */ 105 private var savedCacheAsBitmap:Boolean; 106 107 /** 108 * @private 109 */ 110 private var scaleEffect:Scale; 111 112 /** 113 * @private 114 */ 115 private var targetSnapshot:BitmapImage; 116 117 /** 118 * @private 119 * Stores the location of the cached navigator in the global coordinate space 120 * so that the transition can properly position it when added to the display list. 121 */ 122 private var targetSnapshotGlobalPosition:Point = new Point(); 123 124 /** 125 * @private 126 */ 127 private var cachedNavigatorGroup:Group; 128 129 //-------------------------------------------------------------------------- 130 // 131 // Properties 132 // 133 //-------------------------------------------------------------------------- 134 135 //--------------------------------- 136 // minimumScale 137 //--------------------------------- 138 139 private var _minimumScale:Number = .25; 140 141 /** 142 * Specifies the minimum scale of the zoomed view (represents when the 143 * view is first visible when zooming in or last visible when zooming 144 * out). 145 * 146 * @default .25 147 * 148 * @langversion 3.0 149 * @playerversion AIR 2.5 150 * @productversion Flex 4.5 151 */ 152 public function get minimumScale():Number 153 { 154 return _minimumScale; 155 } 156 157 /** 158 * @private 159 */ 160 public function set minimumScale(value:Number):void 161 { 162 _minimumScale = value; 163 } 164 165 //--------------------------------- 166 // mode 167 //--------------------------------- 168 169 private var _mode:String = "out"; // avoid deprecation warning for ZoomViewTransitionMode.OUT; 170 171 [Inspectable(category="General", enumeration="in,out", defaultValue="out")] 172 /** 173 * Specifies the type of zoom transition to perform. 174 * 175 * @default ZoomTransitionMode.OUT 176 * 177 * @langversion 3.0 178 * @playerversion AIR 2.5 179 * @productversion Flex 4.5 180 */ 181 public function get mode():String 182 { 183 return _mode; 184 } 185 186 /** 187 * @private 188 */ 189 public function set mode(value:String):void 190 { 191 _mode = value; 192 } 193 194 //-------------------------------------------------------------------------- 195 // 196 // Methods 197 // 198 //-------------------------------------------------------------------------- 199 200 /** 201 * @private 202 * 203 * @langversion 3.0 204 * @playerversion AIR 2.5 205 * @productversion Flex 4.5 206 */ 207 override public function captureStartValues():void 208 { 209 // Suppress the default action bar transition, not really 210 // appropriate for the zoom. 211 actionBarTransitionMode = ViewTransitionBase.ACTION_BAR_MODE_NONE; 212 213 super.captureStartValues(); 214 215 var oldVisibility:Boolean = endView.visible; 216 endView.visible = false; 217 cachedNavigator = getSnapshot(targetNavigator, 0, cachedNavigatorGlobalPosition); 218 endView.visible = oldVisibility; 219 } 220 221 /** 222 * @private 223 * 224 * @langversion 3.0 225 * @playerversion AIR 2.5 226 * @productversion Flex 4.5 227 */ 228 override public function captureEndValues():void 229 { 230 super.captureEndValues(); 231 232 // Set targetSnapshot to the snapshot that we will be 233 // transitioning in or out. 234 if (consolidatedTransition) 235 { 236 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 237 { 238 targetSnapshot = cachedNavigator; 239 targetSnapshotGlobalPosition = cachedNavigationGroupGlobalPosition.clone(); 240 } 241 else 242 { 243 targetSnapshot = getSnapshot(targetNavigator.skin, 0, targetSnapshotGlobalPosition); 244 } 245 } 246 else 247 { 248 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 249 { 250 targetSnapshot = getSnapshot(startView, 0, targetSnapshotGlobalPosition); 251 } 252 else 253 { 254 targetSnapshot = getSnapshot(endView, 0, targetSnapshotGlobalPosition); 255 } 256 } 257 } 258 259 /** 260 * @private 261 * 262 * @langversion 3.0 263 * @playerversion AIR 2.5 264 * @productversion Flex 4.5 265 */ 266 override protected function createViewEffect():IEffect 267 { 268 // Add a group to contain targetSnapshot. 269 transitionGroup = new Group(); 270 transitionGroup.includeInLayout = false; 271 addComponentToContainer(transitionGroup, DisplayObjectContainer(navigator) as UIComponent); 272 273 // Disable layout and visibility of our start view as necessary 274 if (startView) 275 { 276 startViewProps = {includeInLayout:startView.includeInLayout, 277 visible:startView.visible}; 278 startView.includeInLayout = false; 279 280 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 281 startView.visible = false; 282 } 283 284 // Disable layout and visibility of our start end as necessary 285 if (endView) 286 { 287 endViewProps = {includeInLayout:endView.includeInLayout, 288 visible:endView.visible}; 289 endView.includeInLayout = false; 290 291 if (mode == "in") // avoid deprecation warning for ZoomViewTransitionMode.IN 292 endView.visible = false; 293 } 294 295 if (targetSnapshot) 296 addCachedElementToGroup(transitionGroup, targetSnapshot, targetSnapshotGlobalPosition); 297 298 transitionGroup.validateNow(); 299 300 // Initialize our target's transform center. 301 transitionGroup.transformX = endView.width / 2; 302 transitionGroup.transformY = endView.height / 2; 303 304 // Ensure our alpha is initialized to 0 prior to the start 305 // of our transition so that the view isn't displayed briefly 306 // after validation. 307 if (mode == "in") // avoid deprecation warning for ZoomViewTransitionMode.IN 308 transitionGroup.alpha = 0; 309 310 // Set our blendMode to 'normal' for performance reasons. 311 transitionGroup.blendMode = BlendMode.NORMAL; 312 313 return createZoomEffect(transitionGroup); 314 } 315 316 /** 317 * @private 318 * 319 * @langversion 3.0 320 * @playerversion AIR 2.5 321 * @productversion Flex 4.5 322 */ 323 override protected function createConsolidatedEffect():IEffect 324 { 325 // If we have no cachedNavigator then there is not much we can do. 326 if (!cachedNavigator && mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 327 return null; 328 329 // Add a group to contain our snapshot view of the original navigator. 330 cachedNavigatorGroup = new Group(); 331 cachedNavigatorGroup.includeInLayout = false; 332 333 // On zoom out, place the cachedNavigator above the targetNavigator 334 var index:int = getComponentChildIndex(targetNavigator, targetNavigator.parent as UIComponent); 335 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 336 index++; 337 addComponentToContainerAt(cachedNavigatorGroup, DisplayObjectContainer(targetNavigator).parent as UIComponent, index); 338 339 cachedNavigator.includeInLayout = false; 340 addCachedElementToGroup(cachedNavigatorGroup, cachedNavigator, cachedNavigatorGlobalPosition); 341 342 // Add our temporary transition group to our target navigator's parent 343 // so we can make it and the original navigator siblings. 344 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 345 { 346 // We'll be zooming out our cachedNavigatorGroup. 347 transitionGroup = cachedNavigatorGroup; 348 } 349 else 350 { 351 transitionGroup = new Group(); 352 transitionGroup.includeInLayout = false; 353 354 // We'll be zooming in our snapshot of the new navigator. Host our 355 // snapshot and make sure it's rendered. 356 cachedNavigatorGroup.addElement(transitionGroup); 357 addCachedElementToGroup(transitionGroup, targetSnapshot, targetSnapshotGlobalPosition); 358 cachedNavigatorGroup.validateNow(); 359 360 // Hide our real navigator. 361 endViewProps = {visible:targetNavigator.skin.visible} 362 targetNavigator.skin.visible = false; 363 } 364 365 transitionGroup.validateNow(); 366 367 // Initialize our target's transform center. 368 transitionGroup.transformX = cachedNavigator.getLayoutBoundsWidth(true) / 2 + targetNavigator.getLayoutBoundsX(true); 369 transitionGroup.transformY = cachedNavigator.getLayoutBoundsHeight(true) / 2 + targetNavigator.getLayoutBoundsY(true); 370 371 // Ensure our alpha is initialized to 0 prior to the start 372 // of our transition so that the view isn't displayed briefly 373 // after validation. 374 if (mode == "in") // avoid deprecation warning for ZoomViewTransitionMode.IN 375 transitionGroup.alpha = 0; 376 377 // Set our blendMode to 'normal' for performance reasons. 378 transitionGroup.blendMode = BlendMode.NORMAL; 379 380 return createZoomEffect(transitionGroup); 381 } 382 383 /** 384 * @private 385 * 386 * @langversion 3.0 387 * @playerversion AIR 2.5 388 * @productversion Flex 4.5 389 */ 390 override protected function cleanUp():void 391 { 392 if (!consolidatedTransition) 393 { 394 if (startView) 395 { 396 startView.includeInLayout = startViewProps.includeInLayout; 397 startView.visible = startViewProps.visible; 398 } 399 400 if (endView) 401 { 402 endView.includeInLayout = endViewProps.includeInLayout; 403 endView.visible = endViewProps.visible;; 404 } 405 406 if (transitionGroup) 407 removeComponentFromContainer(transitionGroup, UIComponent(DisplayObjectContainer(navigator))); 408 } 409 else 410 { 411 if (cachedNavigatorGroup) 412 removeComponentFromContainer(cachedNavigatorGroup, UIComponent(DisplayObjectContainer(targetNavigator).parent)); 413 414 if (endViewProps) 415 targetNavigator.skin.visible = endViewProps.visible; 416 } 417 418 transitionGroup = null; 419 cachedNavigator = null; 420 cachedNavigatorGroup = null; 421 endViewProps = null; 422 startViewProps = null; 423 424 scaleEffect.removeEventListener("effectUpdate", scaleEffectUpdateHandler); 425 scaleEffect = null; 426 427 super.cleanUp(); 428 } 429 430 //-------------------------------------------------------------------------- 431 // 432 // Private Methods 433 // 434 //-------------------------------------------------------------------------- 435 436 /** 437 * @private 438 * Shared helper routine which serves as our effect factory for both standard 439 * and consolidated transitions. 440 */ 441 protected function createZoomEffect(zoomTarget:Object):IEffect 442 { 443 // This will be a composite control, initialized with the appropriate target 444 // depending on the transition mode (in/out). 445 var parallel:Parallel = new Parallel; 446 parallel.target = zoomTarget; 447 448 // Create fade effect to gradually fade our zoom target, we don't fade for the 449 // duration of the effect as this degrades overall transition performance, we 450 // simply fade near the point of first appearance or disappearance. 451 var fadeEffect:Fade = new Fade(); 452 fadeEffect.duration = (mode == "in") ? // avoid deprecation warning for ZoomViewTransitionMode.IN 453 duration * .4 : duration * .6; 454 if (mode == "out") // avoid deprecation warning for ZoomViewTransitionMode.OUT 455 fadeEffect.startDelay = duration * .4; 456 fadeEffect.alphaTo = (mode == "out") ? // avoid deprecation warning for ZoomViewTransitionMode.OUT 457 0 : 1; 458 fadeEffect.alphaFrom = (mode == "out") ? // avoid deprecation warning forZoomViewTransitionMode.OUT 459 1 : 0; 460 461 // Create scale effect to zoom in/our our target from or to our 462 // specified minimum scale. 463 scaleEffect = new Scale(); 464 scaleEffect.duration = duration; 465 scaleEffect.easer = easer; 466 scaleEffect.scaleXFrom = scaleEffect.scaleYFrom = 467 (mode == "out") ? // avoid deprecation warning for ZoomViewTransitionMode.OUT 468 1 : minimumScale; 469 scaleEffect.scaleXTo = scaleEffect.scaleYTo = 470 (mode == "out") ? // avoid deprecation warning for ZoomViewTransitionMode.OUT 471 minimumScale : 1; 472 scaleEffect.addEventListener("effectUpdate", scaleEffectUpdateHandler); 473 474 parallel.addChild(fadeEffect); 475 parallel.addChild(scaleEffect); 476 477 return parallel; 478 } 479 480 /** 481 * @private 482 * Ensures transform matrix is updated even if layout is disabled. 483 */ 484 private function scaleEffectUpdateHandler(e:Event):void 485 { 486 transitionGroup.validateDisplayList(); 487 } 488 489} 490} 491