package com.rubenswieringa.containers { import flash.display.DisplayObject; import flash.display.Shape; import mx.containers.Canvas; import mx.core.Container; import flash.events.Event; import mx.events.FlexEvent; import mx.events.IndexChangedEvent; // event declarations: /** * Dispatched when the selected child Container changes. * * @eventType mx.events.IndexChangedEvent.CHANGE */ [Event(name="change", type="mx.events.IndexChangedEvent")] /** * lib_flex_book_com_rubenswieringa_containers_SuperViewStack in many ways behaves like the classic ViewStack. * Additional features are reversed indexing (0=top, N=bottom) and fading of children. * * @author Ruben Swieringa * ruben.swieringa@gmail.com * www.rubenswieringa.com * @version 1.0.3 * @see mx.containers.ViewStack * * * edit 3 * * Before modifying and/or redistributing this class, please contact Ruben Swieringa (ruben.swieringa@gmail.com) * * * View code documentation at: * http://www.rubenswieringa.com/code/as3/flex/lib_flex_book_com_rubenswieringa_containers_SuperViewStack/docs/ * */ public class lib_flex_book_com_rubenswieringa_containers_SuperViewStack extends Canvas { // status variables: /** * @private */ protected var _childrenCreated:Boolean = false; // internals for accessors: /** * @private */ protected var _selectedIndex:int = -1; /** * @private */ protected var __fade:Array = [lib_flex_book_com_rubenswieringa_containers_SuperViewStack.DEFAULT_FADE, 1.0]; /** * @private */ protected var _fadeColor:uint = lib_flex_book_com_rubenswieringa_containers_SuperViewStack.DEFAULT_FADECOLOR; // constants: /** * Name of the Shape that is used to simulate fading of Containers. */ public static const FADESHAPE_NAME:String = "superviewstackfade"; /** * Event type for the Event that is dispatched when the selected child Container changes. * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#behavior */ public static const BEHAVIOR_CHANGED:String = "Behavior of lib_flex_book_com_rubenswieringa_containers_SuperViewStack changed"; /** * Full-feature lib_flex_book_com_rubenswieringa_containers_SuperViewStack behavior mode * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#behavior */ public static const SUPER:String = "lib_flex_book_com_rubenswieringa_containers_SuperViewStack"; /** * Normal behavior mode, simulating the behavior of the classic ViewStack * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#behavior * @see mx.containers.ViewStack */ public static const NORMAL:String = "ViewStack"; /** * @private */ protected static const DEFAULT_FADE:Number = 0.6; /** * @private */ protected static const DEFAULT_FADECOLOR:uint = 0xFFFFFF; // CONSTRUCTOR: /** * Constructor. */ public function lib_flex_book_com_rubenswieringa_containers_SuperViewStack ():void { super(); // set creationPolicy so that all children will be created from the start off: this.creationPolicy = "all"; } // OVERRIDES: /** * @see mx.containers.ViewStack#childrenCreated() * * @private */ override protected function childrenCreated ():void { super.childrenCreated(); this._childrenCreated = true; if (this._selectedIndex == -1){ this.selectedIndex = 0; } this.showChildren(); } /** * @see mx.containers.ViewStack#updateDisplayList() * * @private */ override protected function updateDisplayList (unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); this.showChildren(); for (var i:uint=0; i this.selectedIndex) this._selectedIndex++; }else{ if (index > this.selectedIndex) this._selectedIndex++; } this.applyFade(); this.showChildren(); } // return child: return child; } /** * Event handler for the creationComplete event of an added child, calls resizeFade(). * * @param event . * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#resizeFade() * * @private */ protected function childCreationComplete (event:FlexEvent):void { this.resizeFade(event.target as Container); } /** * Returns the child display object instance that exists at the specified index. * * @param index The index position of the child object. * * @return The child display object at the specified index position. * * @see mx.containers.ViewStack#getChildAt() */ override public function getChildAt (index:int):DisplayObject { return super.getChildAt(this.reverseIndex(index)); } /** * Returns the index position of a child DisplayObject instance. * * @param child The DisplayObject instance to identify. * * @return The index position of the child display object to identify. * * @see mx.containers.ViewStack#getChildIndex() */ override public function getChildIndex (child:DisplayObject):int { return this.reverseIndex(super.getChildIndex(child)); } /** * Removes a child DisplayObject from the specified index position in the child list of the DisplayObjectContainer. * * @param index The child index of the DisplayObject to remove. * * @return The DisplayObject instance that was removed. * * @see mx.containers.ViewStack#removeChildAt() */ override public function removeChildAt (index:int):DisplayObject { this.unregisterChildAt(index); return super.removeChildAt(this.reverseIndex(index)); } /** * Removes a child DisplayObject from the child list of this Container. * * @param child The DisplayObject to remove. * * @return The DisplayObject instance that was removed. * * @see mx.containers.ViewStack#removeChild() */ override public function removeChild (child:DisplayObject):DisplayObject { this.unregisterChildAt(this.getChildIndex(child)); return super.removeChild(child); } /** * Clears a child to be removed of event listeners added by this class and refreshes visuals. * * @param index The index of the DisplayObject to be removed. * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#removeChild() * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#removeChildAt() * * @private */ protected function unregisterChildAt (index:int):void { var child:DisplayObject = this.getChildAt(index); child.removeEventListener(FlexEvent.CREATION_COMPLETE, this.childCreationComplete); if (this._childrenCreated){ if (index < this.selectedIndex) this._selectedIndex--; this.applyFade(); this.showChildren(); } } /** * Changes the position of an existing child in the display object container. * * @param child The child DisplayObject instance for which you want to change the index number. * @param index The resulting index number for the child display object. * * @see mx.containers.ViewStack#setChildIndex() */ override public function setChildIndex(child:DisplayObject, index:int):void { super.setChildIndex(child, this.reverseIndex(index)); } /** * Swaps the z-order (front-to-back order) of the child objects at the two specified index positions in the child list. * * @param index1 The index position of the first child object. * @param index2 The index position of the second child object. * * @see mx.containers.ViewStack#swapChildrenAt() */ override public function swapChildrenAt (index1:int, index2:int):void { index1 = this.reverseIndex(index1); index2 = this.reverseIndex(index2); super.swapChildrenAt(index1, index2); } /** * Removes all children from the child list of this container. * * @see mx.containers.ViewStack#removeAllChildren() */ override public function removeAllChildren ():void { super.removeAllChildren(); this._selectedIndex = -1; } // CUSTOM: /** * Set visibility to true for the children underneath selectedChild (and selectedChild itself), false for the rest. * * @private */ protected function showChildren ():void { for (var i:uint=0; i this.numChildren-1) value = this.numChildren-1; // reverse value: value = this.reverseIndex(value); // return if there is no change: if (this._selectedIndex == value) return; // set internal and refresh children: this._selectedIndex = value; this.showChildren(); // store new value and dispatch event: event.newIndex = this.selectedIndex; event.relatedObject = this.selectedChild; dispatchEvent(event); } /** * A reference to the currently visible child container. * * @copy mx.containers.ViewStack#selectedChild * @see mx.containers.ViewStack#selectedChild */ public function get selectedChild ():Container { return super.getChildAt(this._selectedIndex) as Container; } public function set selectedChild (child:Container):void { this.selectedIndex = this.getChildIndex(child); } /** * Degree to which a child should be faded if it's underneath another visible child. * Values range from 0.0 (completely transparent) to 1.0 (no transparency), defaults to 0.6. */ public function get fade ():Number { return this._fade; } public function set fade (value:Number):void { // make sure value is within bounds: if (value < 0) value = 0; if (value > 1) value = 1; // return if there is no change: if (this._fade == value) return; // switch back to lib_flex_book_com_rubenswieringa_containers_SuperViewStack behavior (if necessary): this.behavior = lib_flex_book_com_rubenswieringa_containers_SuperViewStack.SUPER; // set internal and refresh children: this._fade = value; this.showChildren(); } /** * First value in __fade (Array), indicating the transparency of fades * * @private */ protected function get _fade ():Number { return this.__fade[0]; } /** * @private */ protected function set _fade (value:Number):void { this.__fade[0] = value; } /** * Color with which to fade a child, defaults to white (0xFFFFFF). */ public function get fadeColor ():uint { return this._fadeColor; } public function set fadeColor (value:uint):void { // switch back to lib_flex_book_com_rubenswieringa_containers_SuperViewStack behavior (if necessary): this.behavior = lib_flex_book_com_rubenswieringa_containers_SuperViewStack.SUPER; // set internal and refresh children: this._fadeColor = value; this.applyFade(); } /** * Behavior of this lib_flex_book_com_rubenswieringa_containers_SuperViewStack. Can be adjusted during runtime. * Values can be either lib_flex_book_com_rubenswieringa_containers_SuperViewStack.SUPER or lib_flex_book_com_rubenswieringa_containers_SuperViewStack.NORMAL. * If normal, the lib_flex_book_com_rubenswieringa_containers_SuperViewStack will act like the classic ViewStack. * * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#BEHAVIOR_CHANGED * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#SUPER * @see lib_flex_book_com_rubenswieringa_containers_SuperViewStack#NORMAL */ public function get behavior ():String { if (this._fade == 1.0){ return lib_flex_book_com_rubenswieringa_containers_SuperViewStack.NORMAL; }else{ return lib_flex_book_com_rubenswieringa_containers_SuperViewStack.SUPER; } } public function set behavior (value:String):void { if (value == this.behavior || (value != lib_flex_book_com_rubenswieringa_containers_SuperViewStack.SUPER && value != lib_flex_book_com_rubenswieringa_containers_SuperViewStack.NORMAL)){ return; } this.__fade.reverse(); this.showChildren(); this.dispatchEvent(new Event(lib_flex_book_com_rubenswieringa_containers_SuperViewStack.BEHAVIOR_CHANGED)); } } }