Frobit setting inline style from code

This commit is contained in:
vakrilov
2015-07-07 14:40:58 +03:00
parent c5748bf73b
commit f3979136a4
10 changed files with 130 additions and 108 deletions

View File

@ -1,10 +1,13 @@
import view = require("ui/core/view"); import view = require("ui/core/view");
import pages = require("ui/page");
export function applyTap(args) { export function applyTap(args) {
var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); var page = <pages.Page>view.getAncestor(args.object, "Page");
(<any>el).style = args.object.tag; var css = "#test-element { " + args.object.tag + " }";
page.css = css;
} }
export function resetTap(args) { export function resetTap(args) {
var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); var page = <pages.Page>view.getAncestor(args.object, "Page");
(<any>el).style = ""; page.css = "";
} }

View File

@ -310,7 +310,7 @@ export function test_setting_font_shorthand_property() {
function test_font_shorthand_property(short: string, family: string, size: number, style: string, weight:string) { function test_font_shorthand_property(short: string, family: string, size: number, style: string, weight:string) {
var testView = new buttonModule.Button(); var testView = new buttonModule.Button();
(<any>testView).style = "font: " + short; (<any>testView.style)["font"] = short;
TKUnit.assertEqual(testView.style.fontFamily, family, "style.fontFamily"); TKUnit.assertEqual(testView.style.fontFamily, family, "style.fontFamily");
TKUnit.assertEqual(testView.style.fontStyle, style, "style.fontStyle"); TKUnit.assertEqual(testView.style.fontStyle, style, "style.fontStyle");

View File

@ -99,23 +99,23 @@ export function test_type_selector() {
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
page = new pageModule.Page(); page = new pageModule.Page();
// <snippet module="ui/styling" title="styling"> // <snippet module="ui/styling" title="styling">
// ### Using type selector // ### Using type selector
// ``` JavaScript // ``` JavaScript
page.css = "button { color: red; }"; page.css = "button { color: red; }";
//// Will be styled //// Will be styled
btn = new buttonModule.Button(); btn = new buttonModule.Button();
//// Won't be styled //// Won't be styled
label = new labelModule.Label(); label = new labelModule.Label();
// ``` // ```
// </snippet> // </snippet>
var stack = new stackModule.StackLayout(); var stack = new stackModule.StackLayout();
page.content = stack; page.content = stack;
stack.addChild(label); stack.addChild(label);
stack.addChild(btn); stack.addChild(btn);
return page; return page;
}; };
@ -135,24 +135,24 @@ export function test_class_selector() {
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
page = new pageModule.Page(); page = new pageModule.Page();
// <snippet module="ui/styling" title="styling"> // <snippet module="ui/styling" title="styling">
// ### Using class selector // ### Using class selector
// ``` JavaScript // ``` JavaScript
page.css = ".test { color: red; }"; page.css = ".test { color: red; }";
//// Will be styled //// Will be styled
btnWithClass = new buttonModule.Button(); btnWithClass = new buttonModule.Button();
btnWithClass.cssClass = "test"; btnWithClass.cssClass = "test";
//// Won't be styled //// Won't be styled
btnWithNoClass = new buttonModule.Button(); btnWithNoClass = new buttonModule.Button();
// ``` // ```
// </snippet> // </snippet>
var stack = new stackModule.StackLayout(); var stack = new stackModule.StackLayout();
page.content = stack; page.content = stack;
stack.addChild(btnWithClass); stack.addChild(btnWithClass);
stack.addChild(btnWithNoClass); stack.addChild(btnWithNoClass);
return page; return page;
}; };
@ -199,24 +199,24 @@ export function test_id_selector() {
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
page = new pageModule.Page(); page = new pageModule.Page();
// <snippet module="ui/styling" title="styling"> // <snippet module="ui/styling" title="styling">
// ### Using id selector // ### Using id selector
// ``` JavaScript // ``` JavaScript
page.css = "#myButton { color: red; }"; page.css = "#myButton { color: red; }";
//// Will be styled //// Will be styled
btnWithId = new buttonModule.Button(); btnWithId = new buttonModule.Button();
btnWithId.id = "myButton"; btnWithId.id = "myButton";
//// Won't be styled //// Won't be styled
btnWithNoId = new buttonModule.Button(); btnWithNoId = new buttonModule.Button();
// ``` // ```
// </snippet> // </snippet>
var stack = new stackModule.StackLayout(); var stack = new stackModule.StackLayout();
page.content = stack; page.content = stack;
stack.addChild(btnWithId); stack.addChild(btnWithId);
stack.addChild(btnWithNoId); stack.addChild(btnWithNoId);
return page; return page;
}; };
@ -234,13 +234,13 @@ export function test_state_selector() {
var page: pageModule.Page; var page: pageModule.Page;
var btn: buttonModule.Button; var btn: buttonModule.Button;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
// Arrange // Arrange
page = new pageModule.Page(); page = new pageModule.Page();
var testStack = new stackModule.StackLayout(); var testStack = new stackModule.StackLayout();
page.content = testStack; page.content = testStack;
btn = new buttonModule.Button(); btn = new buttonModule.Button();
testStack.addChild(btn); testStack.addChild(btn);
page.css = ":pressed { color: red; }"; page.css = ":pressed { color: red; }";
return page; return page;
@ -260,18 +260,18 @@ export function test_type_and_state_selector() {
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
page = new pageModule.Page(); page = new pageModule.Page();
// <snippet module="ui/styling" title="styling"> // <snippet module="ui/styling" title="styling">
// ### Using state selector // ### Using state selector
// ``` JavaScript // ``` JavaScript
page.css = "button:pressed { color: red; }"; page.css = "button:pressed { color: red; }";
//// Will be red when pressed //// Will be red when pressed
btn = new buttonModule.Button(); btn = new buttonModule.Button();
// ``` // ```
// </snippet> // </snippet>
var stack = new stackModule.StackLayout(); var stack = new stackModule.StackLayout();
page.content = stack; page.content = stack;
stack.addChild(btn); stack.addChild(btn);
return page; return page;
}; };
@ -287,14 +287,14 @@ export function test_class_and_state_selector() {
var page: pageModule.Page; var page: pageModule.Page;
var btn: buttonModule.Button; var btn: buttonModule.Button;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
// Arrange // Arrange
page = new pageModule.Page(); page = new pageModule.Page();
var testStack = new stackModule.StackLayout(); var testStack = new stackModule.StackLayout();
page.content = testStack; page.content = testStack;
btn = new buttonModule.Button(); btn = new buttonModule.Button();
btn.cssClass = "test" btn.cssClass = "test"
testStack.addChild(btn); testStack.addChild(btn);
page.css = ".test:pressed { color: red; }"; page.css = ".test:pressed { color: red; }";
return page; return page;
@ -337,14 +337,14 @@ export function test_id_and_state_selector() {
var page: pageModule.Page; var page: pageModule.Page;
var btn: buttonModule.Button; var btn: buttonModule.Button;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
// Arrange // Arrange
page = new pageModule.Page(); page = new pageModule.Page();
var testStack = new stackModule.StackLayout(); var testStack = new stackModule.StackLayout();
page.content = testStack; page.content = testStack;
btn = new buttonModule.Button(); btn = new buttonModule.Button();
btn.id = "myButton"; btn.id = "myButton";
testStack.addChild(btn); testStack.addChild(btn);
page.css = "#myButton:pressed { color: red; }"; page.css = "#myButton:pressed { color: red; }";
return page; return page;
@ -362,16 +362,16 @@ export function test_restore_original_values_when_state_is_changed() {
var page: pageModule.Page; var page: pageModule.Page;
var btn: buttonModule.Button; var btn: buttonModule.Button;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
// Arrange // Arrange
page = new pageModule.Page(); page = new pageModule.Page();
var testStack = new stackModule.StackLayout(); var testStack = new stackModule.StackLayout();
page.content = testStack; page.content = testStack;
btn = new buttonModule.Button(); btn = new buttonModule.Button();
testStack.addChild(btn); testStack.addChild(btn);
page.css = "button { color: blue; } " + page.css = "button { color: blue; } " +
"button:pressed { color: red; } "; "button:pressed { color: red; } ";
return page; return page;
}; };
@ -483,7 +483,7 @@ export var test_style_is_applied_when_control_is_added_after_load = function ()
}; };
helper.navigate(pageFactory); helper.navigate(pageFactory);
testStack.addChild(btn); testStack.addChild(btn);
TKUnit.assert(btn.style.color, "Color property no applied correctly."); TKUnit.assert(btn.style.color, "Color property no applied correctly.");
TKUnit.assert(btn.style.color.hex === "#FF0000", "Color property no applied correctly."); TKUnit.assert(btn.style.color.hex === "#FF0000", "Color property no applied correctly.");
@ -657,20 +657,20 @@ function testSelectorsPrioritiesTemplate(css: string) {
var btnWithId: buttonModule.Button; var btnWithId: buttonModule.Button;
var pageFactory = function (): pageModule.Page { var pageFactory = function (): pageModule.Page {
page = new pageModule.Page(); page = new pageModule.Page();
var testStack = new stackModule.StackLayout(); var testStack = new stackModule.StackLayout();
page.content = testStack; page.content = testStack;
btn = new buttonModule.Button(); btn = new buttonModule.Button();
testStack.addChild(btn); testStack.addChild(btn);
btnWithClass = new buttonModule.Button(); btnWithClass = new buttonModule.Button();
btnWithClass.cssClass = "button-class"; btnWithClass.cssClass = "button-class";
testStack.addChild(btnWithClass); testStack.addChild(btnWithClass);
btnWithId = new buttonModule.Button(); btnWithId = new buttonModule.Button();
btnWithId.cssClass = "button-class"; btnWithId.cssClass = "button-class";
btnWithId.id = "myButton" btnWithId.id = "myButton"
testStack.addChild(btnWithId); testStack.addChild(btnWithId);
page.css = css; page.css = css;
return page; return page;
@ -748,19 +748,12 @@ export function test_setInlineStyle_setsLocalValues() {
}); });
} }
export function test_setInlineStyle_resetsLocalValues() { export function test_setStyle_throws() {
var testButton = new buttonModule.Button(); var testButton = new buttonModule.Button();
testButton.text = "Test";
testButton.style.fontSize = 10;
var stack = new stackModule.StackLayout();
stack.addChild(testButton);
helper.buildUIAndRunTest(stack, function (views: Array<viewModule.View>) { TKUnit.assertThrows(function () {
(<any>testButton)._applyInlineStyle("color: red;"); (<any>testButton).style = "background-color: red;";
helper.assertViewColor(testButton, "#FF0000", dependencyObservableModule.ValueSource.Local); }, "View.style property is read-only.");
TKUnit.assert(types.isUndefined(testButton.style.fontSize), "Setting inline style should reset font size");
TKUnit.assertEqual(testButton.style._getValueSource(styling.properties.fontSizeProperty), dependencyObservableModule.ValueSource.Default, "valueSource");
});
} }
export var test_CSS_isAppliedOnPage = function () { export var test_CSS_isAppliedOnPage = function () {

View File

@ -1,10 +1,13 @@
import view = require("ui/core/view"); import view = require("ui/core/view");
import pages = require("ui/page");
export function applyTap(args) { export function applyTap(args) {
var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); var page = <pages.Page>view.getAncestor(args.object, "Page");
(<any>el).style = args.object.tag; var css = "#test-element { " + args.object.tag + " }";
page.css = css;
} }
export function resetTap(args) { export function resetTap(args) {
var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); var page = <pages.Page>view.getAncestor(args.object, "Page");
(<any>el).style = ""; page.css = "";
} }

View File

@ -18,7 +18,7 @@ export class Span extends bindable.Bindable implements definition.Span, view.App
private _spanModifiers: Array<any>; private _spanModifiers: Array<any>;
private _parentFormattedString: formattedString.FormattedString; private _parentFormattedString: formattedString.FormattedString;
private _isInEditMode: boolean; private _isInEditMode: boolean;
get fontFamily(): string { get fontFamily(): string {
return this._fontFamily; return this._fontFamily;
} }
@ -157,7 +157,7 @@ export class Span extends bindable.Bindable implements definition.Span, view.App
} }
public updateSpanModifiers(parent: formattedString.FormattedString) { public updateSpanModifiers(parent: formattedString.FormattedString) {
// a virtual method overriden in platform specific implementations. // a virtual method overridden in platform specific implementations.
if (this._isInEditMode) { if (this._isInEditMode) {
throw new Error("Cannot update span modifiers during update!"); throw new Error("Cannot update span modifiers during update!");
} }
@ -180,7 +180,7 @@ export class Span extends bindable.Bindable implements definition.Span, view.App
this.updateAndNotify(); this.updateAndNotify();
} }
public applyXmlAttribute(attribute, value): boolean { public _applyXmlAttribute(attribute, value): boolean {
if (attribute === "fontAttributes") { if (attribute === "fontAttributes") {
if (value.indexOf(",")) { if (value.indexOf(",")) {
var fontAttr = value.split(","); var fontAttr = value.split(",");

View File

@ -174,8 +174,8 @@ export function setPropertyValue(instance: view.View, instanceModule: Object, ex
} else { } else {
var attrHandled = false; var attrHandled = false;
if ((<any>instance).applyXmlAttribute) { if ((<any>instance)._applyXmlAttribute) {
attrHandled = (<any>instance).applyXmlAttribute(propertyName, propertyValue); attrHandled = (<any>instance)._applyXmlAttribute(propertyName, propertyValue);
} }
if (!attrHandled) { if (!attrHandled) {

View File

@ -389,7 +389,7 @@ export class View extends proxy.ProxyObject implements definition.View {
return this._style; return this._style;
} }
set style(value) { set style(value) {
this._applyInlineStyle(value); throw new Error("View.style property is read-only.");
} }
get isLayoutValid(): boolean { get isLayoutValid(): boolean {
@ -763,7 +763,6 @@ export class View extends proxy.ProxyObject implements definition.View {
if (types.isString(inlineStyle)) { if (types.isString(inlineStyle)) {
try { try {
this.style._beginUpdate(); this.style._beginUpdate();
this.style._resetLocalValues();
styleScope.applyInlineSyle(this, <string>inlineStyle); styleScope.applyInlineSyle(this, <string>inlineStyle);
} finally { } finally {
this.style._endUpdate(); this.style._endUpdate();
@ -942,6 +941,15 @@ export class View extends proxy.ProxyObject implements definition.View {
this._requestedVisualState = state; this._requestedVisualState = state;
} }
public _applyXmlAttribute(attribute, value): boolean {
if (attribute === "style") {
this._applyInlineStyle(value);
return true;
}
return false;
}
public _updateLayout() { public _updateLayout() {
// needed for iOS. // needed for iOS.
} }

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

@ -94,7 +94,7 @@ declare module "ui/core/view" {
* This class is the base class for all UI components. * 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. * 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 { export class View extends proxy.ProxyObject implements ApplyXmlAttributes {
/** /**
* Gets or sets the corner radius of the view. * Gets or sets the corner radius of the view.
*/ */
@ -441,6 +441,8 @@ declare module "ui/core/view" {
_updateLayout(): void; _updateLayout(): void;
_applyXmlAttribute(attribute, value): boolean;
/** /**
* Called my measure method to cache measureSpecs. * Called my measure method to cache measureSpecs.
*/ */
@ -515,6 +517,6 @@ declare module "ui/core/view" {
* @param attrValue - the value of the attribute (bold) * @param attrValue - the value of the attribute (bold)
* Should return true if this attribute is handled and there is no need default handler to process it. * Should return true if this attribute is handled and there is no need default handler to process it.
*/ */
applyXmlAttribute(attributeName: string, attrValue: any): boolean; _applyXmlAttribute(attributeName: string, attrValue: any): boolean;
} }
} }

View File

@ -446,7 +446,7 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
} }
} }
applyXmlAttribute(attributeName: string, attributeValue: any): boolean { _applyXmlAttribute(attributeName: string, attributeValue: any): boolean {
if (attributeName === "columns") { if (attributeName === "columns") {
this.setColumns(attributeValue); this.setColumns(attributeValue);
return true; return true;
@ -456,7 +456,7 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
return true; return true;
} }
return false; return super._applyXmlAttribute(attributeName, attributeValue);
} }
private static parseItemSpecs(value: string): Array<ItemSpec> { private static parseItemSpecs(value: string): Array<ItemSpec> {

View File

@ -25,7 +25,7 @@ var noStylingClasses = {};
export class Style extends observable.DependencyObservable implements styling.Style { export class Style extends observable.DependencyObservable implements styling.Style {
private _view: view.View; private _view: view.View;
private _inUpdate = false; private _updateCounter = 0;
private _nativeSetters = new Map<dependencyObservable.Property, any>(); private _nativeSetters = new Map<dependencyObservable.Property, any>();
get color(): color.Color { get color(): color.Color {
@ -265,13 +265,18 @@ export class Style extends observable.DependencyObservable implements styling.St
} }
public _beginUpdate() { public _beginUpdate() {
this._inUpdate = true; this._updateCounter++;
} }
public _endUpdate() { public _endUpdate() {
this._inUpdate = false; this._updateCounter--;
this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); }); if (this._updateCounter < 0) {
this._nativeSetters.clear(); throw new Error("style._endUpdate() called, but no update is in progress.");
}
if (this._updateCounter === 0) {
this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); });
this._nativeSetters.clear();
}
} }
public _resetCssValues() { public _resetCssValues() {
@ -334,7 +339,7 @@ export class Style extends observable.DependencyObservable implements styling.St
} }
private _applyStyleProperty(property: dependencyObservable.Property, newValue: any) { private _applyStyleProperty(property: dependencyObservable.Property, newValue: any) {
if (this._inUpdate) { if (this._updateCounter > 0) {
this._nativeSetters.set(property, newValue); this._nativeSetters.set(property, newValue);
return; return;
} }
@ -486,6 +491,7 @@ function onBackgroundImagePropertyChanged(data: observable.PropertyChangeData) {
var style = <Style>data.object; var style = <Style>data.object;
var url: string = data.newValue; var url: string = data.newValue;
var currentBackground = <background.Background>style._getValue(backgroundInternalProperty); var currentBackground = <background.Background>style._getValue(backgroundInternalProperty);
var isValid = false;
if (types.isString(data.newValue)) { if (types.isString(data.newValue)) {
var pattern: RegExp = /url\(('|")(.*?)\1\)/; var pattern: RegExp = /url\(('|")(.*?)\1\)/;
@ -498,9 +504,11 @@ function onBackgroundImagePropertyChanged(data: observable.PropertyChangeData) {
var base64Data = url.split(",")[1]; var base64Data = url.split(",")[1];
if (types.isDefined(base64Data)) { if (types.isDefined(base64Data)) {
style._setValue(backgroundInternalProperty, currentBackground.withImage(imageSource.fromBase64(base64Data))); style._setValue(backgroundInternalProperty, currentBackground.withImage(imageSource.fromBase64(base64Data)));
isValid = true;
} }
} else if (utils.isFileOrResourcePath(url)) { } else if (utils.isFileOrResourcePath(url)) {
style._setValue(backgroundInternalProperty, currentBackground.withImage(imageSource.fromFileOrResource(url))); style._setValue(backgroundInternalProperty, currentBackground.withImage(imageSource.fromFileOrResource(url)));
isValid = true;
} else if (url.indexOf("http") !== -1) { } else if (url.indexOf("http") !== -1) {
style["_url"] = url; style["_url"] = url;
style._setValue(backgroundInternalProperty, currentBackground.withImage(undefined)); style._setValue(backgroundInternalProperty, currentBackground.withImage(undefined));
@ -509,8 +517,13 @@ function onBackgroundImagePropertyChanged(data: observable.PropertyChangeData) {
style._setValue(backgroundInternalProperty, currentBackground.withImage(r)); style._setValue(backgroundInternalProperty, currentBackground.withImage(r));
} }
}); });
isValid = true;
} }
} }
if (!isValid) {
style._setValue(backgroundInternalProperty, currentBackground.withImage(undefined));
}
} }
function onBackgroundColorPropertyChanged(data: observable.PropertyChangeData) { function onBackgroundColorPropertyChanged(data: observable.PropertyChangeData) {