Added support for binding to all Style properties directly.

This commit is contained in:
Rossen Hristov
2015-03-23 09:20:56 +02:00
parent 974f15e0ad
commit d1f97d7050
10 changed files with 336 additions and 178 deletions

View File

@ -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);

View File

@ -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
}
/**

View File

@ -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);

View File

@ -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 <T>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,18 +216,74 @@ 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 {
@ -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;
}

83
ui/core/view.d.ts vendored
View File

@ -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.
*/

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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.