diff --git a/apps/tests/ui/view/view-tests-common.ts b/apps/tests/ui/view/view-tests-common.ts index d0fcd9db3..48130cab5 100644 --- a/apps/tests/ui/view/view-tests-common.ts +++ b/apps/tests/ui/view/view-tests-common.ts @@ -494,13 +494,13 @@ export var test_binding_cssClass = function () { property_binding_test("cssClass", "class1", "class2"); } -//export var test_binding_style_color = function () { -// property_binding_style_test("color", "#FF0000", "#00FF00"); -//} +export var test_binding_style_color = function () { + property_binding_style_test("color", new color.Color("#FF0000"), new color.Color("#00FF00")); +} -//export var test_binding_style_backgroundColor = function () { -// property_binding_style_test("backgroundColor", "#FF0000", "#00FF00"); -//} +export var test_binding_style_backgroundColor = function () { + property_binding_style_test("backgroundColor", new color.Color("#FF0000"), new color.Color("#00FF00")); +} export var test_binding_style_fontSize = function () { property_binding_style_test("fontSize", 5, 10); diff --git a/ui/core/dependency-observable.d.ts b/ui/core/dependency-observable.d.ts index 398e40888..3c10cab7b 100644 --- a/ui/core/dependency-observable.d.ts +++ b/ui/core/dependency-observable.d.ts @@ -13,20 +13,29 @@ declare module "ui/core/dependency-observable" { * @param name The name of the property. * @param ownerType The name of class that registers this property. * @param metadata The PropertyMetadata object associated with this property. + * @param valueConverter A function that can create an instance of the property type given a string. Used when parsing CSS and XML attribute values which are strings. */ - constructor(name: string, ownerType: string, metadata: PropertyMetadata); + constructor(name: string, ownerType: string, metadata: PropertyMetadata, valueConverter?: (value: string) => any); + /** * Gets the name of the property. This is a read-only property. */ name: string; + /** * Gets the id of the property. This is used for fast lookup. This is a read-only property. */ id: number; + /** * Gets the PropertyMetadata object associated with the property. This is a read-only property. */ metadata: PropertyMetadata; + + /** + * Gets the valueConverter function associated with the property. This is a read-only property. + */ + valueConverter: (value: string) => any } /** diff --git a/ui/core/dependency-observable.ts b/ui/core/dependency-observable.ts index a447f065e..16f09bf30 100644 --- a/ui/core/dependency-observable.ts +++ b/ui/core/dependency-observable.ts @@ -108,8 +108,9 @@ export class Property implements definition.Property { private _name: string; private _ownerType: string; private _id: number; + private _valueConverter: (value: any) => any; - constructor(name: string, ownerType: string, metadata: PropertyMetadata) { + constructor(name: string, ownerType: string, metadata: PropertyMetadata, valueConverter?: (value: string) => any) { // register key this._key = generatePropertyKey(name, ownerType, true); @@ -132,6 +133,8 @@ export class Property implements definition.Property { // generate a unique numeric id for each property (faster lookup than a string key) this._id = propertyIdCounter++; + + this._valueConverter = valueConverter; } public get name(): string { @@ -155,6 +158,10 @@ export class Property implements definition.Property { return true; } + public get valueConverter(): (value: string) => any { + return this._valueConverter; + } + public _getEffectiveValue(entry: PropertyEntry): any { if (types.isDefined(entry.localValue)) { entry.valueSource = ValueSource.Local; @@ -359,6 +366,12 @@ export class DependencyObservable extends observable.Observable { } private _setValueInternal(property: Property, value: any, source: number) { + + // Convert the value to the real property type in case it is coming as a string from CSS or XML. + if (types.isString(value) && property.valueConverter) { + value = property.valueConverter(value); + } + var entry: PropertyEntry = this._propertyEntries[property.id]; if (!entry) { entry = new PropertyEntry(property); diff --git a/ui/core/view-common.ts b/ui/core/view-common.ts index 523c288f0..7dcd4b09e 100644 --- a/ui/core/view-common.ts +++ b/ui/core/view-common.ts @@ -11,6 +11,7 @@ import bindable = require("ui/core/bindable"); import styleScope = require("ui/styling/style-scope"); import enums = require("ui/enums"); import utils = require("utils/utils"); +import color = require("color"); export function getViewById(view: View, id: string): View { if (!view) { @@ -157,6 +158,50 @@ export class View extends proxy.ProxyObject implements definition.View, definiti return getViewById(this, id); } + // START Style property shortcuts + + get color(): color.Color { + return this.style.color; + } + set color(value: color.Color) { + this.style.color = value; + } + + get backgroundColor(): color.Color { + return this.style.backgroundColor; + } + set backgroundColor(value: color.Color) { + this.style.backgroundColor = value; + } + + get fontSize(): number { + return this.style.fontSize; + } + set fontSize(value: number) { + this.style.fontSize = value; + } + + get textAlignment(): string { + return this.style.textAlignment; + } + set textAlignment(value: string) { + this.style.textAlignment; + } + + get minWidth(): number { + return this.style.minWidth; + } + set minWidth(value: number) { + this.style.minWidth = value; + } + + get minHeight(): number { + return this.style.minHeight; + } + set minHeight(value: number) { + this.style.minHeight = value; + } + get width(): number { return this.style.width; } @@ -171,20 +216,76 @@ export class View extends proxy.ProxyObject implements definition.View, definiti this.style.height = value; } - get minHeight(): number { - return this.style.minHeight; + get margin(): string { + return this.style.margin; } - set minHeight(value: number) { - this.style.minHeight = value; + set margin(value: string) { + this.style.margin = value; } - get minWidth(): number { - return this.style.minWidth; + get marginLeft(): number { + return this.style.marginLeft; } - set minWidth(value: number) { - this.style.minWidth = value; + set marginLeft(value: number) { + this.style.marginLeft = value; } + get marginTop(): number { + return this.style.marginTop; + } + set marginTop(value: number) { + this.style.marginTop = value; + } + + get marginRight(): number { + return this.style.marginRight; + } + set marginRight(value: number) { + this.style.marginRight = value; + } + + get marginBottom(): number { + return this.style.marginBottom; + } + set marginBottom(value: number) { + this.style.marginBottom = value; + } + + get padding(): string { + return this.style.padding; + } + set padding(value: string) { + this.style.padding = value; + } + + get paddingLeft(): number { + return this.style.paddingLeft; + } + set paddingLeft(value: number) { + this.style.paddingLeft = value; + } + + get paddingTop(): number { + return this.style.paddingTop; + } + set paddingTop(value: number) { + this.style.paddingTop = value; + } + + get paddingRight(): number { + return this.style.paddingRight; + } + set paddingRight(value: number) { + this.style.paddingRight = value; + } + + get paddingBottom(): number { + return this.style.paddingBottom; + } + set paddingBottom(value: number) { + this.style.paddingBottom = value; + } + get horizontalAlignment(): string { return this.style.horizontalAlignment; } @@ -199,34 +300,6 @@ export class View extends proxy.ProxyObject implements definition.View, definiti this.style.verticalAlignment = value; } - public get marginLeft(): number { - return this.style.marginLeft; - } - public set marginLeft(value: number) { - this.style.marginLeft = value; - } - - public get marginTop(): number { - return this.style.marginTop; - } - public set marginTop(value: number) { - this.style.marginTop = value; - } - - public get marginRight(): number { - return this.style.marginRight; - } - public set marginRight(value: number) { - this.style.marginRight = value; - } - - public get marginBottom(): number { - return this.style.marginBottom; - } - public set marginBottom(value: number) { - this.style.marginBottom = value; - } - get visibility(): string { return this.style.visibility; } @@ -234,6 +307,15 @@ export class View extends proxy.ProxyObject implements definition.View, definiti this.style.visibility = value; } + get opacity(): number { + return this.style.opacity; + } + set opacity(value: number) { + this.style.opacity = value; + } + + //END Style property shortcuts + get isEnabled(): boolean { return this._getValue(View.isEnabledProperty); } @@ -825,14 +907,14 @@ export class View extends proxy.ProxyObject implements definition.View, definiti } applyXmlAttribute(attributeName: string, attributeValue: any): boolean { - if (attributeName === "margin") { - this.style.margin = attributeValue; - return true; - } - else if (attributeName === "padding") { - this.style.padding = attributeValue; - return true; - } + //if (attributeName === "margin") { + // this.style.margin = attributeValue; + // return true; + //} + //else if (attributeName === "padding") { + // this.style.padding = attributeValue; + // return true; + //} return false; } diff --git a/ui/core/view.d.ts b/ui/core/view.d.ts index 77eae896d..0424f8429 100644 --- a/ui/core/view.d.ts +++ b/ui/core/view.d.ts @@ -3,6 +3,8 @@ declare module "ui/core/view" { import dependencyObservable = require("ui/core/dependency-observable"); import proxy = require("ui/core/proxy"); import gestures = require("ui/gestures"); + import color = require("color"); + import styling = require("ui/styling"); /** * Gets a child view by id. @@ -107,7 +109,7 @@ declare module "ui/core/view" { * This class is the base class for all UI components. * A View occupies a rectangular area on the screen and is responsible for drawing and layouting of all UI components within. */ - export class View extends proxy.ProxyObject implements ApplyXmlAttributes { + export class View extends proxy.ProxyObject/* implements ApplyXmlAttributes*/ { /** * Represents the observable property backing the id property of each View. */ @@ -122,15 +124,27 @@ declare module "ui/core/view" { constructor(options?: Options); - /** - * Gets or sets the desired width of the view. - */ - width: number; + //----------Style property shortcuts---------- /** - * Gets or sets the desired height of the view. + * Gets or sets the color of the view. */ - height: number; + color: color.Color; + + /** + * Gets or sets the background color of the view. + */ + backgroundColor: color.Color; + + /** + * Gets or sets font-size style property. + */ + fontSize: number; + + /** + * Gets or sets text-alignment style property. + */ + textAlignment: string; /** * Gets or sets the minimum width the view may grow to. @@ -143,14 +157,19 @@ declare module "ui/core/view" { minHeight: number; /** - * Gets or sets the alignment of this view within its parent along the Horizontal axis. + * Gets or sets the desired width of the view. */ - horizontalAlignment: string; + width: number; /** - * Gets or sets the alignment of this view within its parent along the Vertical axis. + * Gets or sets the desired height of the view. */ - verticalAlignment: string; + height: number; + + /** + * Gets or sets margin style property. + */ + margin: string; /** * Specifies extra space on the left side of this view. @@ -172,11 +191,53 @@ declare module "ui/core/view" { */ marginBottom: number; + /** + * Gets or sets padding style property. + */ + padding: string; + + /** + * Specify the left padding of this view. + */ + paddingLeft: number; + + /** + * Specify the top padding of this view. + */ + paddingTop: number; + + /** + * Specify the right padding of this view. + */ + paddingRight: number; + + /** + * Specify the bottom padding of this view. + */ + paddingBottom: number; + + /** + * Gets or sets the alignment of this view within its parent along the Horizontal axis. + */ + horizontalAlignment: string; + + /** + * Gets or sets the alignment of this view within its parent along the Vertical axis. + */ + verticalAlignment: string; + /** * Gets or sets the visibility of the view. */ visibility: string; + /** + * Gets or sets the opacity style property. + */ + opacity: number; + + //----------Style property shortcuts---------- + /** * Gets or sets a value indicating whether the the view is enabled. This affects the appearance of the view. */ diff --git a/ui/styling/converters.ts b/ui/styling/converters.ts index f2bc8ae43..dd4fec3ae 100644 --- a/ui/styling/converters.ts +++ b/ui/styling/converters.ts @@ -2,40 +2,40 @@ import enums = require("ui/enums"); import types = require("utils/types"); -export function colorConverter(cssValue: any): color.Color { - return new color.Color(cssValue); +export function colorConverter(value: string): color.Color { + return new color.Color(value); } -export function fontSizeConverter(cssValue: any): number { +export function fontSizeConverter(value: string): number { // TODO: parse different unit types - var result: number = parseFloat(cssValue); + var result: number = parseFloat(value); return result; } -export function textAlignConverter(cssValue: any): string { - switch (cssValue) { +export function textAlignConverter(value: string): string { + switch (value) { case enums.TextAlignment.left: case enums.TextAlignment.center: case enums.TextAlignment.right: - return cssValue; + return value; break; default: - throw new Error("CSS text-align \"" + cssValue + "\" is not supported."); + throw new Error("CSS text-align \"" + value + "\" is not supported."); break; } } export var numberConverter = parseFloat; -export function visibilityConverter(cssValue: any): string { - if (types.isString(cssValue) && cssValue.toLowerCase() === enums.Visibility.collapsed) { +export function visibilityConverter(value: string): string { + if (value.toLowerCase() === enums.Visibility.collapsed) { return enums.Visibility.collapsed; } return enums.Visibility.visible; } -export function opacityConverter(cssValue: any): number { - var result = parseFloat(cssValue); +export function opacityConverter(value: string): number { + var result = parseFloat(value); result = Math.max(0.0, result); result = Math.min(1.0, result); diff --git a/ui/styling/css-selector.ts b/ui/styling/css-selector.ts index 726469a15..49c648983 100644 --- a/ui/styling/css-selector.ts +++ b/ui/styling/css-selector.ts @@ -47,9 +47,8 @@ export class CssSelector { property = styleProperty.getPropertyByCssName(this._declarations[i].property); if (property) { resolvedValue = this._declarations[i].value; - if (property.valueConverter) { - resolvedValue = property.valueConverter(resolvedValue); - } + // The property.valueConverter is now used to convert the value later on in DependencyObservable._setValueInternal. + console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); callback(property, resolvedValue); } } diff --git a/ui/styling/style-property.ts b/ui/styling/style-property.ts index 84c0319ab..85903180c 100644 --- a/ui/styling/style-property.ts +++ b/ui/styling/style-property.ts @@ -51,13 +51,11 @@ export function eachInheritableProperty(callback: (property: Property) => void) export class Property extends observable.Property implements definition.Property { private _cssName; - private _valueConverter: (value: any) => any; constructor(name: string, cssName: string, metadata: observable.PropertyMetadata, valueConverter?: (value: any) => any) { - super(name, "Style", metadata); + super(name, "Style", metadata, valueConverter); this._cssName = cssName; - this._valueConverter = valueConverter; registerProperty(this); } @@ -66,10 +64,6 @@ export class Property extends observable.Property implements definition.Property return this._cssName; } - public get valueConverter(): (value: any) => any { - return this._valueConverter; - } - public _getEffectiveValue(entry: observable.PropertyEntry): any { if (types.isDefined(entry.visualStateValue)) { entry.valueSource = observable.ValueSource.VisualState; diff --git a/ui/styling/style.ts b/ui/styling/style.ts index b48a4701e..54cf12904 100644 --- a/ui/styling/style.ts +++ b/ui/styling/style.ts @@ -56,88 +56,18 @@ export class Style extends observable.DependencyObservable implements styling.St this._setValue(textAlignmentProperty, value, observable.ValueSource.Local); } - get verticalAlignment(): string { - return this._getValue(verticalAlignmentProperty); + get minWidth(): number { + return this._getValue(minWidthProperty); } - set verticalAlignment(value: string) { - this._setValue(verticalAlignmentProperty, value, observable.ValueSource.Local); + set minWidth(value: number) { + this._setValue(minWidthProperty, value, observable.ValueSource.Local); } - get horizontalAlignment(): string { - return this._getValue(horizontalAlignmentProperty); + get minHeight(): number { + return this._getValue(minHeightProperty); } - set horizontalAlignment(value: string) { - this._setValue(horizontalAlignmentProperty, value, observable.ValueSource.Local); - } - - get padding(): string { - return this._getValue(paddingProperty); - } - set padding(value: string) { - this._setValue(paddingProperty, value, observable.ValueSource.Local); - } - - get margin(): string { - return this._getValue(marginProperty); - } - set margin(value: string) { - this._setValue(marginProperty, value, observable.ValueSource.Local); - } - - public get marginLeft(): number { - return this._getValue(marginLeftProperty); - } - public set marginLeft(value: number) { - this._setValue(marginLeftProperty, value, observable.ValueSource.Local); - } - - public get marginTop(): number { - return this._getValue(marginTopProperty); - } - public set marginTop(value: number) { - this._setValue(marginTopProperty, value, observable.ValueSource.Local); - } - - public get marginRight(): number { - return this._getValue(marginRightProperty); - } - public set marginRight(value: number) { - this._setValue(marginRightProperty, value, observable.ValueSource.Local); - } - - public get marginBottom(): number { - return this._getValue(marginBottomProperty); - } - public set marginBottom(value: number) { - this._setValue(marginBottomProperty, value, observable.ValueSource.Local); - } - - public get paddingLeft(): number { - return this._getValue(paddingLeftProperty); - } - public set paddingLeft(value: number) { - this._setValue(paddingLeftProperty, value, observable.ValueSource.Local); - } - - public get paddingTop(): number { - return this._getValue(paddingTopProperty); - } - public set paddingTop(value: number) { - this._setValue(paddingTopProperty, value, observable.ValueSource.Local); - } - - public get paddingRight(): number { - return this._getValue(paddingRightProperty); - } - public set paddingRight(value: number) { - this._setValue(paddingRightProperty, value, observable.ValueSource.Local); - } - - public get paddingBottom(): number { - return this._getValue(paddingBottomProperty); - } - public set paddingBottom(value: number) { - this._setValue(paddingBottomProperty, value, observable.ValueSource.Local); + set minHeight(value: number) { + this._setValue(minHeightProperty, value, observable.ValueSource.Local); } get width(): number { @@ -154,18 +84,88 @@ export class Style extends observable.DependencyObservable implements styling.St this._setValue(heightProperty, value, observable.ValueSource.Local); } - get minWidth(): number { - return this._getValue(minWidthProperty); + get margin(): string { + return this._getValue(marginProperty); } - set minWidth(value: number) { - this._setValue(minWidthProperty, value, observable.ValueSource.Local); + set margin(value: string) { + this._setValue(marginProperty, value, observable.ValueSource.Local); } - get minHeight(): number { - return this._getValue(minHeightProperty); + get marginLeft(): number { + return this._getValue(marginLeftProperty); } - set minHeight(value: number) { - this._setValue(minHeightProperty, value, observable.ValueSource.Local); + set marginLeft(value: number) { + this._setValue(marginLeftProperty, value, observable.ValueSource.Local); + } + + get marginTop(): number { + return this._getValue(marginTopProperty); + } + set marginTop(value: number) { + this._setValue(marginTopProperty, value, observable.ValueSource.Local); + } + + get marginRight(): number { + return this._getValue(marginRightProperty); + } + set marginRight(value: number) { + this._setValue(marginRightProperty, value, observable.ValueSource.Local); + } + + get marginBottom(): number { + return this._getValue(marginBottomProperty); + } + set marginBottom(value: number) { + this._setValue(marginBottomProperty, value, observable.ValueSource.Local); + } + + get padding(): string { + return this._getValue(paddingProperty); + } + set padding(value: string) { + this._setValue(paddingProperty, value, observable.ValueSource.Local); + } + + get paddingLeft(): number { + return this._getValue(paddingLeftProperty); + } + set paddingLeft(value: number) { + this._setValue(paddingLeftProperty, value, observable.ValueSource.Local); + } + + get paddingTop(): number { + return this._getValue(paddingTopProperty); + } + set paddingTop(value: number) { + this._setValue(paddingTopProperty, value, observable.ValueSource.Local); + } + + get paddingRight(): number { + return this._getValue(paddingRightProperty); + } + set paddingRight(value: number) { + this._setValue(paddingRightProperty, value, observable.ValueSource.Local); + } + + get paddingBottom(): number { + return this._getValue(paddingBottomProperty); + } + set paddingBottom(value: number) { + this._setValue(paddingBottomProperty, value, observable.ValueSource.Local); + } + + get horizontalAlignment(): string { + return this._getValue(horizontalAlignmentProperty); + } + set horizontalAlignment(value: string) { + this._setValue(horizontalAlignmentProperty, value, observable.ValueSource.Local); + } + + get verticalAlignment(): string { + return this._getValue(verticalAlignmentProperty); + } + set verticalAlignment(value: string) { + this._setValue(verticalAlignmentProperty, value, observable.ValueSource.Local); } get visibility(): string { diff --git a/ui/styling/styling.d.ts b/ui/styling/styling.d.ts index c0f8c7bed..01c64dc82 100644 --- a/ui/styling/styling.d.ts +++ b/ui/styling/styling.d.ts @@ -111,25 +111,25 @@ declare module "ui/styling" { */ padding: string; - /** - * Specify the bottom padding of this view. - */ - paddingBottom: number; - /** * Specify the left padding of this view. */ paddingLeft: number; + /** + * Specify the top padding of this view. + */ + paddingTop: number; + /** * Specify the right padding of this view. */ paddingRight: number; /** - * Specify the top padding of this view. + * Specify the bottom padding of this view. */ - paddingTop: number; + paddingBottom: number; /** * Gets or sets horizontal-alignment style property.