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

Side by Side Diff: client/layout/ViewLayout.dart

Issue 8363040: Implement measurement using futures (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to all comments Created 9 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** The interface that the layout algorithms use to talk to the view. */ 5 /** The interface that the layout algorithms use to talk to the view. */
6 interface Positionable { 6 interface Positionable {
7 ViewLayout get layout(); 7 ViewLayout get layout();
8 8
9 /** Gets our custom CSS properties, as provided by the CSS preprocessor. */ 9 /** Gets our custom CSS properties, as provided by the CSS preprocessor. */
10 Map<String, String> get customStyle(); 10 Map<String, String> get customStyle();
11 11
12 /** Gets the root DOM used for layout. */ 12 /** Gets the root DOM used for layout. */
13 Element get node(); 13 Element get node();
14 14
15 /** Gets the collection of child views. */ 15 /** Gets the collection of child views. */
16 Collection<Positionable> get childViews(); 16 Collection<Positionable> get childViews();
17 17
18 /** Causes a view to layout its children. */ 18 /** Causes a view to layout its children. */
19 void doLayout(); 19 void doLayout();
20 } 20 }
21 21
22 22
23 /** 23 /**
24 * Caches the layout parameters that were specified in CSS during a layout 24 * Caches the layout parameters that were specified in CSS during a layout
25 * computation. These values are immutable during a layout. 25 * computation. These values are immutable during a layout.
26 */ 26 */
27 class LayoutParams { 27 class LayoutParams {
28 // TODO(jmesserly): should be const, but there's a bug in DartC preventing us 28 // TODO(jmesserly): should be const, but there's a bug in DartC preventing us
29 // from calling "window." in an initializer. See b/5332777 29 // from calling "window." in an initializer. See b/5332777
30 CSSStyleDeclaration style; 30 Future<CSSStyleDeclaration> style;
31 31
32 int get layer() => 0; 32 int get layer() => 0;
33 33
34 LayoutParams(Element node) { 34 LayoutParams(Element node) {
35 style = window.getComputedStyle(node, ''); 35 style = node.computedStyle;
36 } 36 }
37 } 37 }
38 38
39 // TODO(jmesserly): enums would really help here 39 // TODO(jmesserly): enums would really help here
40 class Dimension { 40 class Dimension {
41 // TODO(jmesserly): perhaps this should be X and Y 41 // TODO(jmesserly): perhaps this should be X and Y
42 static final WIDTH = const Dimension._internal('width'); 42 static final WIDTH = const Dimension._internal('width');
43 static final HEIGHT = const Dimension._internal('height'); 43 static final HEIGHT = const Dimension._internal('height');
44 44
45 final String name; // for debugging 45 final String name; // for debugging
(...skipping 18 matching lines...) Expand all
64 * Abstract base class for View layout. Tracks relevant layout state. 64 * Abstract base class for View layout. Tracks relevant layout state.
65 * This code was inspired by code in Android's View.java; it's needed for the 65 * This code was inspired by code in Android's View.java; it's needed for the
66 * rest of the layout system. 66 * rest of the layout system.
67 */ 67 */
68 class ViewLayout { 68 class ViewLayout {
69 /** 69 /**
70 * The layout parameters associated with this view and used by the parent 70 * The layout parameters associated with this view and used by the parent
71 * to determine how this view should be laid out. 71 * to determine how this view should be laid out.
72 */ 72 */
73 LayoutParams layoutParams; 73 LayoutParams layoutParams;
74 Future<ElementRect> _cachedViewRect;
74 75
75 /** The view that this layout belongs to. */ 76 /** The view that this layout belongs to. */
76 final Positionable view; 77 final Positionable view;
77 78
78 /** 79 /**
79 * To get a perforant positioning model on top of the DOM, we read all 80 * To get a perforant positioning model on top of the DOM, we read all
80 * properties in the first pass while computing positions. Then we have a 81 * properties in the first pass while computing positions. Then we have a
81 * second pass that actually moves everything. 82 * second pass that actually moves everything.
82 */ 83 */
83 int _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight; 84 int _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight;
84 85
85 ViewLayout(this.view) {} 86 ViewLayout(this.view);
86 87
87 /** 88 /**
88 * Creates the appropriate view layout, depending on the properties. 89 * Creates the appropriate view layout, depending on the properties.
89 */ 90 */
90 // TODO(jmesserly): we should support user defined layouts somehow. Perhaps 91 // TODO(jmesserly): we should support user defined layouts somehow. Perhaps
91 // registered with a LayoutProvider. 92 // registered with a LayoutProvider.
92 factory ViewLayout.fromView(Positionable view) { 93 factory ViewLayout.fromView(Positionable view) {
93 if (hasCustomLayout(view)) { 94 if (hasCustomLayout(view)) {
94 return new GridLayout(view); 95 return new GridLayout(view);
95 } else { 96 } else {
96 return new ViewLayout(view); 97 return new ViewLayout(view);
97 } 98 }
98 } 99 }
99 100
100 static bool hasCustomLayout(Positionable view) { 101 static bool hasCustomLayout(Positionable view) {
101 return view.customStyle['display'] == "-dart-grid"; 102 return view.customStyle['display'] == "-dart-grid";
102 } 103 }
103 104
104 CSSStyleDeclaration get _style() => layoutParams.style; 105 CSSStyleDeclaration get _style() => layoutParams.style.value;
105 106
106 int get currentWidth() => view.node.offsetWidth; 107 void cacheExistingBrowserLayout() {
107 int get currentHeight() => view.node.offsetHeight; 108 _cachedViewRect = view.node.rect;
109 }
110
111 int get currentWidth() {
112 return _cachedViewRect.value.offset.width;
nweiz 2011/10/28 03:58:38 What happens when _cachedViewRect hasn't fired yet
Jacob 2011/10/31 22:09:50 by design it will always have fired due to appropr
nweiz 2011/11/01 00:49:22 Oh, futures throw an error when value doesn't exis
113 }
114
115 int get currentHeight() {
116 return _cachedViewRect.value.offset.height;
117 }
108 118
109 int get borderLeftWidth() => _toPixels(_style.borderLeftWidth); 119 int get borderLeftWidth() => _toPixels(_style.borderLeftWidth);
nweiz 2011/10/28 03:58:38 Can't _style be null sometimes?
Jacob 2011/10/31 22:09:50 it can't be null, however a future not available y
nweiz 2011/11/01 00:49:22 The fact that it fires a "future not completed" er
110 int get borderTopWidth() => _toPixels(_style.borderTopWidth); 120 int get borderTopWidth() => _toPixels(_style.borderTopWidth);
111 int get borderRightWidth() => _toPixels(_style.borderRightWidth); 121 int get borderRightWidth() => _toPixels(_style.borderRightWidth);
112 int get borderBottomWidth() => _toPixels(_style.borderBottomWidth); 122 int get borderBottomWidth() => _toPixels(_style.borderBottomWidth);
113 int get borderWidth() => borderLeftWidth + borderRightWidth; 123 int get borderWidth() => borderLeftWidth + borderRightWidth;
114 int get borderHeight() => borderTopWidth + borderBottomWidth; 124 int get borderHeight() => borderTopWidth + borderBottomWidth;
115 125
nweiz 2011/10/28 03:58:38 Style nit: trailing whitespace
Jacob 2011/10/31 22:09:50 Done.
116 /** Implements the custom layout computation. */ 126 /** Implements the custom layout computation. */
117 bool measureLayout(int width, int height) => false; 127 void measureLayout(Future<Size> size, Completer<bool> changed) {
128 }
118 129
119 /** 130 /**
120 * Positions the view within its parent container. 131 * Positions the view within its parent container.
121 * Also performs a layout of its children. 132 * Also performs a layout of its children.
122 */ 133 */
123 void setBounds(int left, int top, int width, int height) { 134 void setBounds(int left, int top, int width, int height) {
124 assert(width >= 0 && height >= 0); 135 assert(width >= 0 && height >= 0);
125 136
126 _measuredLeft = left; 137 _measuredLeft = left;
127 _measuredTop = top; 138 _measuredTop = top;
128 139
129 // Note: we need to save the client height 140 // Note: we need to save the client height
130 _measuredWidth = width - borderWidth; 141 _measuredWidth = width - borderWidth;
131 _measuredHeight = height - borderHeight; 142 _measuredHeight = height - borderHeight;
132 143 final completer = new Completer<Size>();
133 measureLayout(_measuredWidth, _measuredHeight); 144 completer.complete(new Size(_measuredWidth, _measuredHeight));
145 measureLayout(completer.future, null);
134 } 146 }
135 147
136 /** Applies the layout to the node. */ 148 /** Applies the layout to the node. */
137 void applyLayout() { 149 void applyLayout() {
138 if (_measuredLeft != null) { 150 if (_measuredLeft != null) {
139 // TODO(jmesserly): benchmark the performance of this DOM interaction 151 // TODO(jmesserly): benchmark the performance of this DOM interaction
140 final style = view.node.style; 152 final style = view.node.style;
141 style.position = 'absolute'; 153 style.position = 'absolute';
142 style.left = '${_measuredLeft}px'; 154 style.left = '${_measuredLeft}px';
143 style.top = '${_measuredTop}px'; 155 style.top = '${_measuredTop}px';
(...skipping 25 matching lines...) Expand all
169 [ContentSizeMode mode = null]) { 181 [ContentSizeMode mode = null]) {
170 switch (dimension) { 182 switch (dimension) {
171 case Dimension.WIDTH: 183 case Dimension.WIDTH:
172 return measureWidth(parent, mode); 184 return measureWidth(parent, mode);
173 case Dimension.HEIGHT: 185 case Dimension.HEIGHT:
174 return measureHeight(parent, mode); 186 return measureHeight(parent, mode);
175 } 187 }
176 } 188 }
177 189
178 int measureWidth(ViewLayout parent, ContentSizeMode mode) { 190 int measureWidth(ViewLayout parent, ContentSizeMode mode) {
179 final style = layoutParams.style; 191 final style = layoutParams.style.value;
180 switch (mode) { 192 switch (mode) {
181 case ContentSizeMode.MIN: 193 case ContentSizeMode.MIN:
182 return _styleToPixels( 194 return _styleToPixels(
183 style.minWidth, currentWidth, parent.currentWidth); 195 style.minWidth, currentWidth, parent.currentWidth);
184 196
185 case ContentSizeMode.MAX: 197 case ContentSizeMode.MAX:
186 return _styleToPixels( 198 return _styleToPixels(
187 style.maxWidth, currentWidth, parent.currentWidth); 199 style.maxWidth, currentWidth, parent.currentWidth);
188 } 200 }
189 } 201 }
190 202
191 int measureHeight(ViewLayout parent, ContentSizeMode mode) { 203 int measureHeight(ViewLayout parent, ContentSizeMode mode) {
192 final style = layoutParams.style; 204 final style = layoutParams.style.value;
193 switch (mode) { 205 switch (mode) {
194 case ContentSizeMode.MIN: 206 case ContentSizeMode.MIN:
195 return _styleToPixels( 207 return _styleToPixels(
196 style.minHeight, currentHeight, parent.currentHeight); 208 style.minHeight, currentHeight, parent.currentHeight);
197 209
198 case ContentSizeMode.MAX: 210 case ContentSizeMode.MAX:
199 return _styleToPixels( 211 return _styleToPixels(
200 style.maxHeight, currentHeight, parent.currentHeight); 212 style.maxHeight, currentHeight, parent.currentHeight);
201 } 213 }
202 } 214 }
(...skipping 13 matching lines...) Expand all
216 // For an unset max-content size, use the actual size 228 // For an unset max-content size, use the actual size
217 return size; 229 return size;
218 } 230 }
219 if (style.endsWith('%')) { 231 if (style.endsWith('%')) {
220 num percent = Math.parseDouble(style.substring(0, style.length - 1)); 232 num percent = Math.parseDouble(style.substring(0, style.length - 1));
221 return ((percent / 100) * parentSize).toInt(); 233 return ((percent / 100) * parentSize).toInt();
222 } 234 }
223 return _toPixels(style); 235 return _toPixels(style);
224 } 236 }
225 } 237 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698