| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import '../node.dart'; | 5 import '../node.dart'; |
| 6 import '../scheduler.dart' as scheduler; | 6 import '../scheduler.dart' as scheduler; |
| 7 import 'dart:math' as math; | 7 import 'dart:math' as math; |
| 8 import 'dart:sky' as sky; | 8 import 'dart:sky' as sky; |
| 9 | 9 |
| 10 class ParentData { | 10 class ParentData { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 } | 37 } |
| 38 } | 38 } |
| 39 | 39 |
| 40 abstract class RenderObject extends AbstractNode { | 40 abstract class RenderObject extends AbstractNode { |
| 41 | 41 |
| 42 // LAYOUT | 42 // LAYOUT |
| 43 | 43 |
| 44 // parentData is only for use by the RenderObject that actually lays this | 44 // parentData is only for use by the RenderObject that actually lays this |
| 45 // node out, and any other nodes who happen to know exactly what | 45 // node out, and any other nodes who happen to know exactly what |
| 46 // kind of node that is. | 46 // kind of node that is. |
| 47 ParentData parentData; | 47 dynamic parentData; // TODO(ianh): change the type of this back to ParentData
once the analyzer is cleverer |
| 48 void setParentData(RenderObject child) { | 48 void setParentData(RenderObject child) { |
| 49 // override this to setup .parentData correctly for your class | 49 // override this to setup .parentData correctly for your class |
| 50 assert(!_debugDoingLayout); | 50 assert(!_debugDoingLayout); |
| 51 assert(!debugDoingPaint); | 51 assert(!debugDoingPaint); |
| 52 if (child.parentData is! ParentData) | 52 if (child.parentData is! ParentData) |
| 53 child.parentData = new ParentData(); | 53 child.parentData = new ParentData(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 void adoptChild(RenderObject child) { // only for use by subclasses | 56 void adoptChild(RenderObject child) { // only for use by subclasses |
| 57 // call this whenever you decide a node is a child | 57 // call this whenever you decide a node is a child |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 void markNeedsLayout() { | 100 void markNeedsLayout() { |
| 101 assert(!_debugDoingLayout); | 101 assert(!_debugDoingLayout); |
| 102 assert(!debugDoingPaint); | 102 assert(!debugDoingPaint); |
| 103 if (_needsLayout) { | 103 if (_needsLayout) { |
| 104 assert(debugAncestorsAlreadyMarkedNeedsLayout()); | 104 assert(debugAncestorsAlreadyMarkedNeedsLayout()); |
| 105 return; | 105 return; |
| 106 } | 106 } |
| 107 _needsLayout = true; | 107 _needsLayout = true; |
| 108 assert(_relayoutSubtreeRoot != null); | 108 assert(_relayoutSubtreeRoot != null); |
| 109 if (_relayoutSubtreeRoot != this) { | 109 if (_relayoutSubtreeRoot != this) { |
| 110 final parent = this.parent; // TODO(ianh): Remove this once the analyzer i
s cleverer |
| 110 assert(parent is RenderObject); | 111 assert(parent is RenderObject); |
| 111 parent.markNeedsLayout(); | 112 parent.markNeedsLayout(); |
| 113 assert(parent == this.parent); // TODO(ianh): Remove this once the analyze
r is cleverer |
| 112 } else { | 114 } else { |
| 113 _nodesNeedingLayout.add(this); | 115 _nodesNeedingLayout.add(this); |
| 114 scheduler.ensureVisualUpdate(); | 116 scheduler.ensureVisualUpdate(); |
| 115 } | 117 } |
| 116 } | 118 } |
| 117 static void flushLayout() { | 119 static void flushLayout() { |
| 118 _debugDoingLayout = true; | 120 _debugDoingLayout = true; |
| 119 List<RenderObject> dirtyNodes = _nodesNeedingLayout; | 121 List<RenderObject> dirtyNodes = _nodesNeedingLayout; |
| 120 _nodesNeedingLayout = new List<RenderObject>(); | 122 _nodesNeedingLayout = new List<RenderObject>(); |
| 121 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { | 123 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { |
| 122 if (node._needsLayout && node.attached) | 124 if (node._needsLayout && node.attached) |
| 123 node._doLayout(); | 125 node._doLayout(); |
| 124 }); | 126 }); |
| 125 _debugDoingLayout = false; | 127 _debugDoingLayout = false; |
| 126 } | 128 } |
| 127 void _doLayout() { | 129 void _doLayout() { |
| 128 try { | 130 try { |
| 129 assert(_relayoutSubtreeRoot == this); | 131 assert(_relayoutSubtreeRoot == this); |
| 130 performLayout(); | 132 performLayout(); |
| 131 } catch (e, stack) { | 133 } catch (e, stack) { |
| 132 print('Exception raised during layout of ${this}: ${e}'); | 134 print('Exception raised during layout of ${this}: ${e}'); |
| 133 print(stack); | 135 print(stack); |
| 134 return; | 136 return; |
| 135 } | 137 } |
| 136 _needsLayout = false; | 138 _needsLayout = false; |
| 137 } | 139 } |
| 138 void layout(dynamic constraints, { bool parentUsesSize: false }) { | 140 void layout(dynamic constraints, { bool parentUsesSize: false }) { |
| 141 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is
cleverer |
| 139 RenderObject relayoutSubtreeRoot; | 142 RenderObject relayoutSubtreeRoot; |
| 140 if (!parentUsesSize || sizedByParent || parent is! RenderObject) | 143 if (!parentUsesSize || sizedByParent || parent is! RenderObject) |
| 141 relayoutSubtreeRoot = this; | 144 relayoutSubtreeRoot = this; |
| 142 else | 145 else |
| 143 relayoutSubtreeRoot = parent._relayoutSubtreeRoot; | 146 relayoutSubtreeRoot = parent._relayoutSubtreeRoot; |
| 147 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer
is cleverer |
| 144 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r
elayoutSubtreeRoot) | 148 if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _r
elayoutSubtreeRoot) |
| 145 return; | 149 return; |
| 146 _constraints = constraints; | 150 _constraints = constraints; |
| 147 _relayoutSubtreeRoot = relayoutSubtreeRoot; | 151 _relayoutSubtreeRoot = relayoutSubtreeRoot; |
| 148 if (sizedByParent) | 152 if (sizedByParent) |
| 149 performResize(); | 153 performResize(); |
| 150 performLayout(); | 154 performLayout(); |
| 151 _needsLayout = false; | 155 _needsLayout = false; |
| 152 markNeedsPaint(); | 156 markNeedsPaint(); |
| 157 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer
is cleverer |
| 153 } | 158 } |
| 154 bool get sizedByParent => false; // return true if the constraints are the onl
y input to the sizing algorithm (in particular, child nodes have no impact) | 159 bool get sizedByParent => false; // return true if the constraints are the onl
y input to the sizing algorithm (in particular, child nodes have no impact) |
| 155 void performResize(); // set the local dimensions, using only the constraints
(only called if sizedByParent is true) | 160 void performResize(); // set the local dimensions, using only the constraints
(only called if sizedByParent is true) |
| 156 void performLayout(); | 161 void performLayout(); |
| 157 // Override this to perform relayout without your parent's | 162 // Override this to perform relayout without your parent's |
| 158 // involvement. | 163 // involvement. |
| 159 // | 164 // |
| 160 // This is called during layout. If sizedByParent is true, then | 165 // This is called during layout. If sizedByParent is true, then |
| 161 // performLayout() should not change your dimensions, only do that | 166 // performLayout() should not change your dimensions, only do that |
| 162 // in performResize(). If sizedByParent is false, then set both | 167 // in performResize(). If sizedByParent is false, then set both |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 RenderObject get result => path.first; | 255 RenderObject get result => path.first; |
| 251 | 256 |
| 252 void add(RenderObject node) { | 257 void add(RenderObject node) { |
| 253 path.add(node); | 258 path.add(node); |
| 254 } | 259 } |
| 255 } | 260 } |
| 256 | 261 |
| 257 | 262 |
| 258 // GENERIC MIXIN FOR RENDER NODES WITH ONE CHILD | 263 // GENERIC MIXIN FOR RENDER NODES WITH ONE CHILD |
| 259 | 264 |
| 260 abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> { | 265 abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem
ents RenderObject { |
| 261 ChildType _child; | 266 ChildType _child; |
| 262 ChildType get child => _child; | 267 ChildType get child => _child; |
| 263 void set child (ChildType value) { | 268 void set child (ChildType value) { |
| 264 if (_child != null) | 269 if (_child != null) |
| 265 dropChild(_child); | 270 dropChild(_child); |
| 266 _child = value; | 271 _child = value; |
| 267 if (_child != null) | 272 if (_child != null) |
| 268 adoptChild(_child); | 273 adoptChild(_child); |
| 269 } | 274 } |
| 270 void attachChildren() { | 275 void attachChildren() { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 int count = 1; | 440 int count = 1; |
| 436 ChildType child = _firstChild; | 441 ChildType child = _firstChild; |
| 437 while (child != null) { | 442 while (child != null) { |
| 438 result += '${prefix}child ${count}: ${child.toString(prefix)}'; | 443 result += '${prefix}child ${count}: ${child.toString(prefix)}'; |
| 439 count += 1; | 444 count += 1; |
| 440 child = child.parentData.nextSibling; | 445 child = child.parentData.nextSibling; |
| 441 } | 446 } |
| 442 return result; | 447 return result; |
| 443 } | 448 } |
| 444 } | 449 } |
| OLD | NEW |