Initial prototype of Observable object

This commit is contained in:
atanasovg
2014-06-03 13:53:55 +03:00
parent 3fcb0e8e40
commit 3b944e1ba5
8 changed files with 179 additions and 2 deletions

View File

@@ -152,6 +152,15 @@
<TypeScriptCompile Include="text\text.ios.ts">
<DependentUpon>text.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="ui\core\proxy.ts" />
<TypeScriptCompile Include="ui\text-view\text-view.android.ts">
<DependentUpon>text-view.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="ui\text-view\text-view.common.ts" />
<TypeScriptCompile Include="ui\text-view\text-view.d.ts" />
<TypeScriptCompile Include="ui\text-view\text-view.ios.ts">
<DependentUpon>text-view.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="utils\module-merge.ts" />
<TypeScriptCompile Include="utils\utils_android.ts" />
<TypeScriptCompile Include="utils\utils_ios.ts" />

View File

@@ -1 +1,112 @@

export enum ChangePhase {
Changing,
Changed
}
export interface ChangeData {
eventName: string;
sender: Observable;
phase?: ChangePhase;
}
export interface PropertyChangeData extends ChangeData {
propertyName: string;
oldValue: any;
newValue: any;
cancel?: boolean;
}
export class Observable {
public static propertyChangeEvent = "propertyChange";
private _observers = {};
// true to track the Changing phase, false otherwise
private _trackChanging = false;
public bind(eventName: string, callback: (data: ChangeData) => void) {
this.verifyCallback(callback);
var list = this.getEventList(eventName, true);
list.push(callback);
}
public setProperty(name: string, value: any) {
// TODO: Parameter validation
if (!(name in this._observers)) {
// no observers to notify for the PropertyChange event
return;
}
// create data for the change
var data: PropertyChangeData = {
eventName: Observable.propertyChangeEvent,
propertyName: name,
sender: this,
oldValue: this[name],
newValue: value,
cancel: false
};
if (this._trackChanging) {
data.phase = ChangePhase.Changing;
this.notifyObservers(data);
if (data.cancel) {
// change is canceled by an observer
// TODO: define some priority, e.g. if someone cancels the change should others be able to override this cancelation?
return;
}
}
data.phase = ChangePhase.Changed;
this.notifyObservers(data);
this.setPropertyCore(data);
}
public getProperty(name: string): any {
return this[name];
}
/**
* This method is intended to be overriden by inheritors to specify additional
*/
public setPropertyCore(data: PropertyChangeData) {
// get the new value from the data since some observer may have it modified - e.g. validation scenario
this[data.eventName] = data.newValue;
}
private getEventList(eventName: string, createIfNeeded?: boolean): Array<(data: ChangeData) => void> {
if (!eventName) {
throw new TypeError("EventName must be valid string.");
}
var list = <Array<(data: ChangeData) => void>>this._observers[eventName];
if (!list && createIfNeeded) {
list = new Array<(data: ChangeData) => void>();
this._observers[eventName] = list;
}
return list;
}
private verifyCallback(callback: any) {
if (!callback || typeof callback !== "function") {
throw new TypeError("Callback must be a valid function.");
}
}
// The method will return true if the change is accepted, false otherwise
private notifyObservers(data: ChangeData) {
var observers = this.getEventList(data.eventName);
if (!observers) {
return;
}
var i,
callback;
for (i = 0; i < observers.length; i++) {
callback = observers[i];
callback(data);
}
}
}

12
ui/core/proxy.ts Normal file
View File

@@ -0,0 +1,12 @@
import observable = require("ui/core/observable");
export class ProxyObject extends observable.Observable {
public setPropertyCore(data: observable.PropertyChangeData) {
super.setPropertyCore(data);
this.setNativeProperty(data);
}
public setNativeProperty(data: observable.PropertyChangeData) {
// TODO:
}
}

View File

@@ -1 +1,5 @@

import proxy = require("ui/core/proxy");
export class View extends proxy.ProxyObject {
}

View File

@@ -0,0 +1,21 @@
import observable = require("ui/core/observable");
import view = require("ui/core/view");
export class TextView extends view.View {
public android: android.widget.TextView;
get text(): string {
if (this.android) {
return this.android.getText().toString();
}
return undefined;
}
set text(value: string) {
}
public setNativeProperty(data: observable.PropertyChangeData) {
// TODO:
}
}

View File

@@ -0,0 +1,14 @@
import observable = require("ui/core/observable");
import view = require("ui/core/view");
export class TextView extends view.View {
public static textProperty = "text";
get text(): string {
return this.getProperty(TextView.textProperty);
}
public setNativeProperty(data: observable.PropertyChangeData) {
// TODO:
}
}

1
ui/text-view/text-view.d.ts vendored Normal file
View File

@@ -0,0 +1 @@


View File

@@ -0,0 +1,5 @@
import view = require("ui/core/view");
export class TextView extends view.View {
}