reset() method to change the value of the host argument
* after creating the Watcher instance.
* The host maintains a list of handlers to invoke when prop changes.
* @param chain A value specifying the property or chain to be watched.
* For example, to watch the property host.a.b.c,
* call the method as: watch(host, ["a","b","c"], ...).
* @param handler An event handler function called when the value of the watched property
* (or any property in a watched chain) is modified.
* @param thisObject this object of which binding with handler
* @returns he ChangeWatcher instance, if at least one property name has been specified to
* the chain argument; null otherwise.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 创建并启动 Watcher 实例。注意:Watcher 只能监视 host 为 egret.IEventDispatcher 对象的属性改变。若属性链中某个属性所对应的实例不是 egret.IEventDispatcher,
* 则属性链中在它之后的属性改变将无法检测到。
* @param host 用于承载要监视的属性或属性链的对象。
* 创建Watcher实例后,您可以利用reset()方法更改host参数的值。
* 当prop改变的时候,会使得host对应的一系列handlers被触发。
* @param chain 用于指定要监视的属性链的值。例如,要监视属性 host.a.b.c,需按以下形式调用此方法:watch¬(host, ["a","b","c"], ...)。
* @param handler 在监视的目标属性链中任何属性的值发生改变时调用的事件处理函数。
* @param thisObject handler 方法绑定的this对象
* @returns 如果已为 chain 参数至少指定了一个属性名称,则返回 Watcher 实例;否则返回 null。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public static watch(host:any, chain:string[], handler:(value:any)=>void, thisObject:any):Watcher {
if (DEBUG) {
if (!chain) {
egret.$error(1003, "chain");
}
}
if (chain.length > 0) {
let property = chain.shift();
let next = Watcher.watch(null, chain, handler, thisObject);
let watcher = new Watcher(property, handler, thisObject, next);
watcher.reset(host);
return watcher;
}
else {
return null;
}
}
/**
* @private
* 检查属性是否可以绑定。若还未绑定,尝试添加绑定事件。若是只读或只写属性,返回false。
*/
private static checkBindable(host:any, property:string):boolean {
let list:string[] = host[bindables];
if (list && list.indexOf(property) != -1) {
return true;
}
let isEventDispatcher = egret.is(host, "egret.IEventDispatcher");
if(!isEventDispatcher && !host[listeners]){
host[listeners] = [];
}
let data:PropertyDescriptor = getPropertyDescriptor(host, property);
if (data && data.set && data.get) {
let orgSet = data.set;
data.set = function (value:any) {
if (this[property] != value) {
orgSet.call(this, value);
if(isEventDispatcher){
PropertyEvent.dispatchPropertyEvent(this, PropertyEvent.PROPERTY_CHANGE, property);
}
else{
notifyListener(this,property);
}
}
};
}
else if (!data || (!data.get && !data.set)) {
bindableCount++;
let newProp = "_" + bindableCount + property;
host[newProp] = data ? data.value : null;
data = watch() method.
* See the watch() method for parameter usage.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 构造函数,非公开。只能从 watch() 方法中调用此方法。有关参数用法,请参阅 watch() 方法。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public constructor(property:string, handler:(value:any)=>void, thisObject:any, next?:Watcher) {
this.property = property;
this.handler = handler;
this.next = next;
this.thisObject = thisObject;
}
/**
* @private
*/
private host:any;
/**
* @private
*/
private property:string;
/**
* @private
*/
private handler:(value:any)=>void;
/**
* @private
*/
private thisObject:any;
/**
* @private
*/
private next:Watcher;
/**
* @private
*/
private isExecuting:boolean = false;
/**
* Detaches this Watcher instance, and its handler function, from the current host.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 从当前宿主中断开此 Watcher 实例及其处理函数。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public unwatch():void {
this.reset(null);
this.handler = null;
if (this.next) {
this.next.handler = null;
}
}
/**
* Retrieves the current value of the watched property or property chain, or null if the host object is null.
* @example
*
* watch(obj, ["a","b","c"], ...).getValue() === obj.a.b.c
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 检索观察的属性或属性链的当前值,当宿主对象为空时此值为空。
* @example
*
* watch(obj, ["a","b","c"], ...).getValue() === obj.a.b.c
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public getValue():any {
if (this.next) {
return this.next.getValue();
}
return this.getHostPropertyValue();
}
/**
* Sets the handler function.s
* @param handler The handler function. This argument must not be null.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 设置处理函数。
* @param handler 处理函数,此参数必须为非空。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public setHandler(handler:(value:any)=>void, thisObject:any):void {
this.handler = handler;
this.thisObject = thisObject;
if (this.next) {
this.next.setHandler(handler, thisObject);
}
}
/**
* Resets this ChangeWatcher instance to use a new host object.
* You can call this method to reuse a watcher instance on a different host.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 重置此 Watcher 实例使用新的宿主对象。
* 您可以通过该方法实现一个Watcher实例用于不同的宿主。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public reset(newHost:egret.IEventDispatcher):void {
let oldHost = this.host;
if(oldHost){
if (egret.is(oldHost, "egret.IEventDispatcher")) {
oldHost.removeEventListener(PropertyEvent.PROPERTY_CHANGE, this.wrapHandler, this);
}
else {
let list:any[] = oldHost[listeners];
let index = list.indexOf(this);
list.splice(index-1,2);
}
}
this.host = newHost;
if(newHost){
Watcher.checkBindable(newHost, this.property);
if (egret.is(newHost, "egret.IEventDispatcher")) {
newHost.addEventListener(PropertyEvent.PROPERTY_CHANGE, this.wrapHandler, this, false, 100);
}
else{
let list:any[] = newHost[listeners];
list.push(this.onPropertyChange);
list.push(this);
}
}
if (this.next)
this.next.reset(this.getHostPropertyValue());
}
/**
* @private
*
* @returns
*/
private getHostPropertyValue():any {
return this.host ? this.host[this.property] : null;
}
/**
* @private
*/
private wrapHandler(event:PropertyEvent):void {
this.onPropertyChange(event.property);
}
/**
* @private
*/
private onPropertyChange(property:string):void{
if (property == this.property && !this.isExecuting) {
try {
this.isExecuting = true;
if (this.next)
this.next.reset(this.getHostPropertyValue());
this.handler.call(this.thisObject, this.getValue());
}
finally {
this.isExecuting = false;
}
}
}
}
}