| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.binding |
| { |
| |
| import flash.events.Event; |
| import flash.events.IEventDispatcher; |
| import mx.core.EventPriority; |
| import mx.core.mx_internal; |
| |
| use namespace mx_internal; |
| |
| [ExcludeClass] |
| |
| /** |
| * @private |
| */ |
| public class FunctionReturnWatcher extends Watcher |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Constructor. |
| */ |
| public function FunctionReturnWatcher(functionName:String, |
| document:Object, |
| parameterFunction:Function, |
| events:Object, |
| listeners:Array, |
| functionGetter:Function = null, |
| isStyle:Boolean = false) |
| { |
| super(listeners); |
| |
| this.functionName = functionName; |
| this.document = document; |
| this.parameterFunction = parameterFunction; |
| this.events = events; |
| this.functionGetter = functionGetter; |
| this.isStyle = isStyle; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * The name of the property, used to actually get the property |
| * and for comparison in propertyChanged events. |
| */ |
| private var functionName:String; |
| |
| /** |
| * @private |
| * The document is what we need to use to execute the parameter function. |
| */ |
| private var document:Object; |
| |
| /** |
| * @private |
| * The function that will give us the parameters for calling the function. |
| */ |
| private var parameterFunction:Function; |
| |
| /** |
| * @private |
| * The events that indicate the property has changed. |
| */ |
| private var events:Object; |
| |
| /** |
| * @private |
| * The parent object of this function. |
| */ |
| private var parentObj:Object; |
| |
| /** |
| * @private |
| * The watcher holding onto the parent object. |
| */ |
| public var parentWatcher:Watcher; |
| |
| /** |
| * Storage for the functionGetter property. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private var functionGetter:Function; |
| |
| /** |
| * Storage for the isStyle property. This will be true, when |
| * watching a function marked with [Bindable(style="true")]. For |
| * example, UIComponent.getStyle(). |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 4 |
| */ |
| private var isStyle:Boolean; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function updateParent(parent:Object):void |
| { |
| if (!(parent is Watcher)) |
| setupParentObj(parent); |
| |
| else if (parent == parentWatcher) |
| setupParentObj(parentWatcher.value); |
| |
| updateFunctionReturn(); |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function shallowClone():Watcher |
| { |
| var clone:FunctionReturnWatcher = new FunctionReturnWatcher(functionName, |
| document, |
| parameterFunction, |
| events, |
| listeners, |
| functionGetter); |
| |
| return clone; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Get the new return value of the function. |
| */ |
| public function updateFunctionReturn():void |
| { |
| wrapUpdate(function():void |
| { |
| if (functionGetter != null) |
| { |
| value = functionGetter(functionName).apply(parentObj, |
| parameterFunction.apply(document)); |
| } |
| else |
| { |
| value = parentObj[functionName].apply(parentObj, |
| parameterFunction.apply(document)); |
| } |
| |
| updateChildren(); |
| }); |
| } |
| |
| /** |
| * @private |
| */ |
| private function setupParentObj(newParent:Object):void |
| { |
| var eventDispatcher:IEventDispatcher; |
| var eventName:String; |
| |
| // Remove listeners from the old "watched" object. |
| if (parentObj != null && |
| parentObj is IEventDispatcher) |
| { |
| eventDispatcher = parentObj as IEventDispatcher; |
| |
| // events can be null when watching a function marked with |
| // [Bindable(style="true")]. |
| if (events != null) |
| { |
| for (eventName in events) |
| { |
| if (eventName != "__NoChangeEvent__") |
| { |
| eventDispatcher.removeEventListener(eventName, eventHandler); |
| } |
| } |
| } |
| |
| if (isStyle) |
| { |
| // For example, if the data binding expression is |
| // {getStyle("color")}, the eventName will be |
| // "colorChanged". |
| eventName = parameterFunction.apply(document) + "Changed"; |
| eventDispatcher.removeEventListener(eventName, eventHandler); |
| eventDispatcher.removeEventListener("allStylesChanged", eventHandler); |
| } |
| } |
| |
| parentObj = newParent; |
| |
| // Add listeners the new "watched" object. |
| if (parentObj != null && |
| parentObj is IEventDispatcher) |
| { |
| eventDispatcher = parentObj as IEventDispatcher; |
| |
| // events can be null when watching a function marked with |
| // [Bindable(style="true")]. |
| if (events != null) |
| { |
| for (eventName in events) |
| { |
| if (eventName != "__NoChangeEvent__") |
| { |
| eventDispatcher.addEventListener(eventName, eventHandler, |
| false, |
| EventPriority.BINDING, |
| true); |
| } |
| } |
| } |
| |
| if (isStyle) |
| { |
| // For example, if the data binding expression is |
| // {getStyle("color")}, the eventName will be |
| // "colorChanged". |
| eventName = parameterFunction.apply(document) + "Changed"; |
| eventDispatcher.addEventListener(eventName, eventHandler, false, |
| EventPriority.BINDING, true); |
| eventDispatcher.addEventListener("allStylesChanged", eventHandler, false, |
| EventPriority.BINDING, true); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public function eventHandler(event:Event):void |
| { |
| updateFunctionReturn(); |
| |
| // events can be null when watching a function marked with |
| // [Bindable(style="true")]. |
| if (events != null) |
| { |
| notifyListeners(events[event.type]); |
| } |
| |
| if (isStyle) |
| { |
| notifyListeners(true); |
| } |
| } |
| } |
| |
| } |