/* * Copyright 2008 (c) Lance Pollard * www.systemsofseven.com/blog * www.4ddesignlab.com * LanceJPollard@gmail.com * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package com.fourD.actions { import com.fourD.animators.IAnimator; import com.fourD.core.FourDComponent; import com.fourD.events.LayoutActionEvent; import com.fourD.layouts.FourDLayout; import flash.display.DisplayObject; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.MouseEvent; import mx.components.baseClasses.GroupBase; import com.fourD.core.SimpleZSorter; public class LayoutAction extends EventDispatcher { protected var token:Object; public var preferredLayoutElementWidth:Number; public var preferredLayoutElementHeight:Number; public var selectedIndex:int; public var selectedChild:DisplayObject; public const INTRO:String = "introLayoutAction"; public const AMBIENT:String = "ambientLayoutAction"; public const ITEM_SELECTED:String = "itemSelectedLayoutAction"; public const ITEM_DESELECTED:String = "itemDeselectedLayoutAction"; public const OUTRO:String = "outroLayoutAction"; [Bindable] public var mouseMoveEnabled:Boolean; [Inspectable(defaultValue="true", enumeration="true,false")] [Bindable] public var ambientActiveDuringItemSelection:Boolean = true; protected var introActionUsed:Boolean; protected var ambientActionUsed:Boolean; protected var itemSelectedActionUsed:Boolean; protected var itemDeselectedActionUsed:Boolean; protected var outroActionUsed:Boolean; protected var introActionActive:Boolean; protected var ambientActionActive:Boolean; protected var itemSelectedActionActive:Boolean; protected var itemDeselectedActionActive:Boolean; protected var outroActionActive:Boolean; private var _activeActions:Array; [Bindable] public function get activeActions():Array { return _activeActions; } public function set activeActions(value:Array):void { _activeActions = value; } private var _usedActions:Array; [Bindable] public function get usedActions():Array { return _usedActions; } public function set usedActions(value:Array):void { _usedActions = value; attachActionHandlers(); } private var _layout:FourDLayout; [Bindable] public function get layout():FourDLayout { return _layout; } public function set layout(value:FourDLayout):void { _layout = value; } private var _animator:IAnimator; [Bindable] public function get animator():IAnimator { return _animator; } public function set animator(value:IAnimator):void { _animator = value; } private var _target:GroupBase; [Bindable] public function get target():GroupBase { return _target; } public function set target(value:GroupBase):void { _target = value; } private var _container:FourDComponent; [Bindable] public function get container():FourDComponent { return _container; } public function set container(value:FourDComponent):void { _container = value; } public function LayoutAction() { } private function attachActionHandlers():void { var i:int=0; var len:int = usedActions.length; for (i; i < len; i++) { if (usedActions[i] == INTRO) { introActionUsed = true; this.addEventListener(LayoutActionEvent.INTRO_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.INTRO_END, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.INTRO_COMPLETE, handleLayoutActionEvents); } if (usedActions[i] == AMBIENT) { ambientActionUsed = true; this.addEventListener(LayoutActionEvent.AMBIENT_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.AMBIENT_END, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.AMBIENT_COMPLETE, handleLayoutActionEvents); } if (usedActions[i] == ITEM_SELECTED) { itemSelectedActionUsed = true; this.addEventListener(LayoutActionEvent.ITEM_SELECTED_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.ITEM_SELECTED_END, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.ITEM_SELECTED_COMPLETE, handleLayoutActionEvents); } if (usedActions[i] == ITEM_DESELECTED) { itemDeselectedActionUsed = true; this.addEventListener(LayoutActionEvent.ITEM_DESELECTED_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.ITEM_DESELECTED_END, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.ITEM_DESELECTED_COMPLETE, handleLayoutActionEvents); } if (usedActions[i] == OUTRO) { outroActionUsed = true; this.addEventListener(LayoutActionEvent.OUTRO_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.OUTRO_END, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.OUTRO_COMPLETE, handleLayoutActionEvents); } } this.addEventListener(LayoutActionEvent.LAYOUT_START, handleLayoutActionEvents); this.addEventListener(LayoutActionEvent.LAYOUT_COMPLETE, handleLayoutActionEvents); } protected function handleLayoutActionEvents(event:LayoutActionEvent):void { var eventType:String = event.type; // The layoutComplete event is dispatched at the end of the first pass of // layout.updateDisplayList(w, h). It allows you to start your action animation cycle. if (eventType == LayoutActionEvent.LAYOUT_START) { if (INTRO) { introStart(); } else { layoutStart(); } } if (eventType == LayoutActionEvent.LAYOUT_COMPLETE) { dispatchLayoutActionEvent(LayoutActionEvent.INTRO_START); } // Intro events if (eventType == LayoutActionEvent.INTRO_START) { introActionActive = true; introStart(); } if (eventType == LayoutActionEvent.INTRO_END) { introEnd(); } if (eventType == LayoutActionEvent.INTRO_COMPLETE) { introActionActive = false; dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_START); } // Ambient events if (eventType == LayoutActionEvent.AMBIENT_START) { ambientActionActive = true; ambientStart(); } if (eventType == LayoutActionEvent.AMBIENT_END) { ambientActionActive = true; ambientEnd(); } if (eventType == LayoutActionEvent.AMBIENT_COMPLETE) { ambientActionActive = false; if (itemSelectedActionActive) { // could redispatch the event, but that might be expensive // so instead we'll just hardwire all the methods throughout for now. // dispatchLayoutActionEvent(LayoutActionEvent.INTRO_START); itemSelectedStart(); } else if (outroActionActive) { outroStart(); } else { itemSelectedStart(); } } // Item selected events if (eventType == LayoutActionEvent.ITEM_SELECTED_START) { itemSelectedActionActive = true; if (ambientActionActive) { if (ambientActiveDuringItemSelection) { itemSelectedStart(); } else { dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_END); } } else if (introActionActive) { dispatchLayoutActionEvent(LayoutActionEvent.INTRO_END); } else { itemSelectedStart(); } } if (eventType == LayoutActionEvent.ITEM_SELECTED_END) { itemSelectedEnd(); } if (eventType == LayoutActionEvent.ITEM_SELECTED_COMPLETE) { itemSelectedActionActive = false; if (itemDeselectedActionUsed) { target.stage.addEventListener(MouseEvent.CLICK, itemDeselected); } else { dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_START); } } // Item deselected events if (eventType == LayoutActionEvent.ITEM_DESELECTED_START) { itemDeselectedActionActive = true; itemDeselectedStart(); } if (eventType == LayoutActionEvent.ITEM_DESELECTED_END) { itemDeselectedEnd(); } if (eventType == LayoutActionEvent.ITEM_DESELECTED_COMPLETE) { itemDeselectedActionActive = false; dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_START); } // Outro events if (eventType == LayoutActionEvent.OUTRO_START) { outroActionActive = true; outroStart(); } if (eventType == LayoutActionEvent.OUTRO_END) { outroEnd(); } if (eventType == LayoutActionEvent.OUTRO_COMPLETE) { outroActionActive = false; } } /** LAYOUT */ // sets the initial position and alpha of the components in your layout // then figures out if there's an intro or not, and if not, to just lay // the items out public function layoutStart():void { dispatchLayoutActionEvent(LayoutActionEvent.LAYOUT_START); } protected function layoutComplete(event:Event=null):void { } /** INTRO */ public function intro():void { dispatchLayoutActionEvent(LayoutActionEvent.INTRO_START); } protected function introStart():void { } // introEnd is only called if you interrupt the intro with a click or something. // by default, clicking does nothing to the intro, but if you want to be crazy, // override this method. protected function introEnd():void { } protected function introComplete():void { dispatchLayoutActionEvent(LayoutActionEvent.INTRO_COMPLETE); } /** AMBIENT */ public function ambient():void { dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_START); } protected function ambientStart():void { } protected function ambientUpdate(event:Event):void { } protected function ambientEnd():void { } protected function ambientComplete():void { dispatchLayoutActionEvent(LayoutActionEvent.AMBIENT_COMPLETE); } /** ITEM_SELECTED */ public function itemSelected():void { dispatchLayoutActionEvent(LayoutActionEvent.ITEM_SELECTED_START); } protected function itemSelectedStart():void { } protected function itemSelectedEnd():void { } protected function itemSelectedComplete():void { dispatchLayoutActionEvent(LayoutActionEvent.ITEM_SELECTED_COMPLETE); } /** ITEM_DESELECTED */ public function itemDeselected(event:MouseEvent=null):void { dispatchLayoutActionEvent(LayoutActionEvent.ITEM_DESELECTED_START); } protected function itemDeselectedStart():void { } protected function itemDeselectedEnd():void { } protected function itemDeselectedComplete():void { dispatchLayoutActionEvent(LayoutActionEvent.ITEM_DESELECTED_COMPLETE); } /** OUTRO */ public function outro():void { dispatchLayoutActionEvent(LayoutActionEvent.OUTRO_START); } protected function outroStart():void { } protected function outroEnd():void { } protected function outroComplete():void { dispatchLayoutActionEvent(LayoutActionEvent.OUTRO_COMPLETE); } /** Dispatch events to continue animation cycle */ protected function dispatchLayoutActionEvent(eventType:String):void { var event:LayoutActionEvent = new LayoutActionEvent(eventType); this.dispatchEvent(event); } } }