Skip to content

Commit 43bdef0

Browse files
committed
Update Renderer to support precompiled views.
1 parent 64dccbf commit 43bdef0

File tree

2 files changed

+156
-173
lines changed

2 files changed

+156
-173
lines changed

src/nativescript-angular/renderer.ts

Lines changed: 117 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,94 @@
1-
import {Injectable} from 'angular2/angular2';
2-
import {MapWrapper} from 'angular2/src/core/facade/collection';
3-
import {DomProtoView, resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
1+
import {Inject, Injectable} from 'angular2/src/core/di';
2+
import {DOCUMENT} from 'angular2/src/core/render/dom/dom_tokens';
3+
import {createRenderView, NodeFactory} from 'angular2/src/core/render/view_factory';
44
import {
55
Renderer,
66
RenderEventDispatcher,
77
RenderElementRef,
88
RenderProtoViewRef,
99
RenderViewRef,
1010
RenderFragmentRef,
11-
RenderViewWithFragments
11+
RenderViewWithFragments,
12+
RenderTemplateCmd
1213
} from 'angular2/src/core/render/api';
13-
import {DefaultProtoViewRef} from 'angular2/src/core/render/view';
14-
import {NG_BINDING_CLASS, cloneAndQueryProtoView} from 'angular2/src/core/render/dom/util';
14+
import {isBlank} from 'angular2/src/core/facade/lang';
15+
import {
16+
DefaultProtoViewRef,
17+
DefaultRenderView,
18+
DefaultRenderFragmentRef
19+
} from 'angular2/src/core/render/view';
1520
import {DOM} from 'angular2/src/core/dom/dom_adapter';
16-
1721
import {ViewNode, DummyViewNode} from 'nativescript-angular/view_node';
1822

19-
export class NativeScriptView {
20-
public eventDispatcher: RenderEventDispatcher;
21-
22-
constructor(
23-
public proto: DomProtoView,
24-
public rootChildElements,
25-
public boundElements: Array<ViewNode>) {
26-
}
27-
28-
getBoundNode(index: number): ViewNode {
29-
return this.boundElements[index];
30-
}
31-
}
23+
@Injectable()
24+
export class NativeScriptRenderer extends Renderer implements NodeFactory<ViewNode> {
25+
private _document;
3226

33-
export class NativeScriptViewRef extends RenderViewRef {
34-
_view: NativeScriptView;
35-
constructor(view: NativeScriptView) {
27+
constructor(@Inject(DOCUMENT) document) {
3628
super();
37-
this._view = view;
29+
console.log('NativeScriptRenderer created');
30+
this._document = document;
3831
}
3932

40-
resolveView(): NativeScriptView {
41-
return this._view;
33+
public createProtoView(cmds: RenderTemplateCmd[]): RenderProtoViewRef {
34+
console.log('NativeScriptRenderer.createProtoView: ' + cmds);
35+
return new DefaultProtoViewRef(cmds);
4236
}
43-
}
4437

45-
export class NativeScriptFragmentRef extends RenderFragmentRef {
46-
constructor(private nodes: ViewNode[]) {
47-
super();
48-
}
38+
public createRootHostView(
39+
hostProtoViewRef: RenderProtoViewRef,
40+
fragmentCount: number,
41+
hostElementSelector: string
42+
): RenderViewWithFragments {
43+
console.log("NativeScriptRenderer.createRootHostView");
4944

50-
resolveNodes(): ViewNode[] {
51-
return this.nodes;
52-
}
53-
}
45+
let rootViewWithFragments = this._createView(hostProtoViewRef, null);
5446

55-
@Injectable()
56-
export class NativeScriptRenderer extends Renderer {
57-
constructor() {
58-
super();
59-
console.log('NativeScriptRenderer created');
60-
}
47+
let rootView = resolveInternalDomView(rootViewWithFragments.viewRef);
48+
let rootNode = rootView.boundElements[0];
49+
rootNode.attachToView();
6150

62-
createRootHostView(hostProtoViewRef: RenderProtoViewRef,
63-
fragmentCount: number,
64-
hostElementSelector: string): RenderViewWithFragments {
65-
console.log("NativeScriptRenderer.createRootHostView");
66-
var hostProtoView = resolveInternalDomProtoView(hostProtoViewRef);
67-
//return new NativeScriptViewRef(this._createView(hostProtoView, null, true));
68-
return this._createView(hostProtoView, null, true);
51+
return rootViewWithFragments;
6952
}
7053

71-
detachFreeHostView(parentHostViewRef: RenderViewRef, hostViewRef: RenderViewRef) {
72-
console.log("NativeScriptRenderer.detachFreeHostView");
54+
public createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
55+
console.log("NativeScriptRenderer.createView");
56+
return this._createView(protoViewRef, null);
7357
}
7458

75-
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
76-
console.log("NativeScriptRenderer.createView");
77-
var protoView = resolveInternalDomProtoView(protoViewRef);
78-
//return new NativeScriptViewRef(this._createView(protoView, null, false));
79-
return this._createView(protoView, null, false);
59+
private _createView(protoViewRef: RenderProtoViewRef, inplaceElement: HTMLElement): RenderViewWithFragments {
60+
var view = createRenderView((<DefaultProtoViewRef>protoViewRef).cmds, inplaceElement, this);
61+
return new RenderViewWithFragments(view, view.fragments);
8062
}
8163

82-
destroyView(viewRef: RenderViewRef) {
64+
public destroyView(viewRef: RenderViewRef) {
8365
console.log("NativeScriptRenderer.destroyView");
8466
// Seems to be called on component dispose only (router outlet)
8567
//TODO: handle this when we resolve routing and navigation.
8668
}
8769

88-
attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef, fragmentRef: RenderFragmentRef) {
70+
public getRootNodes(fragment: RenderFragmentRef): ViewNode[] {
71+
return resolveInternalDomFragment(fragment);
72+
}
73+
74+
public attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef, fragmentRef: RenderFragmentRef) {
8975
console.log("NativeScriptRenderer.attachFragmentAfterFragment");
90-
var previousFragmentNodes = (<NativeScriptFragmentRef>previousFragmentRef).resolveNodes();
91-
var lastNode: ViewNode = previousFragmentNodes[previousFragmentNodes.length - 1];
92-
var fragmentNodes = (<NativeScriptFragmentRef>fragmentRef).resolveNodes();
9376

94-
this.attachFragmentAfter(lastNode, fragmentNodes);
77+
var previousFragmentNodes = resolveInternalDomFragment(previousFragmentRef);
78+
if (previousFragmentNodes.length > 0) {
79+
var sibling = previousFragmentNodes[previousFragmentNodes.length - 1];
80+
let nodes = resolveInternalDomFragment(fragmentRef);
81+
this.attachFragmentAfter(sibling, nodes);
82+
}
9583
}
9684

97-
attachFragmentAfterElement(location: RenderElementRef, fragmentRef: RenderFragmentRef) {
85+
public attachFragmentAfterElement(location: RenderElementRef, fragmentRef: RenderFragmentRef) {
9886
console.log("NativeScriptRenderer.attachFragmentAfterElement");
99-
var hostView = (<NativeScriptViewRef>location.renderView).resolveView();
100-
var startNode: ViewNode = hostView.getBoundNode(location.renderBoundElementIndex);
101-
var fragmentNodes = (<NativeScriptFragmentRef>fragmentRef).resolveNodes();
10287

103-
this.attachFragmentAfter(startNode, fragmentNodes);
88+
var parentView = resolveInternalDomView(location.renderView);
89+
var element = parentView.boundElements[location.boundElementIndex];
90+
var nodes = resolveInternalDomFragment(fragmentRef);
91+
this.attachFragmentAfter(element, nodes);
10492
}
10593

10694
private attachFragmentAfter(anchorNode: ViewNode, fragmentNodes: ViewNode[]) {
@@ -114,9 +102,9 @@ export class NativeScriptRenderer extends Renderer {
114102
}
115103

116104
detachFragment(fragmentRef: RenderFragmentRef) {
117-
//TODO: implement...
118105
console.log('NativeScriptRenderer.detachFragment');
119-
var fragmentNodes = (<NativeScriptFragmentRef>fragmentRef).resolveNodes();
106+
107+
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
120108
fragmentNodes.forEach((node) => {
121109
console.log('detaching fragment child: ' + node.viewName);
122110
if (node.parentNode)
@@ -137,8 +125,8 @@ export class NativeScriptRenderer extends Renderer {
137125
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any) {
138126
console.log("NativeScriptRenderer.setElementProperty " + propertyName + " = " + propertyValue);
139127

140-
var view = (<NativeScriptViewRef>location.renderView).resolveView();
141-
var node = view.getBoundNode(location.renderBoundElementIndex);
128+
var view = resolveInternalDomView(location.renderView);
129+
var node = view.boundElements[location.boundElementIndex];
142130
node.setProperty(propertyName, propertyValue);
143131
}
144132

@@ -150,8 +138,8 @@ export class NativeScriptRenderer extends Renderer {
150138
setElementClass(location: RenderElementRef, className: string, isAdd: boolean): void {
151139
console.log("NativeScriptRenderer.setElementClass " + className + " - " + isAdd);
152140

153-
var view = (<NativeScriptViewRef>location.renderView).resolveView();
154-
var node = view.getBoundNode(location.renderBoundElementIndex);
141+
var view = resolveInternalDomView(location.renderView);
142+
var node = view.boundElements[location.boundElementIndex];
155143
if (isAdd) {
156144
node.addClass(className);
157145
} else {
@@ -162,8 +150,8 @@ export class NativeScriptRenderer extends Renderer {
162150
getNativeElementSync(location: RenderElementRef): any {
163151
console.log("NativeScriptRenderer.getNativeElementSync");
164152

165-
var view = (<NativeScriptViewRef>location.renderView).resolveView();
166-
var node = view.getBoundNode(location.renderBoundElementIndex);
153+
var view = resolveInternalDomView(location.renderView);
154+
var node = view.boundElements[location.boundElementIndex];
167155
return node.nativeView;
168156
}
169157

@@ -180,91 +168,73 @@ export class NativeScriptRenderer extends Renderer {
180168

181169
setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher) {
182170
console.log("NativeScriptRenderer.setEventDispatcher ");
183-
var view = (<NativeScriptViewRef>viewRef).resolveView();
171+
var view = resolveInternalDomView(viewRef);
184172
view.eventDispatcher = dispatcher;
185173
}
186174

187-
_createView(proto: DomProtoView, inplaceElement: HTMLElement, isRoot = false): RenderViewWithFragments {
188-
console.log("NativeScriptRenderer._createView ");
175+
private _componentCmds: Map<number, RenderTemplateCmd[]> = new Map<number, RenderTemplateCmd[]>();
189176

190-
var clonedProtoView = cloneAndQueryProtoView(this._templateCloner, proto, true);
177+
public registerComponentTemplate(
178+
templateId: number,
179+
commands: RenderTemplateCmd[],
180+
styles: string[],
181+
nativeShadow: boolean
182+
) {
183+
console.log('NativeScriptRenderer.registerComponentTemplate: ' + templateId);
184+
this._componentCmds.set(templateId, commands);
185+
}
191186

192-
var nativeElements: Array<ViewNode>;
193-
var boundElements: Array<ViewNode> = [];
187+
public resolveComponentTemplate(templateId: number): RenderTemplateCmd[] {
188+
console.log('NativeScriptRenderer.resolveComponentTemplate: ' + templateId);
189+
return this._componentCmds.get(templateId);
190+
}
194191

195-
var templateRoot = clonedProtoView.fragments[0][0];
196-
nativeElements = this._createNodes(null, [templateRoot], boundElements);
192+
public createTemplateAnchor(attrNameAndValues: string[]): ViewNode {
193+
console.log('NativeScriptRenderer.createTemplateAnchor');
194+
return new ViewNode(null, 'template', attrNameAndValues);
195+
}
197196

198-
if (isRoot) {
199-
nativeElements[0].attachToView();
200-
}
197+
public createElement(name: string, attrNameAndValues: string[]): ViewNode {
198+
console.log('NativeScriptRenderer.createElement: ' + name);
199+
return new ViewNode(null, name, attrNameAndValues);
200+
}
201201

202-
var view = new NativeScriptView(proto, nativeElements, boundElements);
202+
public mergeElement(existing: ViewNode, attrNameAndValues: string[]){
203+
console.log('NativeScriptRenderer.mergeElement: ' + existing.viewName);
204+
console.dump(existing);
205+
existing.clearChildren();
206+
existing.setAttributeValues(attrNameAndValues);
207+
}
203208

204-
var binders = proto.elementBinders;
205-
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
206-
var binder = binders[binderIdx];
207-
var viewNode = boundElements[binderIdx];
209+
public createShadowRoot(host: ViewNode, templateId: number): ViewNode {
210+
throw new Error('Not implemented.');
211+
}
208212

209-
// events
210-
if (binder.eventLocals != null && binder.localEvents != null) {
211-
for (var i = 0; i < binder.localEvents.length; i++) {
212-
viewNode.createEventListener(view, binderIdx, binder.localEvents[i].name, binder.eventLocals);
213-
}
214-
}
215-
}
213+
public createText(value: string): ViewNode {
214+
console.log('NativeScriptRenderer.createText');
215+
return new DummyViewNode(null);
216+
}
216217

217-
let fragments = clonedProtoView.fragments.map(nodes => {
218-
console.log('Fragment with nodes: ' + nodes.length + ' first: ' + (<any>nodes[0]).name);
219-
return new NativeScriptFragmentRef(nativeElements)
220-
})
221-
return new RenderViewWithFragments(
222-
new NativeScriptViewRef(view), fragments);
218+
public appendChild(parent: ViewNode, child: ViewNode) {
219+
console.log('NativeScriptRenderer.appendChild: ' + parent.viewName + ' -> ' + child.viewName);
220+
parent.appendChild(child);
223221
}
224222

225-
_createNodes(parent: ViewNode, parsedChildren, boundElements: Array<ViewNode>): Array<ViewNode> {
226-
console.log('NativeScriptRenderer._createNodes ' + (parent ? parent.viewName : 'NULL'));
227-
var viewNodes = [];
228-
parsedChildren.forEach(node => {
229-
var viewNode: ViewNode;
230-
if (node.type == "tag") {
231-
if (node.name.indexOf('itemtemplate') >= 0) {
232-
// all lowercased. the only thing that can work here
233-
// is kebab-cased tags and attributes.
234-
let templateString = DOM.getInnerHTML(node);
235-
parent.setAttribute('itemTemplate', templateString);
236-
// return a view node even if we do nothing with it so that
237-
// index-based binding configuration doesn't break for bound
238-
// nodes coming after.
239-
viewNode = new DummyViewNode(parent);
240-
} else {
241-
viewNode = new ViewNode(parent, node.name, node.attribs);
242-
}
243-
} else if (node.type == "text") {
244-
//viewNode = new ViewNode(parent, "rawtext", {text: node.data});
245-
//Ignore text nodes
246-
return;
247-
} else if (node.type == "root") {
248-
//viewNode = new ViewNode(parent, "root", {});
249-
//Ignore "root" elements.
250-
return;
251-
} else {
252-
console.dump(node);
253-
throw new Error('Unknown parse node type');
254-
}
255-
256-
if (DOM.hasClass(node, NG_BINDING_CLASS)) {
257-
boundElements.push(viewNode);
258-
}
259-
260-
if (node.children) {
261-
var children = this._createNodes(viewNode, node.children, boundElements);
262-
children.forEach((childViewNode, index) => {
263-
viewNode.insertChildAt(index, childViewNode);
264-
});
265-
}
266-
viewNodes.push(viewNode)
267-
});
268-
return viewNodes;
223+
public on(element: ViewNode, eventName: string, callback: Function) {
224+
console.log('NativeScriptRenderer.on: ' + eventName);
225+
let zonedCallback = global.zone.bind(callback);
226+
element.on(eventName, zonedCallback);
227+
}
228+
229+
public globalOn(target: string, eventName: string, callback: Function): Function {
230+
throw new Error('Not implemented.');
269231
}
270232
}
233+
234+
function resolveInternalDomView(viewRef: RenderViewRef): DefaultRenderView<ViewNode> {
235+
return <DefaultRenderView<ViewNode>>viewRef;
236+
}
237+
238+
function resolveInternalDomFragment(fragmentRef: RenderFragmentRef): ViewNode[] {
239+
return (<DefaultRenderFragmentRef<ViewNode>>fragmentRef).nodes;
240+
}

0 commit comments

Comments
 (0)