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

Side by Side Diff: sky/examples/raw/sector-layout.dart

Issue 1152383002: A proof of concept for annular sector layout. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: add the Path C++ and IDL files which I forgot before 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/engine/core/painting/Path.idl ('k') | sky/sdk/lib/framework/layout2.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 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 import 'dart:math' as math;
6 import 'dart:sky' as sky;
7 import 'package:sky/framework/layout2.dart';
8
9 const double kTwoPi = 2 * math.PI;
10
11 double deg(double radians) => radians * 180.0 / math.PI;
12
13 class SectorConstraints {
14 const SectorConstraints({
15 this.minDeltaRadius: 0.0,
16 this.maxDeltaRadius: double.INFINITY,
17 this.minDeltaTheta: 0.0,
18 this.maxDeltaTheta: kTwoPi});
19
20 const SectorConstraints.tight({ double deltaRadius: 0.0, double deltaTheta: 0. 0 })
21 : minDeltaRadius = deltaRadius,
22 maxDeltaRadius = deltaRadius,
23 minDeltaTheta = deltaTheta,
24 maxDeltaTheta = deltaTheta;
25
26 final double minDeltaRadius;
27 final double maxDeltaRadius;
28 final double minDeltaTheta;
29 final double maxDeltaTheta;
30
31 double constrainDeltaRadius(double deltaRadius) {
32 return clamp(min: minDeltaRadius, max: maxDeltaRadius, value: deltaRadius);
33 }
34
35 double constrainDeltaTheta(double deltaTheta) {
36 return clamp(min: minDeltaTheta, max: maxDeltaTheta, value: deltaTheta);
37 }
38 }
39
40 class SectorDimensions {
41 const SectorDimensions({ this.deltaRadius: 0.0, this.deltaTheta: 0.0 });
42
43 factory SectorDimensions.withConstraints(
44 SectorConstraints constraints,
45 { double deltaRadius: 0.0, double deltaTheta: 0.0 }
46 ) {
47 return new SectorDimensions(
48 deltaRadius: constraints.constrainDeltaRadius(deltaRadius),
49 deltaTheta: constraints.constrainDeltaTheta(deltaTheta)
50 );
51 }
52
53 final double deltaRadius;
54 final double deltaTheta;
55 }
56
57 class SectorParentData extends ParentData {
58 double radius = 0.0;
59 double theta = 0.0;
60 }
61
62 abstract class RenderSector extends RenderNode {
63
64 void setParentData(RenderNode child) {
65 if (child.parentData is! SectorParentData)
66 child.parentData = new SectorParentData();
67 }
68
69 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
70 return new SectorDimensions.withConstraints(constraints);
71 }
72
73 void layout(SectorConstraints constraints, double radius, { RenderNode relayou tSubtreeRoot }) {
74 deltaRadius = constraints.constrainDeltaRadius(0.0);
75 deltaTheta = constraints.constrainDeltaTheta(0.0);
76 layoutDone();
77 }
78
79 double deltaRadius;
80 double deltaTheta;
81 }
82
83 class RenderDecoratedSector extends RenderSector {
84 BoxDecoration _decoration;
85
86 RenderDecoratedSector(BoxDecoration decoration) : _decoration = decoration;
87
88 void setBoxDecoration(BoxDecoration decoration) {
89 if (_decoration == decoration)
90 return;
91 _decoration = decoration;
92 markNeedsPaint();
93 }
94
95 // origin must be set to the center of the circle
96 void paint(RenderNodeDisplayList canvas) {
97 assert(deltaRadius != null);
98 assert(deltaTheta != null);
99 assert(parentData is SectorParentData);
100
101 if (_decoration == null)
102 return;
103
104 if (_decoration.backgroundColor != null) {
105 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor;
106 sky.Path path = new sky.Path();
107 double outerRadiusOver2 = (parentData.radius + deltaRadius) / 2.0;
108 sky.Rect outerBounds = new sky.Rect()..setLTRB(-outerRadiusOver2, -outerRa diusOver2, outerRadiusOver2, outerRadiusOver2);
109 path.arcTo(outerBounds, deg(parentData.theta), deg(deltaTheta), true);
110 double innerRadiusOver2 = parentData.radius / 2.0;
111 sky.Rect innerBounds = new sky.Rect()..setLTRB(-innerRadiusOver2, -innerRa diusOver2, innerRadiusOver2, innerRadiusOver2);
112 path.arcTo(innerBounds, deg(parentData.theta + deltaTheta), deg(-deltaThet a), false);
113 path.close();
114 canvas.drawPath(path, paint);
115 }
116 }
117 }
118
119 class SectorChildListParentData extends SectorParentData with ContainerParentDat aMixin<RenderSector> { }
120
121 class RenderSectorRing extends RenderDecoratedSector with ContainerRenderNodeMix in<RenderSector, SectorChildListParentData> {
122 // lays out RenderSector children in a ring
123
124 RenderSectorRing({
125 BoxDecoration decoration,
126 double deltaRadius: double.INFINITY,
127 double padding: 0.0
128 }) : super(decoration), _padding = padding, _desiredDeltaRadius = deltaRadius;
129
130 double _desiredDeltaRadius;
131 double get desiredDeltaRadius => _desiredDeltaRadius;
132 void set desiredDeltaRadius(double value) {
133 assert(value != null);
134 if (_desiredDeltaRadius != value) {
135 _desiredDeltaRadius = value;
136 markNeedsLayout();
137 }
138 }
139
140 double _padding;
141 double get padding => _padding;
142 void set padding(double value) {
143 assert(value != null);
144 if (_padding != value) {
145 _padding = value;
146 markNeedsLayout();
147 }
148 }
149
150 void setParentData(RenderNode child) {
151 if (child.parentData is! SectorChildListParentData)
152 child.parentData = new SectorChildListParentData();
153 }
154
155 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
156 double outerDeltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadiu s);
157 double innerDeltaRadius = outerDeltaRadius - padding * 2.0;
158 double childRadius = radius + padding;
159 double paddingTheta = math.atan(padding / (radius + outerDeltaRadius));
160 double innerTheta = paddingTheta; // increments with each child
161 double remainingTheta = constraints.maxDeltaTheta - (innerTheta + paddingThe ta);
162 RenderSector child = firstChild;
163 while (child != null) {
164 SectorConstraints innerConstraints = new SectorConstraints(
165 maxDeltaRadius: innerDeltaRadius,
166 maxDeltaTheta: remainingTheta
167 );
168 SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConst raints, childRadius);
169 innerTheta += childDimensions.deltaTheta;
170 remainingTheta -= childDimensions.deltaTheta;
171 assert(child.parentData is SectorChildListParentData);
172 child = child.parentData.nextSibling;
173 if (child != null) {
174 innerTheta += paddingTheta;
175 remainingTheta -= paddingTheta;
176 }
177 }
178 return new SectorDimensions.withConstraints(constraints,
179 deltaRadius: outerDeltaRadius,
180 deltaTheta: innerTheta);
181 }
182
183 SectorConstraints _constraints;
184 void layout(SectorConstraints constraints, double radius, { RenderNode relayou tSubtreeRoot }) {
185 if (relayoutSubtreeRoot != null)
186 saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
187 relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRo ot;
188 deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius);
189 assert(deltaRadius < double.INFINITY);
190 _constraints = constraints;
191 internalLayout(radius, relayoutSubtreeRoot);
192 }
193
194 void relayout() {
195 assert(parentData is SectorParentData);
196 internalLayout(parentData.radius, this);
197 }
198
199 void internalLayout(double radius, RenderNode relayoutSubtreeRoot) {
200 double innerDeltaRadius = deltaRadius - padding * 2.0;
201 double childRadius = radius + padding;
202 double paddingTheta = math.atan(padding / (radius + deltaRadius));
203 double innerTheta = paddingTheta; // increments with each child
204 double remainingTheta = _constraints.maxDeltaTheta - (innerTheta + paddingTh eta);
205 RenderSector child = firstChild;
206 while (child != null) {
207 SectorConstraints innerConstraints = new SectorConstraints(
208 maxDeltaRadius: innerDeltaRadius,
209 maxDeltaTheta: remainingTheta
210 );
211 child.layout(innerConstraints, childRadius, relayoutSubtreeRoot: relayoutS ubtreeRoot);
212 assert(child.parentData is SectorParentData);
213 child.parentData.theta = innerTheta;
214 child.parentData.radius = childRadius;
215 innerTheta += child.deltaTheta;
216 remainingTheta -= child.deltaTheta;
217 assert(child.parentData is SectorChildListParentData);
218 child = child.parentData.nextSibling;
219 if (child != null) {
220 innerTheta += paddingTheta;
221 remainingTheta -= paddingTheta;
222 }
223 }
224 deltaTheta = innerTheta;
225 }
226
227 // TODO(ianh): hit testing et al is pending on adam's patch
228
229 // paint origin is 0,0 of our circle
230 // each sector then knows how to paint itself at its location
231 void paint(RenderNodeDisplayList canvas) {
232 super.paint(canvas);
233 RenderSector child = firstChild;
234 while (child != null) {
235 assert(child.parentData is SectorChildListParentData);
236 canvas.paintChild(child, 0.0, 0.0);
237 child = child.parentData.nextSibling;
238 }
239 }
240
241 }
242
243 class RenderBoxToRenderSectorAdapter extends RenderBox {
244
245 RenderBoxToRenderSectorAdapter({ double innerRadius: 0.0, RenderSector child } ) :
246 _innerRadius = innerRadius {
247 _child = child;
248 adoptChild(_child);
249 }
250
251 double _innerRadius;
252 double get innerRadius => _innerRadius;
253 void set innerRadius(double value) {
254 _innerRadius = value;
255 markNeedsLayout();
256 }
257
258 RenderSector _child;
259 RenderSector get child => _child;
260 void set child(RenderSector value) {
261 if (_child != null)
262 dropChild(_child);
263 _child = value;
264 adoptChild(_child);
265 markNeedsLayout();
266 }
267
268 void setParentData(RenderNode child) {
269 if (child.parentData is! SectorParentData)
270 child.parentData = new SectorParentData();
271 }
272
273 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) {
274 if (child == null)
275 return new BoxDimensions.withConstraints(constraints, width: 0.0, height: 0.0);
276 assert(child is RenderSector);
277 assert(child.parentData is SectorParentData);
278 assert(!constraints.isInfinite);
279 double maxChildDeltaRadius = math.max(constraints.maxWidth, constraints.maxH eight) / 2.0 - innerRadius;
280 SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorCo nstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
281 double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
282 return new BoxDimensions.withConstraints(constraints, width: dimension, heig ht: dimension);
283 }
284
285 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) {
286 if (relayoutSubtreeRoot != null)
287 saveRelayoutSubtreeRoot(relayoutSubtreeRoot);
288 relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRo ot;
289 BoxDimensions ourDimensions;
290 if (child == null) {
291 ourDimensions = new BoxDimensions.withConstraints(constraints, width: 0.0, height: 0.0);
292 } else {
293 assert(child is RenderSector);
294 assert(child.parentData is SectorParentData);
295 assert(!constraints.isInfinite);
296 double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.ma xHeight) / 2.0 - innerRadius;
297 child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), i nnerRadius, relayoutSubtreeRoot: relayoutSubtreeRoot);
298 double dimension = (innerRadius + child.deltaRadius) * 2.0;
299 ourDimensions = new BoxDimensions.withConstraints(constraints, width: dime nsion, height: dimension);
300 }
301 width = ourDimensions.width;
302 height = ourDimensions.height;
303 print("adapter is: ${width}x${height}");
304 layoutDone();
305 }
306
307 double width;
308 double height;
309
310 // TODO(ianh): hit testing et al is pending on adam's patch
311
312 // paint origin is 0,0 of our circle
313 void paint(RenderNodeDisplayList canvas) {
314 super.paint(canvas);
315 if (child != null) {
316 print("painting child at ${width/2.0},${height/2.0}");
317 sky.Paint paint;
318 paint = new sky.Paint()..color = 0xFF474700;
319 canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint);
320 paint = new sky.Paint()..color = 0xFFF7F700;
321 canvas.drawRect(new sky.Rect()..setLTRB(10.0, 10.0, width-10.0, height-10. 0), paint);
322 paint = new sky.Paint()..color = 0xFFFFFFFF;
323 canvas.drawRect(new sky.Rect()..setLTRB(width/2.0-5.0, height/2.0-5.0, wid th/2.0+5.0, height/2.0+5.0), paint);
324 canvas.paintChild(child, width/2.0, height/2.0);
325 }
326 }
327
328 }
329
330 class RenderSolidColor extends RenderDecoratedSector {
331 final int backgroundColor;
332
333 RenderSolidColor(int backgroundColor)
334 : super(new BoxDecoration(backgroundColor: backgroundColor)),
335 backgroundColor = backgroundColor;
336
337 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
338 return new SectorDimensions.withConstraints(constraints, deltaTheta: 1.0); / / 1.0 radians
339 }
340
341 void layout(SectorConstraints constraints, double radius, { RenderNode relayou tSubtreeRoot }) {
342 deltaRadius = constraints.constrainDeltaRadius(constraints.maxDeltaRadius);
343 deltaTheta = constraints.constrainDeltaTheta(1.0); // 1.0 radians
344 layoutDone();
345 }
346 }
347
348 RenderView renderView;
349
350 void beginFrame(double timeStamp) {
351 RenderNode.flushLayout();
352
353 renderView.paintFrame();
354 }
355
356 bool handleEvent(sky.Event event) {
357 if (event is! sky.PointerEvent)
358 return false;
359 return renderView.handlePointer(event, x: event.x, y: event.y);
360 }
361
362 void main() {
363 print("test...");
364 sky.view.setEventCallback(handleEvent);
365 sky.view.setBeginFrameCallback(beginFrame);
366
367 var rootCircle = new RenderSectorRing(padding: 10.0);
368 rootCircle.add(new RenderSolidColor(0xFF00FF00));
369 rootCircle.add(new RenderSolidColor(0xFF0000FF));
370
371 var root = new RenderBoxToRenderSectorAdapter(innerRadius: 50.0, child: rootCi rcle);
372 renderView = new RenderView(root: root);
373 renderView.layout(newWidth: sky.view.width, newHeight: sky.view.height);
374
375 sky.view.scheduleFrame();
376 print("window is ${sky.view.width}x${sky.view.height}");
377 }
OLDNEW
« no previous file with comments | « sky/engine/core/painting/Path.idl ('k') | sky/sdk/lib/framework/layout2.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698