Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: sky/framework/layout.dart

Issue 1117143003: [Effen] Port fn.dart from the legacy sky.Node backend to the RenderNode backend, which is currently… (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Tweak debug functions as suggested Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/framework/fn.dart ('k') | sky/framework/node.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 library layout;
2
3 import 'node.dart';
4 import 'dart:sky' as sky;
5 import 'dart:collection';
6
7 // UTILS
8
9 // Bridge to legacy CSS-like style specification
10 // Eventually we'll replace this with something else
11 class Style {
12 final String _className;
13 static final Map<String, Style> _cache = new HashMap<String, Style>();
14
15 static int _nextStyleId = 1;
16
17 static String _getNextClassName() { return "style${_nextStyleId++}"; }
18
19 Style extend(Style other) {
20 var className = "$_className ${other._className}";
21
22 return _cache.putIfAbsent(className, () {
23 return new Style._internal(className);
24 });
25 }
26
27 factory Style(String styles) {
28 return _cache.putIfAbsent(styles, () {
29 var className = _getNextClassName();
30 sky.Element styleNode = sky.document.createElement('style');
31 styleNode.setChild(new sky.Text(".$className { $styles }"));
32 sky.document.appendChild(styleNode);
33 return new Style._internal(className);
34 });
35 }
36
37 Style._internal(this._className);
38 }
39
40 class Rect {
41 const Rect(this.x, this.y, this.width, this.height);
42 final double x;
43 final double y;
44 final double width;
45 final double height;
46 }
47
48
49 // ABSTRACT LAYOUT
50
51 class ParentData {
52 void detach() {
53 detachSiblings();
54 }
55 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart
56 }
57
58 abstract class RenderNode extends Node {
59
60 // LAYOUT
61
62 // parentData is only for use by the RenderNode that actually lays this
63 // node out, and any other nodes who happen to know exactly what
64 // kind of node that is.
65 ParentData parentData;
66 void setupPos(RenderNode child) {
67 // override this to setup .parentData correctly for your class
68 if (child.parentData is! ParentData)
69 child.parentData = new ParentData();
70 }
71
72 void setAsChild(RenderNode child) { // only for use by subclasses
73 // call this whenever you decide a node is a child
74 assert(child != null);
75 setupPos(child);
76 super.setAsChild(child);
77 }
78 void dropChild(RenderNode child) { // only for use by subclasses
79 assert(child != null);
80 assert(child.parentData != null);
81 child.parentData.detach();
82 super.dropChild(child);
83 }
84
85 }
86
87 abstract class RenderBox extends RenderNode { }
88
89
90 // GENERIC MIXIN FOR RENDER NODES THAT TAKE A LIST OF CHILDREN
91
92 abstract class ContainerParentDataMixin<ChildType extends RenderNode> {
93 ChildType previousSibling;
94 ChildType nextSibling;
95 void detachSiblings() {
96 if (previousSibling != null) {
97 assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>);
98 assert(previousSibling != this);
99 assert(previousSibling.parentData.nextSibling == this);
100 previousSibling.parentData.nextSibling = nextSibling;
101 }
102 if (nextSibling != null) {
103 assert(nextSibling.parentData is ContainerParentDataMixin<ChildType>);
104 assert(nextSibling != this);
105 assert(nextSibling.parentData.previousSibling == this);
106 nextSibling.parentData.previousSibling = previousSibling;
107 }
108 previousSibling = null;
109 nextSibling = null;
110 }
111 }
112
113 abstract class ContainerRenderNodeMixin<ChildType extends RenderNode, ParentData Type extends ContainerParentDataMixin<ChildType>> implements RenderNode {
114 // abstract class that has only InlineNode children
115
116 bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) {
117 assert(child.parentData is ParentDataType);
118 while (child.parentData.previousSibling != null) {
119 assert(child.parentData.previousSibling != child);
120 child = child.parentData.previousSibling;
121 assert(child.parentData is ParentDataType);
122 }
123 return child == equals;
124 }
125 bool _debugUltimateNextSiblingOf(ChildType child, { ChildType equals }) {
126 assert(child.parentData is ParentDataType);
127 while (child.parentData.nextSibling != null) {
128 assert(child.parentData.nextSibling != child);
129 child = child.parentData.nextSibling;
130 assert(child.parentData is ParentDataType);
131 }
132 return child == equals;
133 }
134
135 ChildType _firstChild;
136 ChildType _lastChild;
137 void add(ChildType child, { ChildType before }) {
138 assert(child != this);
139 assert(before != this);
140 assert(child != before);
141 assert(child != _firstChild);
142 assert(child != _lastChild);
143 setAsChild(child);
144 assert(child.parentData is ParentDataType);
145 assert(child.parentData.nextSibling == null);
146 assert(child.parentData.previousSibling == null);
147 if (before == null) {
148 // append at the end (_lastChild)
149 child.parentData.previousSibling = _lastChild;
150 if (_lastChild != null) {
151 assert(_lastChild.parentData is ParentDataType);
152 _lastChild.parentData.nextSibling = child;
153 }
154 _lastChild = child;
155 if (_firstChild == null)
156 _firstChild = child;
157 } else {
158 assert(_firstChild != null);
159 assert(_lastChild != null);
160 assert(_debugUltimatePreviousSiblingOf(before, equals: _firstChild));
161 assert(_debugUltimateNextSiblingOf(before, equals: _lastChild));
162 assert(before.parentData is ParentDataType);
163 if (before.parentData.previousSibling == null) {
164 // insert at the start (_firstChild); we'll end up with two or more chil dren
165 assert(before == _firstChild);
166 child.parentData.nextSibling = before;
167 before.parentData.previousSibling = child;
168 _firstChild = child;
169 } else {
170 // insert in the middle; we'll end up with three or more children
171 // set up links from child to siblings
172 child.parentData.previousSibling = before.parentData.previousSibling;
173 child.parentData.nextSibling = before;
174 // set up links from siblings to child
175 assert(child.parentData.previousSibling.parentData is ParentDataType);
176 assert(child.parentData.nextSibling.parentData is ParentDataType);
177 child.parentData.previousSibling.parentData.nextSibling = child;
178 child.parentData.nextSibling.parentData.previousSibling = child;
179 assert(before.parentData.previousSibling == child);
180 }
181 }
182 markNeedsLayout();
183 }
184 void remove(ChildType child) {
185 assert(child.parentData is ParentDataType);
186 assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
187 assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
188 if (child.parentData.previousSibling == null) {
189 assert(_firstChild == child);
190 _firstChild = child.parentData.nextSibling;
191 } else {
192 assert(child.parentData.previousSibling.parentData is ParentDataType);
193 child.parentData.previousSibling.parentData.nextSibling = child.parentData .nextSibling;
194 }
195 if (child.parentData.nextSibling == null) {
196 assert(_lastChild == child);
197 _lastChild = child.parentData.previousSibling;
198 } else {
199 assert(child.parentData.nextSibling.parentData is ParentDataType);
200 child.parentData.nextSibling.parentData.previousSibling = child.parentData .previousSibling;
201 }
202 child.parentData.previousSibling = null;
203 child.parentData.nextSibling = null;
204 dropChild(child);
205 markNeedsLayout();
206 }
207 void redepthChildren() {
208 ChildType child = _firstChild;
209 while (child != null) {
210 redepthChild(child);
211 assert(child.parentData is ParentDataType);
212 child = child.parentData.nextSibling;
213 }
214 }
215 void attachChildren() {
216 ChildType child = _firstChild;
217 while (child != null) {
218 child.attach();
219 assert(child.parentData is ParentDataType);
220 child = child.parentData.nextSibling;
221 }
222 }
223 void detachChildren() {
224 ChildType child = _firstChild;
225 while (child != null) {
226 child.detach();
227 assert(child.parentData is ParentDataType);
228 child = child.parentData.nextSibling;
229 }
230 }
231
232 ChildType get firstChild => _firstChild;
233 ChildType get lastChild => _lastChild;
234 ChildType childAfter(ChildType child) {
235 assert(child.parentData is ParentDataType);
236 return child.parentData.nextSibling;
237 }
238
239 }
240
241
242 // CSS SHIMS
243
244 abstract class RenderCSS extends RenderBox {
245
246 dynamic debug;
247 sky.Element _skyElement;
248
249 RenderCSS(this.debug) {
250 _skyElement = createSkyElement();
251 registerEventTarget(_skyElement, this);
252 }
253
254 sky.Element createSkyElement();
255
256 void updateStyles(List<Style> styles) {
257 _skyElement.setAttribute('class', styles.map((s) => s._className).join(' ')) ;
258 }
259
260 void updateInlineStyle(String newStyle) {
261 _skyElement.setAttribute('style', newStyle);
262 }
263
264 double get width {
265 sky.ClientRect rect = _skyElement.getBoundingClientRect();
266 return rect.width;
267 }
268
269 double get height {
270 sky.ClientRect rect = _skyElement.getBoundingClientRect();
271 return rect.height;
272 }
273
274 Rect get rect {
275 sky.ClientRect rect = _skyElement.getBoundingClientRect();
276 return new Rect(rect.left, rect.top, rect.width, rect.height);
277 }
278
279 }
280
281 class CSSParentData extends ParentData with ContainerParentDataMixin<RenderCSS> { }
282
283 class RenderCSSContainer extends RenderCSS with ContainerRenderNodeMixin<RenderC SS, CSSParentData> {
284
285 RenderCSSContainer(debug) : super(debug);
286
287 void setupPos(RenderNode child) {
288 if (child.parentData is! CSSParentData)
289 child.parentData = new CSSParentData();
290 }
291
292 sky.Element createSkyElement() => sky.document.createElement('div')
293 ..setAttribute('debug', debug.toS tring());
294
295 void markNeedsLayout() { }
296
297 void add(RenderCSS child, { RenderCSS before }) {
298 if (before != null) {
299 assert(before._skyElement.parentNode != null);
300 assert(before._skyElement.parentNode == _skyElement);
301 }
302 super.add(child, before: before);
303 if (before != null) {
304 before._skyElement.insertBefore([child._skyElement]);
305 assert(child._skyElement.parentNode != null);
306 assert(child._skyElement.parentNode == _skyElement);
307 assert(child._skyElement.parentNode == before._skyElement.parentNode);
308 } else {
309 _skyElement.appendChild(child._skyElement);
310 }
311 }
312 void remove(RenderCSS child) {
313 child._skyElement.remove();
314 super.remove(child);
315 }
316
317 }
318
319 class RenderCSSText extends RenderCSS {
320
321 RenderCSSText(debug, String newData) : super(debug) {
322 data = newData;
323 }
324
325 static final Style _displayParagraph = new Style('display:paragraph');
326
327 sky.Element createSkyElement() {
328 return sky.document.createElement('div')
329 ..setChild(new sky.Text())
330 ..setAttribute('class', _displayParagraph._className)
331 ..setAttribute('debug', debug.toString());
332 }
333
334 void set data (String value) {
335 (_skyElement.firstChild as sky.Text).data = value;
336 }
337
338 }
339
340 class RenderCSSImage extends RenderCSS {
341
342 RenderCSSImage(debug, String src, num width, num height) : super(debug) {
343 configure(src, width, height);
344 }
345
346 sky.Element createSkyElement() {
347 return sky.document.createElement('img')
348 ..setAttribute('debug', debug.toString());
349 }
350
351 void configure(String src, num width, num height) {
352 if (_skyElement.getAttribute('src') != src)
353 _skyElement.setAttribute('src', src);
354 _skyElement.style['width'] = '${width}px';
355 _skyElement.style['height'] = '${height}px';
356 }
357
358 }
359
360 class RenderCSSRoot extends RenderCSSContainer {
361 RenderCSSRoot(debug) : super(debug);
362 sky.Element createSkyElement() {
363 var result = super.createSkyElement();
364 assert(result != null);
365 sky.document.appendChild(result);
366 return result;
367 }
368 }
369
370
371 // legacy tools
372 Map<sky.EventTarget, RenderNode> _eventTargetRegistry = {};
373 void registerEventTarget(sky.EventTarget e, RenderNode n) {
374 _eventTargetRegistry[e] = n;
375 }
376 RenderNode bridgeEventTargetToRenderNode(sky.EventTarget e) {
377 return _eventTargetRegistry[e];
378 }
379
380
381
382
383 String _attributes(node) {
384 if (node is! sky.Element) return '';
385 var result = '';
386 var attrs = node.getAttributes();
387 for (var attr in attrs)
388 result += ' ${attr.name}="${attr.value}"';
389 return result;
390 }
391
392 void _serialiseDOM(node, [String prefix = '']) {
393 if (node is sky.Text) {
394 print(prefix + 'text: "' + node.data.replaceAll('\n', '\\n') + '"');
395 return;
396 }
397 print(prefix + node.toString() + _attributes(node));
398 var children = node.getChildNodes();
399 prefix = prefix + ' ';
400 for (var child in children)
401 _serialiseDOM(child, prefix);
402 }
403
404 void dumpState() {
405 _serialiseDOM(sky.document);
406 }
OLDNEW
« no previous file with comments | « sky/framework/fn.dart ('k') | sky/framework/node.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698