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

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

Issue 9382027: Move client/{base, observable, layout, touch, util, view} to samples/ui_lib . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « client/layout/SizingFunctions.dart ('k') | client/layout/layout.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 // 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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /** The interface that the layout algorithms use to talk to the view. */
6 interface Positionable {
7 ViewLayout get layout();
8
9 /** Gets our custom CSS properties, as provided by the CSS preprocessor. */
10 Map<String, String> get customStyle();
11
12 /** Gets the root DOM used for layout. */
13 Element get node();
14
15 /** Gets the collection of child views. */
16 Collection<Positionable> get childViews();
17
18 /** Causes a view to layout its children. */
19 void doLayout();
20 }
21
22
23 /**
24 * Caches the layout parameters that were specified in CSS during a layout
25 * computation. These values are immutable during a layout.
26 */
27 class LayoutParams {
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
30 Future<CSSStyleDeclaration> style;
31
32 int get layer() => 0;
33
34 LayoutParams(Element node) {
35 style = node.computedStyle;
36 }
37 }
38
39 // TODO(jmesserly): enums would really help here
40 class Dimension {
41 // TODO(jmesserly): perhaps this should be X and Y
42 static final WIDTH = const Dimension._internal('width');
43 static final HEIGHT = const Dimension._internal('height');
44
45 final String name; // for debugging
46 const Dimension._internal(this.name);
47 }
48
49 class ContentSizeMode {
50 /** Minimum content size, e.g. min-width and min-height in CSS. */
51 static final MIN = const ContentSizeMode._internal('min');
52
53 /** Maximum content size, e.g. min-width and min-height in CSS. */
54 static final MAX = const ContentSizeMode._internal('max');
55
56 // TODO(jmesserly): we probably want some sort of "auto" or "best fit" mode
57 // Don't need it yet though.
58
59 final String name; // for debugging
60 const ContentSizeMode._internal(this.name);
61 }
62
63 /**
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
66 * rest of the layout system.
67 */
68 class ViewLayout {
69 /**
70 * The layout parameters associated with this view and used by the parent
71 * to determine how this view should be laid out.
72 */
73 LayoutParams layoutParams;
74 Future<ElementRect> _cachedViewRect;
75
76 /** The view that this layout belongs to. */
77 final Positionable view;
78
79 /**
80 * To get a perforant positioning model on top of the DOM, we read all
81 * properties in the first pass while computing positions. Then we have a
82 * second pass that actually moves everything.
83 */
84 int _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight;
85
86 ViewLayout(this.view);
87
88 /**
89 * Creates the appropriate view layout, depending on the properties.
90 */
91 // TODO(jmesserly): we should support user defined layouts somehow. Perhaps
92 // registered with a LayoutProvider.
93 factory ViewLayout.fromView(Positionable view) {
94 if (hasCustomLayout(view)) {
95 return new GridLayout(view);
96 } else {
97 return new ViewLayout(view);
98 }
99 }
100
101 static bool hasCustomLayout(Positionable view) {
102 return view.customStyle['display'] == "-dart-grid";
103 }
104
105 CSSStyleDeclaration get _style() => layoutParams.style.value;
106
107 void cacheExistingBrowserLayout() {
108 _cachedViewRect = view.node.rect;
109 }
110
111 int get currentWidth() {
112 return _cachedViewRect.value.offset.width;
113 }
114
115 int get currentHeight() {
116 return _cachedViewRect.value.offset.height;
117 }
118
119 int get borderLeftWidth() => _toPixels(_style.borderLeftWidth);
120 int get borderTopWidth() => _toPixels(_style.borderTopWidth);
121 int get borderRightWidth() => _toPixels(_style.borderRightWidth);
122 int get borderBottomWidth() => _toPixels(_style.borderBottomWidth);
123 int get borderWidth() => borderLeftWidth + borderRightWidth;
124 int get borderHeight() => borderTopWidth + borderBottomWidth;
125
126 /** Implements the custom layout computation. */
127 void measureLayout(Future<Size> size, Completer<bool> changed) {
128 }
129
130 /**
131 * Positions the view within its parent container.
132 * Also performs a layout of its children.
133 */
134 void setBounds(int left, int top, int width, int height) {
135 assert(width >= 0 && height >= 0);
136
137 _measuredLeft = left;
138 _measuredTop = top;
139
140 // Note: we need to save the client height
141 _measuredWidth = width - borderWidth;
142 _measuredHeight = height - borderHeight;
143 final completer = new Completer<Size>();
144 completer.complete(new Size(_measuredWidth, _measuredHeight));
145 measureLayout(completer.future, null);
146 }
147
148 /** Applies the layout to the node. */
149 void applyLayout() {
150 if (_measuredLeft != null) {
151 // TODO(jmesserly): benchmark the performance of this DOM interaction
152 final style = view.node.style;
153 style.position = 'absolute';
154 style.left = '${_measuredLeft}px';
155 style.top = '${_measuredTop}px';
156 style.width = '${_measuredWidth}px';
157 style.height = '${_measuredHeight}px';
158 style.zIndex = '${layoutParams.layer}';
159
160 _measuredLeft = null;
161 _measuredTop = null;
162 _measuredWidth = null;
163 _measuredHeight = null;
164
165 // Ensure we can handle our custom layout when it is a child of a
166 // DOM-positioned node. For example, say we have a View tree like this:
167 //
168 // ViewWithLayout <-- uses our layout engine
169 // childView1 <-- is positioned by our layout engine, but uses
170 // HTML layout internally
171 // childOfChild <-- uses our layout engine for its own children
172 if (!hasCustomLayout(view)) {
173 for (final child in view.childViews) {
174 child.doLayout();
175 }
176 }
177 }
178 }
179
180 int measureContent(ViewLayout parent, Dimension dimension,
181 [ContentSizeMode mode = null]) {
182 switch (dimension) {
183 case Dimension.WIDTH:
184 return measureWidth(parent, mode);
185 case Dimension.HEIGHT:
186 return measureHeight(parent, mode);
187 }
188 }
189
190 int measureWidth(ViewLayout parent, ContentSizeMode mode) {
191 final style = layoutParams.style.value;
192 switch (mode) {
193 case ContentSizeMode.MIN:
194 return _styleToPixels(
195 style.minWidth, currentWidth, parent.currentWidth);
196
197 case ContentSizeMode.MAX:
198 return _styleToPixels(
199 style.maxWidth, currentWidth, parent.currentWidth);
200 }
201 }
202
203 int measureHeight(ViewLayout parent, ContentSizeMode mode) {
204 final style = layoutParams.style.value;
205 switch (mode) {
206 case ContentSizeMode.MIN:
207 return _styleToPixels(
208 style.minHeight, currentHeight, parent.currentHeight);
209
210 case ContentSizeMode.MAX:
211 return _styleToPixels(
212 style.maxHeight, currentHeight, parent.currentHeight);
213 }
214 }
215
216 static int _toPixels(String style) {
217 if (style.endsWith('px')) {
218 return Math.parseInt(style.substring(0, style.length - 2));
219 } else {
220 // TODO(jmesserly): other size units
221 throw new UnsupportedOperationException(
222 'Unknown min/max content size format: "$style"');
223 }
224 }
225
226 static int _styleToPixels(String style, num size, num parentSize) {
227 if (style == 'none') {
228 // For an unset max-content size, use the actual size
229 return size;
230 }
231 if (style.endsWith('%')) {
232 num percent = Math.parseDouble(style.substring(0, style.length - 1));
233 return ((percent / 100) * parentSize).toInt();
234 }
235 return _toPixels(style);
236 }
237 }
OLDNEW
« no previous file with comments | « client/layout/SizingFunctions.dart ('k') | client/layout/layout.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698