10000 (WIP) clearing stuff around the CssState · Cayan/NativeScript@8f3a68e · GitHub
[go: up one dir, main page]

Skip to content

Commit 8f3a68e

Browse files
committed
(WIP) clearing stuff around the CssState
1 parent 0b0598b commit 8f3a68e

File tree

8 files changed

+92
-71
lines changed

8 files changed

+92
-71
lines changed

apps/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"name": "tns-samples-apps",
3-
"main": "ui-tests-app/app.js"
3+
"main": "gallery-app/app.js"
44
}

apps/tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
"noImplicitAny": false,
99
"noImplicitUseStrict": true,
1010
"experimentalDecorators": true,
11-
"diagnostics": true,
12-
"sourceMap": true
11+
"diagnostics": true
1312
},
1413
"exclude": [
1514
"node_modules",

tests/app/app/mainPage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ page.on(Page.navigatedToEvent, onNavigatedTo);
2525

2626
function runTests() {
2727
setTimeout(function () {
28-
tests.runAll();
28+
tests.runAll("VALUE-SOURCE.test_value_Inherited_stronger_than_Default");
2929
}, 10);
3030
}
3131

tests/app/ui/styling/value-source-tests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export var test_value_Inherited_stronger_than_Default = function () {
1212
page.content = testStack;
1313
testStack.addChild(btn);
1414
page.css = "stackLayout { color: red; }";
15+
console.log("Btn color: " + btn.color);
1516
helper.assertViewColor(btn, "#FF0000");
1617
page.css = "";
1718
}

tns-core-modules/ui/core/view-base.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ declare module "ui/core/view-base" {
119119
_domId: number;
120120

121121
_cssState: any /* "ui/styling/style-scope" */;
122-
_setCssState(next: any /* "ui/styling/style-scope" */);
122+
_cssStateChanged();
123123

124124
_context: any /* android.content.Context */;
125125

tns-core-modules/ui/core/view-base.ts

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Property, InheritedProperty, Style, clearInheritedProperties, propagate
44
import { Binding, BindingOptions } from "ui/core/bindable";
55
import { isIOS, isAndroid } from "platform";
66
import { fromString as gestureFromString } from "ui/gestures";
7-
import { SelectorCore } from "ui/styling/css-selector";
7+
import { SelectorCore, ChangeMap } from "ui/styling/css-selector";
88
import { KeyframeAnimation } from "ui/animation/keyframe-animation";
99

1010
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet } from "trace";
@@ -126,7 +126,9 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
126126
public _context: any;
127127
public _isAddedToNativeVisualTree: boolean;
128128
public _isCssApplied: boolean;
129+
129130
public _cssState: ssm.CssState;
131+
private _cssChangeMap: ChangeMap<ViewBaseDefinition>;
130132

131133
constructor() {
132134
super();
@@ -188,6 +190,7 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
188190
this._isLoaded = true;
189191
this._loadEachChild();
190192
this._emit("loaded");
193+
this._subscribeForCssChanges();
191194
}
192195

193196
public _loadEachChild() {
@@ -198,7 +201,8 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
198201
}
199202

200203
public onUnloaded() {
201-
this._setCssState(null);
204+
this._unsubscribeFromCssChanges();
205+
202206
this._unloadEachChild();
203207
this._isLoaded = false;
204208
this._emit("unloaded");
@@ -225,61 +229,66 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
225229
this._isCssApplied = true;
226230
}
227231

228-
// TODO: Make sure the state is set to null and this is called on unloaded to clean up change listeners...
229-
_setCssState(next: ssm.CssState): void {
230-
const previous = this._cssState;
231-
this._cssState = next;
232+
_subscribeForCssChanges(): void {
233+
if (this._cssState) {
234+
if (!this._invalidateCssHandler) {
235+
this._invalidateCssHandler = () => {
236+
// TODO: Try to remove this flag: _invalidateCssHandlerSuspended
237+
if (this._invalidateCssHandlerSuspended) {
238+
console.log("Really?");
239+
return;
240+
}
241+
this.applyCssState();
242+
};
243+
}
244+
245+
this._cssState.changeMap.forEach((changes, view) => {
246+
if (changes.attributes) {
247+
changes.attributes.forEach(attribute => {
248+
view.addEventListener(attribute + "Change", this._invalidateCssHandler);
249+
});
250+
}
251+
if (changes.pseudoClasses) {
252+
changes.pseudoClasses.forEach(pseudoClass => {
253+
let eventName = ":" + pseudoClass;
254+
view.addEventListener(":" + pseudoClass, this._invalidateCssHandler);
255+
if (view[eventName]) {
256+
view[eventName](+1);
257+
}
258+
});
259+
}
260+
});
261+
this._unsubscribeFromCssChanges();
262+
this._cssChangeMap = this._cssState.changeMap;
263+
}
264+
}
232265

233-
if (!this._invalidateCssHandler) {
234-
this._invalidateCssHandler = () => {
235-
if (this._invalidateCssHandlerSuspended) {
236-
return;
266+
_unsubscribeFromCssChanges(): void {
267+
if (this._cssChangeMap) {
268+
this._cssChangeMap.forEach((changes, view) => {
269+
if (changes.attributes) {
270+
changes.attributes.forEach(attribute => {
271+
view.removeEventListener("onPropertyChanged:" + attribute, this._invalidateCssHandler);
272+
});
273+
}
274+
if (changes.pseudoClasses) {
275+
changes.pseudoClasses.forEach(pseudoClass => {
276+
let eventName = ":" + pseudoClass;
277+
view.removeEventListener(eventName, this._invalidateCssHandler);
278+
if (view[eventName]) {
279+
view[eventName](-1);
280+
}
281+
});
237282
}
238-
this.applyCssState();
239-
};
283+
});
284+
this._cssChangeMap = null;
240285
}
286+
}
241287

288+
_cssStateChanged(): void {
242289
try {
243290
this._invalidateCssHandlerSuspended = true;
244-
245-
if (next) {
246-
next.changeMap.forEach((changes, view) => {
247-
if (changes.attributes) {
248-
changes.attributes.forEach(attribute => {
249-
view.addEventListener(attribute + "Change", this._invalidateCssHandler);
250-
});
251-
}
252-
if (changes.pseudoClasses) {
253-
changes.pseudoClasses.forEach(pseudoClass => {
254-
let eventName = ":" + pseudoClass;
255-
view.addEventListener(":" + pseudoClass, this._invalidateCssHandler);
256-
if (view[eventName]) {
257-
view[eventName](+1);
258-
}
259-
});
260-
}
261-
});
262-
}
263-
264-
if (previous) {
265-
previous.changeMap.forEach((changes, view) => {
266-
if (changes.attributes) {
267-
changes.attributes.forEach(attribute => {
268-
view.removeEventListener("onPropertyChanged:" + attribute, this._invalidateCssHandler);
269-
});
270-
}
271-
if (changes.pseudoClasses) {
272-
changes.pseudoClasses.forEach(pseudoClass => {
273-
let eventName = ":" + pseudoClass;
274-
view.removeEventListener(eventName, this._invalidateCssHandler);
275-
if (view[eventName]) {
276-
view[eventName](-1);
277-
}
278-
});
279-
}
280-
});
281-
}
282-
291+
this._subscribeForCssChanges();
283292
} finally {
284293
this._invalidateCssHandlerSuspended = false;
285294
}
@@ -302,9 +311,7 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
302311
return;
303312
}
304313

305-
// this.style._beginUpdate();
306314
this._cssState.apply();
307-
// this.style._endUpdate();
308315
}
309316

310317
private pseudoClassAliases = {

tns-core-modules/ui/styling/style-scope.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ declare module "ui/styling/style-scope" {
1212
public apply(): void;
1313

1414
/**
15-
* Gets the static selectors that match the view and the dynamic selectors that may potentially match the view.
15+
* Gets the views, attributes and pseudoclasses that may potentially change the selectors that match the view.
1616
*/
1717
public changeMap: ChangeMap<ViewBase>;
1818
}

tns-core-modules/ui/styling/style-scope.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ let pattern: RegExp = /('|")(.*?)\1/;
3030
export class CssState {
3131
private setters: { [key: string]: string | any } = {};
3232
private animations = new Map<kam.KeyframeAnimationInfo, kam.KeyframeAnimation>();
33+
private match: SelectorsMatch<ViewBase>;
3334

34-
constructor(private view: ViewBase, private match: SelectorsMatch<ViewBase>) {
35+
constructor(private view: ViewBase) {
3536
}
3637

3738
// TODO: Expose "SelectorsMatch<ViewBase>" property to be set when a view gets new CssState instead of making new CssState instances...
@@ -41,6 +42,8 @@ export class CssState {
4142
}
4243

4344
public apply(): void {
45+
// this.style._beginUpdate();
46+
4447
// TODO: iOS views have some scoping that controls animations, apply something here.
4548

4649
let newSelectors = this.match.selectors.filter(sel => sel.dynamic ? sel.match(this.view) : true);
@@ -54,14 +57,17 @@ export class CssState {
5457
let newAnimations = new Map<kam.KeyframeAnimationInfo, kam.KeyframeAnimation>();
5558
newSelectors.forEach(s => {
5659
s.ruleset.declarations.forEach(d => {
57-
let values = ShorthandProperty._split(d);
58-
let shorthand = ShorthandProperty._split(d);
59-
if (shorthand) {
60-
for (let [k, v] of shorthand) {
61-
newComputedCss[k.cssLocalName] = v;
60+
try {
61+
let shorthand = ShorthandProperty._split(d);
62+
if (shorthand) {
63+
for (let [k, v] of shorthand) {
64+
newComputedCss[k.cssLocalName] = v;
65+
}
66+
} else {
67+
newComputedCss[d.property] = d.value;
6268
}
63-
} else {
64-
newComputedCss[d.property] = d.value;
69+
} catch(e) {
70+
traceWrite(`Failed to apply property [${d.property}] with value [${d.value}] to ${this.view}. ${e}`, traceCategories.Error, traceMessageType.error);
6571
}
6672
});
6773
let rulesetAnimations: kam.KeyframeAnimationInfo[] = s.ruleset[animationsSymbol];
@@ -75,12 +81,15 @@ export class CssState {
7581
this.animations.forEach((anim, info) => {
7682
if (anim.isPlaying && !newAnimations.has(info)) {
7783
anim.cancel();
84+
// TODO: Canceling the animation doesn't seem to clear well all values.
7885
}
7986
});
8087
if (newAnimations.size > 0 && this.view.isLoaded && this.view.nativeView) {
8188
ensureKeyframeAnimationModule();
8289
newAnimations.forEach((animation, animationInfo) => {
83-
if (!this.animations.has(animationInfo)) {
90+
if (this.animations.has(animationInfo)) {
91+
newAnimations.set(animationInfo, this.animations.get(animationInfo));
92+
} else {
8493
let animation = keyframeAnimationModule.KeyframeAnimation.keyframeAnimationFromInfo(animationInfo);
8594
newAnimations.set(animationInfo, animation);
8695
animation.play(this.view);
@@ -117,6 +126,8 @@ export class CssState {
117126
}
118127
}
119128
this.setters = newComputedCss;
129+
130+
// this.style._endUpdate();
120131
}
121132
}
122133

@@ -255,11 +266,14 @@ export class StyleScope {
255266

256267
public applySelectors(view: ViewBase): void {
257268
this.ensureSelectors();
269+
let match = this._selectors.query(view);
258270

259-
let state = this._selectors.query(view);
271+
if (!view._cssState) {
272+
view._cssState = new CssState(view);
273+
}
260274

261-
let nextState = new CssState(view, state);
262-
view._setCssState(nextState);
275+
view._cssState.match = match;
276+
view._cssStateChanged();
263277
}
264278

265279
public query(node: Node): SelectorCore[] {

0 commit comments

Comments
 (0)
0