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

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

Issue 1221883002: Remove package:sky/framework (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 5 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/sdk/lib/framework/fn.dart ('k') | sky/sdk/lib/framework/net/fetch.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 // This version of layout.dart is a shim version of layout2.dart that is backed using CSS and <div>s.
4
5 import 'node.dart';
6 import 'dart:sky' as sky;
7 import 'dart:collection';
8
9 // UTILS
10
11 // Bridge to legacy CSS-like style specification
12 // Eventually we'll replace this with something else
13 class Style {
14 final String _className;
15 static final Map<String, Style> _cache = new HashMap<String, Style>();
16
17 static int _nextStyleId = 1;
18
19 static String _getNextClassName() { return "style${_nextStyleId++}"; }
20
21 Style extend(Style other) {
22 var className = "$_className ${other._className}";
23
24 return _cache.putIfAbsent(className, () {
25 return new Style._construct(className);
26 });
27 }
28
29 factory Style(String styles) {
30 assert(!styles.contains(new RegExp('\\b(display|flex|flex-direction)\\b')));
31 return new Style._addToCache(styles);
32 }
33
34 factory Style._addToCache(String styles) {
35 return _cache.putIfAbsent(styles, () {
36 var className = _getNextClassName();
37 sky.Element styleNode = sky.document.createElement('style');
38 styleNode.setChild(new sky.Text(".$className { $styles }"));
39 sky.document.appendChild(styleNode);
40 return new Style._construct(className);
41 });
42 }
43
44 Style._construct(this._className);
45 }
46
47 class Rect {
48 const Rect(this.x, this.y, this.width, this.height);
49 final double x;
50 final double y;
51 final double width;
52 final double height;
53 }
54
55
56 // ABSTRACT LAYOUT
57
58 class ParentData {
59 void detach() {
60 detachSiblings();
61 }
62 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart
63 void merge(ParentData other) {
64 // override this in subclasses to merge in data from other into this
65 assert(other.runtimeType == this.runtimeType);
66 }
67 }
68
69 abstract class RenderNode extends AbstractNode {
70
71 // LAYOUT
72
73 // parentData is only for use by the RenderNode that actually lays this
74 // node out, and any other nodes who happen to know exactly what
75 // kind of node that is.
76 ParentData parentData;
77 void setParentData(RenderNode child) {
78 // override this to setup .parentData correctly for your class
79 if (child.parentData is! ParentData)
80 child.parentData = new ParentData();
81 }
82
83 void adoptChild(RenderNode child) { // only for use by subclasses
84 // call this whenever you decide a node is a child
85 assert(child != null);
86 setParentData(child);
87 super.adoptChild(child);
88 }
89 void dropChild(RenderNode child) { // only for use by subclasses
90 assert(child != null);
91 assert(child.parentData != null);
92 child.parentData.detach();
93 super.dropChild(child);
94 }
95
96 }
97
98 abstract class RenderBox extends RenderNode { }
99
100
101 // GENERIC MIXIN FOR RENDER NODES THAT TAKE A LIST OF CHILDREN
102
103 abstract class ContainerParentDataMixin<ChildType extends RenderNode> {
104 ChildType previousSibling;
105 ChildType nextSibling;
106 void detachSiblings() {
107 if (previousSibling != null) {
108 assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>);
109 assert(previousSibling != this);
110 assert(previousSibling.parentData.nextSibling == this);
111 previousSibling.parentData.nextSibling = nextSibling;
112 }
113 if (nextSibling != null) {
114 assert(nextSibling.parentData is ContainerParentDataMixin<ChildType>);
115 assert(nextSibling != this);
116 assert(nextSibling.parentData.previousSibling == this);
117 nextSibling.parentData.previousSibling = previousSibling;
118 }
119 previousSibling = null;
120 nextSibling = null;
121 }
122 }
123
124 abstract class ContainerRenderNodeMixin<ChildType extends RenderNode, ParentData Type extends ContainerParentDataMixin<ChildType>> implements RenderNode {
125 // abstract class that has only InlineNode children
126
127 bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) {
128 assert(child.parentData is ParentDataType);
129 while (child.parentData.previousSibling != null) {
130 assert(child.parentData.previousSibling != child);
131 child = child.parentData.previousSibling;
132 assert(child.parentData is ParentDataType);
133 }
134 return child == equals;
135 }
136 bool _debugUltimateNextSiblingOf(ChildType child, { ChildType equals }) {
137 assert(child.parentData is ParentDataType);
138 while (child.parentData.nextSibling != null) {
139 assert(child.parentData.nextSibling != child);
140 child = child.parentData.nextSibling;
141 assert(child.parentData is ParentDataType);
142 }
143 return child == equals;
144 }
145
146 ChildType _firstChild;
147 ChildType _lastChild;
148 void add(ChildType child, { ChildType before }) {
149 assert(child != this);
150 assert(before != this);
151 assert(child != before);
152 assert(child != _firstChild);
153 assert(child != _lastChild);
154 adoptChild(child);
155 assert(child.parentData is ParentDataType);
156 assert(child.parentData.nextSibling == null);
157 assert(child.parentData.previousSibling == null);
158 if (before == null) {
159 // append at the end (_lastChild)
160 child.parentData.previousSibling = _lastChild;
161 if (_lastChild != null) {
162 assert(_lastChild.parentData is ParentDataType);
163 _lastChild.parentData.nextSibling = child;
164 }
165 _lastChild = child;
166 if (_firstChild == null)
167 _firstChild = child;
168 } else {
169 assert(_firstChild != null);
170 assert(_lastChild != null);
171 assert(_debugUltimatePreviousSiblingOf(before, equals: _firstChild));
172 assert(_debugUltimateNextSiblingOf(before, equals: _lastChild));
173 assert(before.parentData is ParentDataType);
174 if (before.parentData.previousSibling == null) {
175 // insert at the start (_firstChild); we'll end up with two or more chil dren
176 assert(before == _firstChild);
177 child.parentData.nextSibling = before;
178 before.parentData.previousSibling = child;
179 _firstChild = child;
180 } else {
181 // insert in the middle; we'll end up with three or more children
182 // set up links from child to siblings
183 child.parentData.previousSibling = before.parentData.previousSibling;
184 child.parentData.nextSibling = before;
185 // set up links from siblings to child
186 assert(child.parentData.previousSibling.parentData is ParentDataType);
187 assert(child.parentData.nextSibling.parentData is ParentDataType);
188 child.parentData.previousSibling.parentData.nextSibling = child;
189 child.parentData.nextSibling.parentData.previousSibling = child;
190 assert(before.parentData.previousSibling == child);
191 }
192 }
193 markNeedsLayout();
194 }
195 void remove(ChildType child) {
196 assert(child.parentData is ParentDataType);
197 assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
198 assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
199 if (child.parentData.previousSibling == null) {
200 assert(_firstChild == child);
201 _firstChild = child.parentData.nextSibling;
202 } else {
203 assert(child.parentData.previousSibling.parentData is ParentDataType);
204 child.parentData.previousSibling.parentData.nextSibling = child.parentData .nextSibling;
205 }
206 if (child.parentData.nextSibling == null) {
207 assert(_lastChild == child);
208 _lastChild = child.parentData.previousSibling;
209 } else {
210 assert(child.parentData.nextSibling.parentData is ParentDataType);
211 child.parentData.nextSibling.parentData.previousSibling = child.parentData .previousSibling;
212 }
213 child.parentData.previousSibling = null;
214 child.parentData.nextSibling = null;
215 dropChild(child);
216 markNeedsLayout();
217 }
218 void redepthChildren() {
219 ChildType child = _firstChild;
220 while (child != null) {
221 redepthChild(child);
222 assert(child.parentData is ParentDataType);
223 child = child.parentData.nextSibling;
224 }
225 }
226 void attachChildren() {
227 ChildType child = _firstChild;
228 while (child != null) {
229 child.attach();
230 assert(child.parentData is ParentDataType);
231 child = child.parentData.nextSibling;
232 }
233 }
234 void detachChildren() {
235 ChildType child = _firstChild;
236 while (child != null) {
237 child.detach();
238 assert(child.parentData is ParentDataType);
239 child = child.parentData.nextSibling;
240 }
241 }
242
243 ChildType get firstChild => _firstChild;
244 ChildType get lastChild => _lastChild;
245 ChildType childAfter(ChildType child) {
246 assert(child.parentData is ParentDataType);
247 return child.parentData.nextSibling;
248 }
249
250 }
251
252
253 // CSS SHIMS
254
255 abstract class RenderCSS extends RenderBox {
256
257 dynamic debug;
258 sky.Element _skyElement;
259
260 RenderCSS(this.debug) {
261 _skyElement = createSkyElement();
262 registerEventTarget(_skyElement, this);
263 }
264
265 sky.Element createSkyElement();
266
267 void updateStyles(List<Style> styles) {
268 _skyElement.setAttribute('class', stylesToClasses(styles));
269 }
270
271 String stylesToClasses(List<Style> styles) {
272 return styles.map((s) => s._className).join(' ');
273 }
274
275 String _inlineStyles = '';
276 String _additionalStylesFromParent = ''; // used internally to propagate paren tData settings to the child
277
278 void updateInlineStyle(String newStyle) {
279 assert(newStyle == null || !newStyle.contains(new RegExp('\\b(display|flex|f lex-direction)\\b')));
280 _inlineStyles = newStyle != null ? newStyle : '';
281 _updateInlineStyleAttribute();
282 }
283
284 void _updateInlineStyleAttribute() {
285 if ((_inlineStyles != '') && (_additionalStylesFromParent != ''))
286 _skyElement.setAttribute('style', "$_inlineStyles;$_additionalStylesFromPa rent");
287 else
288 _skyElement.setAttribute('style', "$_inlineStyles$_additionalStylesFromPar ent");
289 }
290
291 double get width {
292 sky.ClientRect rect = _skyElement.getBoundingClientRect();
293 return rect.width;
294 }
295
296 double get height {
297 sky.ClientRect rect = _skyElement.getBoundingClientRect();
298 return rect.height;
299 }
300
301 Rect get rect {
302 sky.ClientRect rect = _skyElement.getBoundingClientRect();
303 return new Rect(rect.left, rect.top, rect.width, rect.height);
304 }
305
306 }
307
308 class CSSParentData extends ParentData with ContainerParentDataMixin<RenderCSS> { }
309
310 class RenderCSSContainer extends RenderCSS with ContainerRenderNodeMixin<RenderC SS, CSSParentData> {
311
312 RenderCSSContainer(debug) : super(debug);
313
314 void setParentData(RenderNode child) {
315 if (child.parentData is! CSSParentData)
316 child.parentData = new CSSParentData();
317 }
318
319 sky.Element createSkyElement() => sky.document.createElement('div')
320 ..setAttribute('debug', debug.toS tring());
321
322 void markNeedsLayout() { }
323
324 void add(RenderCSS child, { RenderCSS before }) {
325 if (before != null) {
326 assert(before._skyElement.parentNode != null);
327 assert(before._skyElement.parentNode == _skyElement);
328 }
329 super.add(child, before: before);
330 if (before != null) {
331 before._skyElement.insertBefore([child._skyElement]);
332 assert(child._skyElement.parentNode != null);
333 assert(child._skyElement.parentNode == _skyElement);
334 assert(child._skyElement.parentNode == before._skyElement.parentNode);
335 } else {
336 _skyElement.appendChild(child._skyElement);
337 }
338 }
339 void remove(RenderCSS child) {
340 child._skyElement.remove();
341 super.remove(child);
342 }
343
344 }
345
346 class FlexBoxParentData extends CSSParentData {
347 int flex;
348 void merge(FlexBoxParentData other) {
349 if (other.flex != null)
350 flex = other.flex;
351 super.merge(other);
352 }
353 }
354
355 enum FlexDirection { Row, Column }
356
357 class RenderCSSFlex extends RenderCSSContainer {
358
359 RenderCSSFlex(debug, FlexDirection direction) : _direction = direction, super( debug);
360
361 FlexDirection _direction;
362 FlexDirection get direction => _direction;
363 void set direction (FlexDirection value) {
364 _direction = value;
365 markNeedsLayout();
366 }
367
368 void setParentData(RenderNode child) {
369 if (child.parentData is! FlexBoxParentData)
370 child.parentData = new FlexBoxParentData();
371 }
372
373 static final Style _displayFlex = new Style._addToCache('display:flex');
374 static final Style _displayFlexRow = new Style._addToCache('flex-direction:row ');
375 static final Style _displayFlexColumn = new Style._addToCache('flex-direction: column');
376
377 String stylesToClasses(List<Style> styles) {
378 var settings = _displayFlex._className;
379 switch (_direction) {
380 case FlexDirection.Row: settings += ' ' + _displayFlexRow._className; brea k;
381 case FlexDirection.Column: settings += ' ' + _displayFlexColumn._className ; break;
382 }
383 return super.stylesToClasses(styles) + ' ' + settings;
384 }
385
386 void markNeedsLayout() {
387 super.markNeedsLayout();
388
389 // pretend we did the layout:
390 RenderCSS child = _firstChild;
391 while (child != null) {
392 assert(child.parentData is FlexBoxParentData);
393 if (child.parentData.flex != null) {
394 child._additionalStylesFromParent = 'flex:${child.parentData.flex}';
395 child._updateInlineStyleAttribute();
396 }
397 child = child.parentData.nextSibling;
398 }
399 }
400
401 }
402
403 class StackParentData extends CSSParentData {
404 double top;
405 double left;
406 double right;
407 double bottom;
408 void merge(StackParentData other) {
409 if (other.top != null)
410 top = other.top;
411 if (other.left != null)
412 left = other.left;
413 if (other.right != null)
414 right = other.right;
415 if (other.bottom != null)
416 bottom = other.bottom;
417 super.merge(other);
418 }
419 }
420
421 class RenderCSSStack extends RenderCSSContainer {
422
423 RenderCSSStack(debug) : super(debug);
424
425 void setParentData(RenderNode child) {
426 if (child.parentData is! StackParentData)
427 child.parentData = new StackParentData();
428 }
429
430 static final Style _displayPosition = new Style._addToCache('transform:transla teX(0);position:relative');
431
432 String stylesToClasses(List<Style> styles) {
433 return super.stylesToClasses(styles) + ' ' + _displayPosition._className;
434 }
435
436 void markNeedsLayout() {
437 super.markNeedsLayout();
438
439 // pretend we did the layout:
440 RenderCSS child = _firstChild;
441 while (child != null) {
442 assert(child.parentData is StackParentData);
443 var style = 'position:absolute;';
444 if (child.parentData.top != null)
445 style += 'top:${child.parentData.top};';
446 if (child.parentData.left != null)
447 style += 'left:${child.parentData.left};';
448 if (child.parentData.right != null)
449 style += 'right:${child.parentData.right};';
450 if (child.parentData.bottom != null)
451 style += 'bottom:${child.parentData.bottom};';
452 child._additionalStylesFromParent = style;
453 child._updateInlineStyleAttribute();
454 child = child.parentData.nextSibling;
455 }
456 }
457
458 }
459
460 class RenderCSSParagraph extends RenderCSSContainer {
461
462 RenderCSSParagraph(debug) : super(debug);
463
464 static final Style _displayParagraph = new Style._addToCache('display:paragrap h');
465
466 String stylesToClasses(List<Style> styles) {
467 return super.stylesToClasses(styles) + ' ' + _displayParagraph._className;
468 }
469
470 }
471
472 class RenderCSSInline extends RenderCSS {
473
474 RenderCSSInline(debug, String newData) : super(debug) {
475 data = newData;
476 }
477
478 static final Style _displayInline = new Style._addToCache('display:inline');
479
480 String stylesToClasses(List<Style> styles) {
481 return super.stylesToClasses(styles) + ' ' + _displayInline._className;
482 }
483
484 sky.Element createSkyElement() {
485 return sky.document.createElement('div')
486 ..setChild(new sky.Text())
487 ..setAttribute('debug', debug.toString());
488 }
489
490 void set data (String value) {
491 (_skyElement.firstChild as sky.Text).data = value;
492 }
493
494 }
495
496 class RenderCSSImage extends RenderCSS {
497
498 RenderCSSImage(debug, String src, num width, num height) : super(debug) {
499 configure(src, width, height);
500 }
501
502 sky.Element createSkyElement() {
503 return sky.document.createElement('img')
504 ..setAttribute('debug', debug.toString());
505 }
506
507 void configure(String src, num width, num height) {
508 if (_skyElement.getAttribute('src') != src)
509 _skyElement.setAttribute('src', src);
510 _skyElement.style['width'] = '${width}px';
511 _skyElement.style['height'] = '${height}px';
512 }
513
514 }
515
516 class RenderCSSRoot extends RenderCSSContainer {
517 RenderCSSRoot(debug) : super(debug);
518 sky.Element createSkyElement() {
519 var result = super.createSkyElement();
520 assert(result != null);
521 sky.document.appendChild(result);
522 return result;
523 }
524 }
525
526
527 // legacy tools
528 Map<sky.EventTarget, RenderNode> _eventTargetRegistry = {};
529 void registerEventTarget(sky.EventTarget e, RenderNode n) {
530 _eventTargetRegistry[e] = n;
531 }
532 RenderNode bridgeEventTargetToRenderNode(sky.EventTarget e) {
533 return _eventTargetRegistry[e];
534 }
535
536
537
538
539 String _attributes(node) {
540 if (node is! sky.Element) return '';
541 var result = '';
542 var attrs = node.getAttributes();
543 for (var attr in attrs)
544 result += ' ${attr.name}="${attr.value}"';
545 return result;
546 }
547
548 void _serialiseDOM(node, [String prefix = '']) {
549 if (node is sky.Text) {
550 print(prefix + 'text: "' + node.data.replaceAll('\n', '\\n') + '"');
551 return;
552 }
553 print(prefix + node.toString() + _attributes(node));
554 var children = node.getChildNodes();
555 prefix = prefix + ' ';
556 for (var child in children)
557 _serialiseDOM(child, prefix);
558 }
559
560 void dumpState() {
561 _serialiseDOM(sky.document);
562 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/framework/fn.dart ('k') | sky/sdk/lib/framework/net/fetch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698