/** * Web App Solution Confidential Information * Copyright 2010, Web App Solution, Inc. * * @date Aug, 5, 2010 */ package com.webappsolution.swiz.mediator { import com.webappsolution.logging.LoggingUtils; import flash.display.DisplayObject; import flash.events.Event; import flash.events.IEventDispatcher; import mx.core.IFlexDisplayObject; import mx.core.IFlexModuleFactory; import mx.core.UIComponent; import mx.events.FlexEvent; import mx.logging.ILogger; import mx.logging.Log; import mx.managers.PopUpManager; import org.swizframework.core.ISwiz; import org.swizframework.core.ISwizAware; /** * The base class for all view mediators. It's most useful function is to * provide the metadata and setter method to inject the corresponding view into * the mediator. * *

* In addition, it allows concrete View Mediators to add view event handlers * and data bindings to children of the corresponding View with confidence by * by determining if the view is "alive" (aka has been instantiated and added to * the stage -- creationComplete event fired) or if it needs to listen for it's * creation complete event before performing actions on it. See the * public function setView( value:* ):void method for more * details on this. *

*/ public class AbstractViewMediator implements ISwizAware { /** * Logger. */ private static const logger:ILogger = Log.getLogger(LoggingUtils.getFullyQualifiedClassName(AbstractViewMediator)); /** * A flag indicating if the correpsonding view's creation complete has fired. */ public var isViewCreationComplete:Boolean = false; /** * The view class we're injecting into the view mediator. */ protected var viewType:Class; /** * The view that corresponds to this view mediator. */ protected var _view:UIComponent; /** * Constructor. */ public function AbstractViewMediator(viewType:Class) { super(); logger.debug("Constructor"); this.viewType = viewType; } /** * Allows this class to dispatch events. The event dispatcher is * injected by Swiz due to the [Dispatcher] metadata and the class * memeber's type of IEventDispatcher. */ [Dispatcher] public var dispatcher:IEventDispatcher; /** * Creates a reference to the instance of Swiz this bean is in. This * allows us to get a hold of manager beans by using: * var vm:MyViewMediator = swiz.beanFactory.getBeanByName("myViewMediator").source as MyViewMediator; */ public function set swiz(swiz:ISwiz):void { this._swiz = swiz; } public function get swiz():ISwiz { return this._swiz; } protected var _swiz:ISwiz; /** * Listen for views added to the stage and determine if it's the corresponding * View for this View Mediator. This check is done by looking at the view added * to the stage and do a simple compare on the viewType:Class class * member that we set in concrete View Medators via their constructors. * *

* Also determine if the View has fired its creation complete event so developers * can perform actions on the view from the View Mediator without hitting null pointers * for uninstantiated objects in the View. If the creation complete has not fired, then * listen for it. *

*/ [Mediate( "flash.events.Event.ADDED_TO_STAGE", properties="target", useCapture="true" )] public function setView(value:*):void { if(value is viewType) { logger.debug("AUTOWIRE :: view = " + value); this._view = value; // determine if the view has been initialized... // NO...listen for it;s creation complete event if(this._view.initialized == false) { this._view.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete); } // YES...call the init() method to kick off the instation of the view mediator else { this.isViewCreationComplete = true; this.init(); } // don't get in GC's way if the view is removed this._view.addEventListener(Event.REMOVED_FROM_STAGE, cleanup); } else { // logger.warn("Don't inject the view " + value); } } /** * Helper method that returns a view mediator managed by Swiz by it's ID. * * @param id The unique ID for the view mediator as defined in the BeanLoader. */ public function getViewMediatorBeanById(id:String):AbstractViewMediator { logger.debug("getViewMediatorBeanById"); var vm:AbstractViewMediator = this.swiz.beanFactory.getBeanByName(id).source as AbstractViewMediator; return vm; } /** * Helper method that returns a view mediator managed by Swiz by it's ID. * * @param clazz The class type for our view mediator. */ public function getViewMediatorBeanByType(clazz:Class):AbstractViewMediator { logger.debug("getViewMediatorBeanByType"); var vm:AbstractViewMediator = this.swiz.beanFactory.getBeanByType(clazz).source as AbstractViewMediator; return vm; } /** * This method is a workaround for wiring up popup views and their corresponding view * mediators. Normally, views are added to the display list, but popups are actually * added to the SystemManager so they don't fire off the "flash.events.Event.ADDED_TO_STAGE" * event that's mediated in the setView() method...that's the core piece of logic behind the * entire AbtractViewMediator. * *

* Simply call the method createPopupView(...) and * a popup view and it's corresponding view mediator will work as expected. *

*/ public function createPopupView( view:IFlexDisplayObject, parent:DisplayObject, modal:Boolean = false, childList:String = null, moduleFactory:IFlexModuleFactory = null ):IFlexDisplayObject { logger.debug("createPopupView"); this.setView(view); PopUpManager.addPopUp(view, parent, true); // window:IFlexDisplayObject,parent:DisplayObject,modal:Boolean = false,childList:String = null,moduleFactory:IFlexModuleFactory = null PopUpManager.centerPopUp(view); return view; } /** * The init() method is only called when the ViewMediator's corresponding * View's creationComplete has been fired; this allows developers to add event listens, * data bindings, and any other view functions in confidence (without worry about accessing * children of the view that are null and cause runtime errors.) * *

* Developers can override this to perform additional initializaitons in their ViewMediator, * but must call super.init() in order for the aforementioned to function * correctly. *

* *

* Does not have to be overriden. Simply here for convenience and as a marker method. *

*/ protected function init():void { logger.debug("init"); this.setViewListeners(); this.setViewDataBindings(); } /** * Set the listeners for the UI components on the stage for the ViewMediator's corresponding View. * *

* Does not have to be overriden. Simply here for convenience and as a marker method. *

*/ protected function setViewListeners():void { logger.debug("setViewListeners"); // OVERRIDDEN } /** * Set the data bindings for the UI components on the stage for the ViewMediator's corresponding View. * *

* Does not have to be overriden. Simply here for convenience and as a marker method. *

*/ protected function setViewDataBindings():void { logger.debug("setViewDataBindings"); // OVERRIDDEN } /** * Listen for the creation complete of the View for this ViewMediator. */ protected function onCreationComplete( event:FlexEvent ):void { logger.debug("onCreationComplete"); this.isViewCreationComplete = true; this._view.removeEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete); this.init(); } /** * Remove any listeners we've created. * *

* Developers should override this method to remove any custom listners * created in the concrete ViewMediator. Developers must call * super.cleanup() in order for this to function correctly. *

*/ protected function cleanup( event:Event ):void { logger.debug("cleanup"); this._view.removeEventListener(Event.REMOVED_FROM_STAGE, cleanup); } } }