diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj index 8bafda30a..b8b21c6f6 100644 --- a/CrossPlatformModules.csproj +++ b/CrossPlatformModules.csproj @@ -347,6 +347,10 @@ trace.d.ts + + repeater.d.ts + + list-picker.d.ts @@ -1528,6 +1532,9 @@ PreserveNewest + + PreserveNewest + diff --git a/ui/repeater/package.json b/ui/repeater/package.json new file mode 100644 index 000000000..219eeec41 --- /dev/null +++ b/ui/repeater/package.json @@ -0,0 +1,2 @@ +{ "name" : "repeater", + "main" : "repeater.js" } \ No newline at end of file diff --git a/ui/repeater/repeater.d.ts b/ui/repeater/repeater.d.ts new file mode 100644 index 000000000..e4885cadc --- /dev/null +++ b/ui/repeater/repeater.d.ts @@ -0,0 +1,81 @@ +/** + * Contains the Repeater class, which represents a UI Repeater component. + */ +declare module "ui/repeater" { + import view = require("ui/core/view"); + import dependencyObservable = require("ui/core/dependency-observable"); + + /** + * Represents a UI Repeater component. + */ + export class Repeater extends view.View { + /** + * Represents the observable property backing the orientation property of each Repeater instance. + */ + public static orientationProperty: dependencyObservable.Property; + + /** + * Dependency property used to support binding operations for the items wrapping of the current Repeater instance. + */ + public static wrapProperty: dependencyObservable.Property; + + /** + * Represents the observable property backing the itemWidth property of each Repeater instance. + */ + public static itemWidthProperty: dependencyObservable.Property; + + /** + * Represents the observable property backing the itemHeight property of each Repeater instance. + */ + public static itemHeightProperty: dependencyObservable.Property; + + /** + * Represents the observable property backing the items property of each Repeater instance. + */ + public static itemsProperty: dependencyObservable.Property; + + /** + * Represents the item template property of each Repeater instance. + */ + public static itemTemplateProperty: dependencyObservable.Property; + + /** + * Gets or sets if layout should be horizontal or vertical. + * The default value is vertical. + */ + orientation: string; + + /** + * Gets or sets whether the Repeater wraps items or not. + */ + wrap: boolean; + + /** + * Gets or sets the width used to measure and layout each child. + * Default value is Number.NaN which does not restrict children. + */ + itemWidth: number; + + /** + * Gets or sets the height used to measure and layout each child. + * Default value is Number.NaN which does not restrict children. + */ + itemHeight: number; + + /** + * Gets or set the items collection of the Repeater. + * The items property can be set to an array or an object defining length and getItem(index) method. + */ + items: any; + + /** + * Gets or set the item template of the Repeater. + */ + itemTemplate: string; + + /** + * Forces the Repeater to reload all its items. + */ + refresh(); + } +} \ No newline at end of file diff --git a/ui/repeater/repeater.ts b/ui/repeater/repeater.ts new file mode 100644 index 000000000..6069dbc38 --- /dev/null +++ b/ui/repeater/repeater.ts @@ -0,0 +1,156 @@ +import definition = require("ui/repeater"); +import proxy = require("ui/core/proxy"); +import dependencyObservable = require("ui/core/dependency-observable"); +import viewModule = require("ui/core/view"); +import observable = require("data/observable"); +import observableArray = require("data/observable-array"); +import weakEvents = require("ui/core/weak-event-listener"); +import enums = require("ui/enums"); + +var ITEMS = "items"; +var WRAP = "wrap"; +var ORIENTATION = "orientation"; +var ITEMTEMPLATE = "itemTemplate"; +var ITEMWIDTH = "itemWidth"; +var ITEMHEIGHT = "itemHeight"; +var REPEATER = "Repeater"; + +export module knownTemplates { + export var itemTemplate = "itemTemplate"; +} + +function onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) { + var repeater = data.object; + repeater._onItemsPropertyChanged(data); +} + +function onItemTemplatePropertyChanged(data: dependencyObservable.PropertyChangeData) { + var repeater = data.object; + repeater.refresh(); +} + +function validateOrientation(value: any): boolean { + return value === enums.Orientation.vertical || value === enums.Orientation.horizontal; +} + +function isWidthHeightValid(value: any): boolean { + return isNaN(value) || (value >= 0.0 && value !== Number.POSITIVE_INFINITY); +} + +export class Repeater extends viewModule.View implements definition.Repeater { + + public static itemsProperty = new dependencyObservable.Property( + ITEMS, + REPEATER, + new proxy.PropertyMetadata( + undefined, + dependencyObservable.PropertyMetadataSettings.AffectsLayout, + onItemsPropertyChanged + ) + ); + + public static itemTemplateProperty = new dependencyObservable.Property( + ITEMTEMPLATE, + REPEATER, + new proxy.PropertyMetadata( + undefined, + dependencyObservable.PropertyMetadataSettings.AffectsLayout, + onItemTemplatePropertyChanged + ) + ); + + public static orientationProperty = new dependencyObservable.Property( + ORIENTATION, + REPEATER, + new proxy.PropertyMetadata(enums.Orientation.vertical, + dependencyObservable.PropertyMetadataSettings.AffectsLayout, + undefined, + validateOrientation) + ); + + public static wrapProperty = new dependencyObservable.Property( + WRAP, + REPEATER, + new proxy.PropertyMetadata(false, dependencyObservable.PropertyMetadataSettings.AffectsLayout) + ); + + public static itemWidthProperty = new dependencyObservable.Property( + ITEMWIDTH, + REPEATER, + new proxy.PropertyMetadata(Number.NaN, + dependencyObservable.PropertyMetadataSettings.AffectsLayout, + undefined, + isWidthHeightValid) + ); + + public static itemHeightProperty = new dependencyObservable.Property( + ITEMHEIGHT, + REPEATER, + new proxy.PropertyMetadata(Number.NaN, + dependencyObservable.PropertyMetadataSettings.AffectsLayout, + undefined, + isWidthHeightValid) + ); + + get items(): any { + return this._getValue(Repeater.itemsProperty); + } + set items(value: any) { + this._setValue(Repeater.itemsProperty, value); + } + + get itemTemplate(): string { + return this._getValue(Repeater.itemTemplateProperty); + } + set itemTemplate(value: string) { + this._setValue(Repeater.itemTemplateProperty, value); + } + + public refresh() { + // + } + + public _onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) { + if (data.oldValue instanceof observable.Observable) { + weakEvents.removeWeakEventListener(data.oldValue, observableArray.ObservableArray.changeEvent, this._onItemsChanged, this); + } + + if (data.newValue instanceof observable.Observable) { + weakEvents.addWeakEventListener(data.newValue, observableArray.ObservableArray.changeEvent, this._onItemsChanged, this); + } + + this.refresh(); + } + + private _onItemsChanged(args: observable.EventData) { + this.refresh(); + } + + get wrap(): boolean { + return this._getValue(Repeater.wrapProperty); + } + set wrap(value: boolean) { + this._setValue(Repeater.wrapProperty, value); + } + + get orientation(): string { + return this._getValue(Repeater.orientationProperty); + } + set orientation(value: string) { + this._setValue(Repeater.orientationProperty, value); + } + + get itemWidth(): number { + return this._getValue(Repeater.itemWidthProperty); + } + set itemWidth(value: number) { + this._setValue(Repeater.itemWidthProperty, value); + } + + get itemHeight(): number { + return this._getValue(Repeater.itemHeightProperty); + } + set itemHeight(value: number) { + this._setValue(Repeater.itemHeightProperty, value); + } +} \ No newline at end of file