Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tns-core-modules/data/observable/observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,4 @@ export function fromObjectRecursive(source: any): Observable {
let observable = new Observable();
addPropertiesFromObject(observable, source, true);
return observable;
}
}
108 changes: 68 additions & 40 deletions tns-core-modules/ui/core/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { unsetValue } from "ui/core/dependency-observable";
import { WrappedValue } from "data/observable";
import { ViewBase } from "./view-base";
import { Style } from "ui/styling/style";
import * as definitions from "ui/core/view-base";

export { unsetValue, Style };

Expand Down Expand Up @@ -31,44 +32,21 @@ const enum ValueSource {
Local = 3
}

export interface PropertyOptions<T, U> {
name: string;
defaultValue?: U;
affectsLayout?: boolean;
equalityComparer?(this: void, x: U, y: U): boolean;
valueChanged?(this: void, target: T, oldValue: U, newValue: U): void;
valueConverter?(this: void, value: string): U;
}

export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
readonly coerceValue: (t: T, u: U) => U;
}

export interface ShorthandPropertyOptions<P> {
name: string;
cssName: string;
converter(this: void, value: string | P): [CssProperty<any, any>, any][];
getter(this: Style): string | P;
}

export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
cssName: string;
}

export class Property<T extends ViewBase, U> implements PropertyDescriptor {
export class Property<T extends ViewBase, U> implements PropertyDescriptor, definitions.Property<T, U> {
private registered: boolean;
private readonly name: string;
public readonly key: symbol;
public readonly native: symbol;
public readonly defaultValueKey: symbol;
public readonly defaultValue: U;
public readonly nativeValueChange: (owner: T, value: U) => void;

public get: () => U;
public set: (value: U) => void;
public enumerable: boolean = true;
public configurable: boolean = true;

constructor(options: PropertyOptions<T, U>) {
constructor(options: definitions.PropertyOptions<T, U>) {
const name = options.name;
this.name = name;

Expand All @@ -85,12 +63,12 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
this.defaultValue = defaultValue;

const eventName = name + "Change";
const affectsLayout: boolean = options.affectsLayout;
const equalityComparer = options.equalityComparer;
const affectsLayout: boolean = options.affectsLayout;
const valueChanged = options.valueChanged;
const valueConverter = options.valueConverter;

this.set = function (this: T, value: any): void {
this.set = function (this: T, value: U): void {
const reset = value === unsetValue;
let unboxedValue: U;
let wrapped: boolean;
Expand Down Expand Up @@ -146,10 +124,34 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
}
}

this.get = function (): U {
this.get = function (this: T): U {
return key in this ? this[key] : defaultValue;
}

this.nativeValueChange = function (owner: T, value: U): void {
const currentValue = key in owner ? owner[key] : defaultValue;
const changed = equalityComparer ? !equalityComparer(currentValue, value) : currentValue !== value;
if (changed) {
owner[key] = value;
if (valueChanged) {
valueChanged(owner, currentValue, value);
}

if (owner.hasListeners(eventName)) {
owner.notify({
eventName: eventName,
propertyName: name,
object: owner,
value: value
});
}

if (affectsLayout) {
owner.requestLayout();
}
}
}

symbolPropertyMap[key] = this;
}

Expand All @@ -162,13 +164,14 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor {
}
}

export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescriptor {
export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescriptor, definitions.CoercibleProperty<T, U> {
private registered: boolean;
private readonly name: string;
public readonly key: symbol;
public readonly native: symbol;
public readonly defaultValueKey: symbol;
public readonly defaultValue: U;
public readonly nativeValueChange: (owner: T, value: U) => void;

public readonly get: () => U;
public readonly set: (value: U) => void;
Expand All @@ -177,7 +180,7 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip

public readonly coerce: (target: T) => void;

constructor(options: CoerciblePropertyOptions<T, U>) {
constructor(options: definitions.CoerciblePropertyOptions<T, U>) {
const name = options.name;
this.name = name;

Expand Down Expand Up @@ -272,6 +275,31 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
return key in this ? this[key] : defaultValue;
}

this.nativeValueChange = function (owner: T, value: U): void {
const currentValue = key in owner ? owner[key] : defaultValue;
const changed = equalityComparer ? !equalityComparer(currentValue, value) : currentValue !== value;
if (changed) {
owner[key] = value;
owner[coerceKey] = value;
if (valueChanged) {
valueChanged(owner, currentValue, value);
}

if (owner.hasListeners(eventName)) {
owner.notify({
eventName: eventName,
propertyName: name,
object: owner,
value: value
});
}

if (affectsLayout) {
owner.requestLayout();
}
}
}

symbolPropertyMap[key] = this;
}

Expand All @@ -284,11 +312,11 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
}
}

export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> implements definitions.InheritedProperty<T, U> {
public readonly sourceKey: symbol;
public readonly setInheritedValue: (value: U) => void;

constructor(options: PropertyOptions<T, U>) {
constructor(options: definitions.PropertyOptions<T, U>) {
super(options);
const name = options.name;
const key = this.key;
Expand Down Expand Up @@ -369,7 +397,7 @@ export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
}
}

export class CssProperty<T extends Style, U> {
export class CssProperty<T extends Style, U> implements definitions.CssProperty<T, U> {
private registered: boolean;

public readonly name: string;
Expand All @@ -384,7 +412,7 @@ export class CssProperty<T extends Style, U> {
public readonly defaultValueKey: symbol;
public readonly defaultValue: U;

constructor(options: CssPropertyOptions<T, U>) {
constructor(options: definitions.CssPropertyOptions<T, U>) {
const name = options.name;
this.name = name;

Expand Down Expand Up @@ -559,10 +587,10 @@ export class CssProperty<T extends Style, U> {
}
}

export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> {
export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> implements definitions.InheritedCssProperty<T,U> {
public setInheritedValue: (value: U) => void;

constructor(options: CssPropertyOptions<T, U>) {
constructor(options: definitions.CssPropertyOptions<T, U>) {
super(options);
const name = options.name;

Expand Down Expand Up @@ -684,7 +712,7 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
}
}

export class ShorthandProperty<T extends Style, P> {
export class ShorthandProperty<T extends Style, P> implements definitions.ShorthandProperty<T, P> {
private registered: boolean;

public readonly key: symbol;
Expand All @@ -697,7 +725,7 @@ export class ShorthandProperty<T extends Style, P> {
public readonly native: symbol;
public readonly sourceKey: symbol;

constructor(options: ShorthandPropertyOptions<P>) {
constructor(options: definitions.ShorthandPropertyOptions<P>) {
const name = options.name;
this.name = name;

Expand All @@ -712,7 +740,7 @@ export class ShorthandProperty<T extends Style, P> {

const converter = options.converter;

function setLocalValue(this: T, value: string| P): void {
function setLocalValue(this: T, value: string | P): void {
this[sourceKey] = ValueSource.Local;
if (this[key] !== value) {
this[key] = value;
Expand Down
14 changes: 0 additions & 14 deletions tns-core-modules/ui/core/view-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,20 +374,6 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
}
}

// public _setCore(data: PropertyChangeData) {
// super._setCore(data);
// this._updateTwoWayBinding(data.propertyName, data.value);
// }

public nativePropertyChanged(property: Property<ViewBase, any>, newValue: any): void {
if (this._updatingJSPropertiesDict[property.native]) {
return;
}
this._updatingJSPropertiesDict[property.native] = true;
property.set.call(this, newValue);
delete this._updatingJSPropertiesDict[property.native];
}

public requestLayout(): void {
//
}
Expand Down
6 changes: 0 additions & 6 deletions tns-core-modules/ui/core/view.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,14 +543,8 @@ declare module "ui/core/view" {
public eachChildView(callback: (view: View) => boolean): void;

//@private
/**
* A property has changed on the native side directly - e.g. the user types in a TextField.
*/
public nativePropertyChanged(property: Property<any, any>, newValue: any): void;

isLayoutRequired: boolean;
_gestureObservers: any;
// _isInheritedChange(): boolean;

_updateLayout(): void;

Expand Down
8 changes: 4 additions & 4 deletions tns-core-modules/ui/date-picker/date-picker.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ class DateChangedListener extends java.lang.Object implements android.widget.Dat

let dateIsChanged = false;
if (year !== owner.year) {
owner.nativePropertyChanged(yearProperty, year);
yearProperty.nativeValueChange(owner, year);
dateIsChanged = true;
}

if ((month + 1) !== owner.month) {
owner.nativePropertyChanged(monthProperty, month + 1);
monthProperty.nativeValueChange(owner, month + 1);
dateIsChanged = true;
}

if (day !== owner.day) {
owner.nativePropertyChanged(dayProperty, day);
dayProperty.nativeValueChange(owner, day);
dateIsChanged = true;
}

if (dateIsChanged) {
owner.nativePropertyChanged(dateProperty, new Date(year, month, day));
dateProperty.nativeValueChange(owner, new Date(year, month, day));
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions tns-core-modules/ui/date-picker/date-picker.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,22 @@ class UIDatePickerChangeHandlerImpl extends NSObject {

let dateChanged = false;
if (comps.year !== owner.year) {
owner.nativePropertyChanged(yearProperty, comps.year);
yearProperty.nativeValueChange(owner, comps.year);
dateChanged = true;
}

if (comps.month !== owner.month) {
owner.nativePropertyChanged(monthProperty, comps.month);
monthProperty.nativeValueChange(owner, comps.month);
dateChanged = true;
}

if (comps.day !== owner.day) {
owner.nativePropertyChanged(dayProperty, comps.day);
dayProperty.nativeValueChange(owner, comps.day);
dateChanged = true;
}

if (dateChanged) {
owner.nativePropertyChanged(dateProperty, new Date(comps.year, comps.month - 1, comps.day));
dateProperty.nativeValueChange(owner, new Date(comps.year, comps.month - 1, comps.day));
}
}

Expand Down
2 changes: 2 additions & 0 deletions tns-core-modules/ui/definitions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ declare module "ui/core/properties" {
public readonly native: symbol;
public readonly defaultValue: U;
public register(cls: { prototype: T }): void;
public nativeValueChange(T, U): void;
}

export class CoercibleProperty<T extends ViewBase, U> implements TypedPropertyDescriptor<U> {
Expand All @@ -218,6 +219,7 @@ declare module "ui/core/properties" {
public readonly defaultValue: U;
public readonly coerce: (target: T) => void;
public register(cls: { prototype: T }): void;
public nativeValueChange(T, U): void;
}

export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TextWatcher extends java.lang.Object implements android.text.TextWatcher {
owner._dirtyTextAccumulator = editable.toString();
break;
case "textChanged":
owner.nativePropertyChanged(textProperty, editable.toString());
textProperty.nativeValueChange(owner, editable.toString());
break;
default:
throw new Error("Invalid updateTextTrigger: " + owner.updateTextTrigger);
Expand Down Expand Up @@ -81,7 +81,7 @@ class FocusChangeListener extends java.lang.Object implements android.view.View.
}
else {
if (owner._dirtyTextAccumulator) {
owner.nativePropertyChanged(textProperty, owner._dirtyTextAccumulator);
textProperty.nativeValueChange(owner, owner._dirtyTextAccumulator);
owner._dirtyTextAccumulator = undefined;
}

Expand Down Expand Up @@ -220,13 +220,8 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
return this._android.getText();
}
set [textProperty.native](value: string) {
let newValue;
if (value === null || value === void 0) {
newValue = "";
} else {
newValue = value + "";
}
this._android.setText(newValue, android.widget.TextView.BufferType.EDITABLE);
const text = (value === null || value === undefined) ? '' : value.toString();
this._android.setText(text, android.widget.TextView.BufferType.EDITABLE);
}

get [keyboardTypeProperty.native](): "datetime" | "phone" | "number" | "url" | "email" | string {
Expand Down
4 changes: 2 additions & 2 deletions tns-core-modules/ui/list-picker/list-picker.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ class ValueChangeListener extends java.lang.Object implements android.widget.Num
return global.__native(this);
}

onValueChange(picker: android.widget.NumberPicker, oldVal: number, newVal: number): void {
onValueChange(picker: android.widget.NumberPicker, oldValue: number, newValue: number): void {
let owner = this.owner.get();
if (owner) {
owner.nativePropertyChanged(selectedIndexProperty, newVal);
selectedIndexProperty.nativeValueChange(owner, newValue);
}
}
}
Expand Down
Loading