diff --git a/apps/tests/pages/background-test.ts b/apps/tests/pages/background-test.ts index d3fc95ba5..17f9c2096 100644 --- a/apps/tests/pages/background-test.ts +++ b/apps/tests/pages/background-test.ts @@ -1,10 +1,13 @@ import view = require("ui/core/view"); +import pages = require("ui/page"); + export function applyTap(args) { - var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); - (el).style = args.object.tag; + var page = view.getAncestor(args.object, "Page"); + var css = "#test-element { " + args.object.tag + " }"; + page.css = css; } export function resetTap(args) { - var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); - (el).style = ""; + var page = view.getAncestor(args.object, "Page"); + page.css = ""; } \ No newline at end of file diff --git a/apps/tests/ui/style/style-properties-tests.ts b/apps/tests/ui/style/style-properties-tests.ts index 729dc2051..a0ce35e5d 100644 --- a/apps/tests/ui/style/style-properties-tests.ts +++ b/apps/tests/ui/style/style-properties-tests.ts @@ -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) { var testView = new buttonModule.Button(); - (testView).style = "font: " + short; + (testView.style)["font"] = short; TKUnit.assertEqual(testView.style.fontFamily, family, "style.fontFamily"); TKUnit.assertEqual(testView.style.fontStyle, style, "style.fontStyle"); diff --git a/apps/tests/ui/style/style-tests.ts b/apps/tests/ui/style/style-tests.ts index e022d9efd..66a35a762 100644 --- a/apps/tests/ui/style/style-tests.ts +++ b/apps/tests/ui/style/style-tests.ts @@ -99,23 +99,23 @@ export function test_type_selector() { var pageFactory = function (): pageModule.Page { page = new pageModule.Page(); - // - // ### Using type selector - // ``` JavaScript - page.css = "button { color: red; }"; + // + // ### Using type selector + // ``` JavaScript + page.css = "button { color: red; }"; - //// Will be styled + //// Will be styled btn = new buttonModule.Button(); - //// Won't be styled + //// Won't be styled label = new labelModule.Label(); - // ``` - // + // ``` + // - var stack = new stackModule.StackLayout(); - page.content = stack; - stack.addChild(label); - stack.addChild(btn); + var stack = new stackModule.StackLayout(); + page.content = stack; + stack.addChild(label); + stack.addChild(btn); return page; }; @@ -135,24 +135,24 @@ export function test_class_selector() { var pageFactory = function (): pageModule.Page { page = new pageModule.Page(); - // - // ### Using class selector - // ``` JavaScript - page.css = ".test { color: red; }"; + // + // ### Using class selector + // ``` JavaScript + page.css = ".test { color: red; }"; - //// Will be styled + //// Will be styled btnWithClass = new buttonModule.Button(); - btnWithClass.cssClass = "test"; + btnWithClass.cssClass = "test"; - //// Won't be styled + //// Won't be styled btnWithNoClass = new buttonModule.Button(); - // ``` - // + // ``` + // - var stack = new stackModule.StackLayout(); - page.content = stack; - stack.addChild(btnWithClass); - stack.addChild(btnWithNoClass); + var stack = new stackModule.StackLayout(); + page.content = stack; + stack.addChild(btnWithClass); + stack.addChild(btnWithNoClass); return page; }; @@ -199,24 +199,24 @@ export function test_id_selector() { var pageFactory = function (): pageModule.Page { page = new pageModule.Page(); - // - // ### Using id selector - // ``` JavaScript - page.css = "#myButton { color: red; }"; + // + // ### Using id selector + // ``` JavaScript + page.css = "#myButton { color: red; }"; - //// Will be styled + //// Will be styled btnWithId = new buttonModule.Button(); - btnWithId.id = "myButton"; + btnWithId.id = "myButton"; - //// Won't be styled + //// Won't be styled btnWithNoId = new buttonModule.Button(); - // ``` - // + // ``` + // - var stack = new stackModule.StackLayout(); - page.content = stack; - stack.addChild(btnWithId); - stack.addChild(btnWithNoId); + var stack = new stackModule.StackLayout(); + page.content = stack; + stack.addChild(btnWithId); + stack.addChild(btnWithNoId); return page; }; @@ -234,13 +234,13 @@ export function test_state_selector() { var page: pageModule.Page; var btn: buttonModule.Button; var pageFactory = function (): pageModule.Page { - // Arrange + // Arrange page = new pageModule.Page(); - var testStack = new stackModule.StackLayout(); + var testStack = new stackModule.StackLayout(); page.content = testStack; btn = new buttonModule.Button(); - testStack.addChild(btn); + testStack.addChild(btn); page.css = ":pressed { color: red; }"; return page; @@ -260,18 +260,18 @@ export function test_type_and_state_selector() { var pageFactory = function (): pageModule.Page { page = new pageModule.Page(); - // - // ### Using state selector - // ``` JavaScript - page.css = "button:pressed { color: red; }"; + // + // ### Using state selector + // ``` JavaScript + page.css = "button:pressed { color: red; }"; - //// Will be red when pressed + //// Will be red when pressed btn = new buttonModule.Button(); - // ``` - // - var stack = new stackModule.StackLayout(); - page.content = stack; - stack.addChild(btn); + // ``` + // + var stack = new stackModule.StackLayout(); + page.content = stack; + stack.addChild(btn); return page; }; @@ -287,14 +287,14 @@ export function test_class_and_state_selector() { var page: pageModule.Page; var btn: buttonModule.Button; var pageFactory = function (): pageModule.Page { - // Arrange + // Arrange page = new pageModule.Page(); - var testStack = new stackModule.StackLayout(); + var testStack = new stackModule.StackLayout(); page.content = testStack; btn = new buttonModule.Button(); - btn.cssClass = "test" - testStack.addChild(btn); + btn.cssClass = "test" + testStack.addChild(btn); page.css = ".test:pressed { color: red; }"; return page; @@ -337,14 +337,14 @@ export function test_id_and_state_selector() { var page: pageModule.Page; var btn: buttonModule.Button; var pageFactory = function (): pageModule.Page { - // Arrange + // Arrange page = new pageModule.Page(); - var testStack = new stackModule.StackLayout(); + var testStack = new stackModule.StackLayout(); page.content = testStack; btn = new buttonModule.Button(); - btn.id = "myButton"; - testStack.addChild(btn); + btn.id = "myButton"; + testStack.addChild(btn); page.css = "#myButton:pressed { color: red; }"; return page; @@ -362,16 +362,16 @@ export function test_restore_original_values_when_state_is_changed() { var page: pageModule.Page; var btn: buttonModule.Button; var pageFactory = function (): pageModule.Page { - // Arrange + // Arrange page = new pageModule.Page(); - var testStack = new stackModule.StackLayout(); + var testStack = new stackModule.StackLayout(); page.content = testStack; btn = new buttonModule.Button(); - testStack.addChild(btn); + testStack.addChild(btn); page.css = "button { color: blue; } " + - "button:pressed { color: red; } "; + "button:pressed { color: red; } "; return page; }; @@ -483,7 +483,7 @@ export var test_style_is_applied_when_control_is_added_after_load = function () }; helper.navigate(pageFactory); - + testStack.addChild(btn); TKUnit.assert(btn.style.color, "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 pageFactory = function (): pageModule.Page { page = new pageModule.Page(); - var testStack = new stackModule.StackLayout(); + var testStack = new stackModule.StackLayout(); page.content = testStack; btn = new buttonModule.Button(); - testStack.addChild(btn); + testStack.addChild(btn); btnWithClass = new buttonModule.Button(); - btnWithClass.cssClass = "button-class"; - testStack.addChild(btnWithClass); + btnWithClass.cssClass = "button-class"; + testStack.addChild(btnWithClass); btnWithId = new buttonModule.Button(); - btnWithId.cssClass = "button-class"; - btnWithId.id = "myButton" - testStack.addChild(btnWithId); + btnWithId.cssClass = "button-class"; + btnWithId.id = "myButton" + testStack.addChild(btnWithId); page.css = css; 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(); - testButton.text = "Test"; - testButton.style.fontSize = 10; - var stack = new stackModule.StackLayout(); - stack.addChild(testButton); - helper.buildUIAndRunTest(stack, function (views: Array) { - (testButton)._applyInlineStyle("color: red;"); - helper.assertViewColor(testButton, "#FF0000", dependencyObservableModule.ValueSource.Local); - 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"); - }); + TKUnit.assertThrows(function () { + (testButton).style = "background-color: red;"; + }, "View.style property is read-only."); } export var test_CSS_isAppliedOnPage = function () { diff --git a/apps/ui-tests-app/pages/background.ts b/apps/ui-tests-app/pages/background.ts index d3fc95ba5..17f9c2096 100644 --- a/apps/ui-tests-app/pages/background.ts +++ b/apps/ui-tests-app/pages/background.ts @@ -1,10 +1,13 @@ import view = require("ui/core/view"); +import pages = require("ui/page"); + export function applyTap(args) { - var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); - (el).style = args.object.tag; + var page = view.getAncestor(args.object, "Page"); + var css = "#test-element { " + args.object.tag + " }"; + page.css = css; } export function resetTap(args) { - var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element"); - (el).style = ""; + var page = view.getAncestor(args.object, "Page"); + page.css = ""; } \ No newline at end of file diff --git a/text/span-common.ts b/text/span-common.ts index f2acb5ca1..f52826de9 100644 --- a/text/span-common.ts +++ b/text/span-common.ts @@ -18,7 +18,7 @@ export class Span extends bindable.Bindable implements definition.Span, view.App private _spanModifiers: Array; private _parentFormattedString: formattedString.FormattedString; private _isInEditMode: boolean; - + get fontFamily(): string { return this._fontFamily; } @@ -157,7 +157,7 @@ export class Span extends bindable.Bindable implements definition.Span, view.App } public updateSpanModifiers(parent: formattedString.FormattedString) { - // a virtual method overriden in platform specific implementations. + // a virtual method overridden in platform specific implementations. if (this._isInEditMode) { 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(); } - public applyXmlAttribute(attribute, value): boolean { + public _applyXmlAttribute(attribute, value): boolean { if (attribute === "fontAttributes") { if (value.indexOf(",")) { var fontAttr = value.split(","); diff --git a/ui/builder/component-builder.ts b/ui/builder/component-builder.ts index 5f2c66dee..7d20422c1 100644 --- a/ui/builder/component-builder.ts +++ b/ui/builder/component-builder.ts @@ -174,8 +174,8 @@ export function setPropertyValue(instance: view.View, instanceModule: Object, ex } else { var attrHandled = false; - if ((instance).applyXmlAttribute) { - attrHandled = (instance).applyXmlAttribute(propertyName, propertyValue); + if ((instance)._applyXmlAttribute) { + attrHandled = (instance)._applyXmlAttribute(propertyName, propertyValue); } if (!attrHandled) { diff --git a/ui/core/view-common.ts b/ui/core/view-common.ts index c3b6f3f9a..8e63e4621 100644 --- a/ui/core/view-common.ts +++ b/ui/core/view-common.ts @@ -389,7 +389,7 @@ export class View extends proxy.ProxyObject implements definition.View { return this._style; } set style(value) { - this._applyInlineStyle(value); + throw new Error("View.style property is read-only."); } get isLayoutValid(): boolean { @@ -763,7 +763,6 @@ export class View extends proxy.ProxyObject implements definition.View { if (types.isString(inlineStyle)) { try { this.style._beginUpdate(); - this.style._resetLocalValues(); styleScope.applyInlineSyle(this, inlineStyle); } finally { this.style._endUpdate(); @@ -942,6 +941,15 @@ export class View extends proxy.ProxyObject implements definition.View { this._requestedVisualState = state; } + public _applyXmlAttribute(attribute, value): boolean { + if (attribute === "style") { + this._applyInlineStyle(value); + return true; + } + + return false; + } + public _updateLayout() { // needed for iOS. } diff --git a/ui/core/view.d.ts b/ui/core/view.d.ts index be8c9bb3a..b2011359a 100644 --- a/ui/core/view.d.ts +++ b/ui/core/view.d.ts @@ -94,7 +94,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 { + export class View extends proxy.ProxyObject implements ApplyXmlAttributes { /** * Gets or sets the corner radius of the view. */ @@ -441,6 +441,8 @@ declare module "ui/core/view" { _updateLayout(): void; + _applyXmlAttribute(attribute, value): boolean; + /** * Called my measure method to cache measureSpecs. */ @@ -515,6 +517,6 @@ declare module "ui/core/view" { * @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. */ - applyXmlAttribute(attributeName: string, attrValue: any): boolean; + _applyXmlAttribute(attributeName: string, attrValue: any): boolean; } } \ No newline at end of file diff --git a/ui/layouts/grid-layout/grid-layout.ts b/ui/layouts/grid-layout/grid-layout.ts index c62b96de0..df8bc5727 100644 --- a/ui/layouts/grid-layout/grid-layout.ts +++ b/ui/layouts/grid-layout/grid-layout.ts @@ -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") { this.setColumns(attributeValue); return true; @@ -456,7 +456,7 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout, return true; } - return false; + return super._applyXmlAttribute(attributeName, attributeValue); } private static parseItemSpecs(value: string): Array { diff --git a/ui/styling/style.ts b/ui/styling/style.ts index 6040fb794..e52f2d263 100644 --- a/ui/styling/style.ts +++ b/ui/styling/style.ts @@ -25,7 +25,7 @@ var noStylingClasses = {}; export class Style extends observable.DependencyObservable implements styling.Style { private _view: view.View; - private _inUpdate = false; + private _updateCounter = 0; private _nativeSetters = new Map(); get color(): color.Color { @@ -265,13 +265,18 @@ export class Style extends observable.DependencyObservable implements styling.St } public _beginUpdate() { - this._inUpdate = true; + this._updateCounter++; } public _endUpdate() { - this._inUpdate = false; - this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); }); - this._nativeSetters.clear(); + this._updateCounter--; + if (this._updateCounter < 0) { + 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() { @@ -334,7 +339,7 @@ export class Style extends observable.DependencyObservable implements styling.St } private _applyStyleProperty(property: dependencyObservable.Property, newValue: any) { - if (this._inUpdate) { + if (this._updateCounter > 0) { this._nativeSetters.set(property, newValue); return; } @@ -486,6 +491,7 @@ function onBackgroundImagePropertyChanged(data: observable.PropertyChangeData) { var style =