import bindable = require("ui/core/bindable"); import dependencyObservable = require("ui/core/dependency-observable"); import definition = require("ui/core/proxy"); import * as types from "utils/types"; import * as observable from "data/observable"; export class PropertyMetadata extends dependencyObservable.PropertyMetadata implements definition.PropertyMetadata { private _onSetNativeValue: dependencyObservable.PropertyChangedCallback; constructor( defaultValue: any, options?: number, onChanged?: dependencyObservable.PropertyChangedCallback, onValidateValue?: dependencyObservable.PropertyValidationCallback, onSetNativeValue?: dependencyObservable.PropertyChangedCallback) { super(defaultValue, options, onChanged, onValidateValue); this._onSetNativeValue = onSetNativeValue; } get onSetNativeValue(): dependencyObservable.PropertyChangedCallback { return this._onSetNativeValue; } set onSetNativeValue(value: dependencyObservable.PropertyChangedCallback) { this._onSetNativeValue = value; } } export class ProxyObject extends bindable.Bindable implements definition.ProxyObject { private _updatingJSPropertiesDict = {}; /** * Gets the android-specific native instance that lies behind this proxy. Will be available if running on an Android platform. */ get android(): any { return undefined; } /** * Gets the ios-specific native instance that lies behind this proxy. Will be available if running on an iOS platform. */ get ios(): any { return undefined; } public _onPropertyChanged(property: dependencyObservable.Property, oldValue: any, newValue: any) { super._onPropertyChanged(property, oldValue, newValue); this._trySetNativeValue(property, oldValue, newValue); } /** * A property has changed on the native side directly - e.g. the user types in a TextField. */ public _onPropertyChangedFromNative(property: dependencyObservable.Property, newValue: any) { if (this._updatingJSPropertiesDict[property.name]) { return; } this._updatingJSPropertiesDict[property.name] = true; this._setValue(property, newValue); delete this._updatingJSPropertiesDict[property.name]; } public _syncNativeProperties() { var that = this; var eachPropertyCallback = function (property: dependencyObservable.Property): boolean { that._trySetNativeValue(property); return true; } this._eachSetProperty(eachPropertyCallback); } /** * Checks whether the proxied native object has been created and properties may be applied to it. */ protected _canApplyNativeProperty(): boolean { return false; } private _trySetNativeValue(property: dependencyObservable.Property, oldValue?:any, newValue?: any) { if (this._updatingJSPropertiesDict[property.name]) { // This is the case when a property has changed from the native side directly and we have received the "_onPropertyChanged" event while synchronizing our local cache return; } if (!this._canApplyNativeProperty()) { // in android we have lazy loading and we do not have a native widget created yet, do not call the onSetNativeValue callback // properties will be synced when the widget is created return; } var metadata = property.metadata; if (!(metadata instanceof PropertyMetadata)) { return; } var proxyMetadata = metadata; if (proxyMetadata.onSetNativeValue) { if (types.isUndefined(newValue)) { newValue = this._getValue(property); } proxyMetadata.onSetNativeValue({ object: this, property: property, eventName: observable.Observable.propertyChangeEvent, newValue: newValue, oldValue: oldValue }); } } }