blob: 3ebef70cb6a890f2a0cd327e7688692a7f194438 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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);
}
}
}
}