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

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

Issue 1161003002: Split layout2.dart into several files (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 6 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/examples/raw/render_paragraph.dart ('k') | sky/examples/raw/sector_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 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/app.dart';
8 import 'package:sky/framework/layout2.dart';
9
10 const double kTwoPi = 2 * math.PI;
11
12 double deg(double radians) => radians * 180.0 / math.PI;
13
14 class SectorConstraints {
15 const SectorConstraints({
16 this.minDeltaRadius: 0.0,
17 this.maxDeltaRadius: double.INFINITY,
18 this.minDeltaTheta: 0.0,
19 this.maxDeltaTheta: kTwoPi
20 });
21
22 const SectorConstraints.tight({ double deltaRadius: 0.0, double deltaTheta: 0. 0 })
23 : minDeltaRadius = deltaRadius,
24 maxDeltaRadius = deltaRadius,
25 minDeltaTheta = deltaTheta,
26 maxDeltaTheta = deltaTheta;
27
28 final double minDeltaRadius;
29 final double maxDeltaRadius;
30 final double minDeltaTheta;
31 final double maxDeltaTheta;
32
33 double constrainDeltaRadius(double deltaRadius) {
34 return clamp(min: minDeltaRadius, max: maxDeltaRadius, value: deltaRadius);
35 }
36
37 double constrainDeltaTheta(double deltaTheta) {
38 return clamp(min: minDeltaTheta, max: maxDeltaTheta, value: deltaTheta);
39 }
40 }
41
42 class SectorDimensions {
43 const SectorDimensions({ this.deltaRadius: 0.0, this.deltaTheta: 0.0 });
44
45 factory SectorDimensions.withConstraints(
46 SectorConstraints constraints,
47 { double deltaRadius: 0.0, double deltaTheta: 0.0 }
48 ) {
49 return new SectorDimensions(
50 deltaRadius: constraints.constrainDeltaRadius(deltaRadius),
51 deltaTheta: constraints.constrainDeltaTheta(deltaTheta)
52 );
53 }
54
55 final double deltaRadius;
56 final double deltaTheta;
57 }
58
59 class SectorParentData extends ParentData {
60 double radius = 0.0;
61 double theta = 0.0;
62 }
63
64 abstract class RenderSector extends RenderNode {
65
66 void setParentData(RenderNode child) {
67 if (child.parentData is! SectorParentData)
68 child.parentData = new SectorParentData();
69 }
70
71 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
72 return new SectorDimensions.withConstraints(constraints);
73 }
74
75 SectorConstraints get constraints => super.constraints as SectorConstraints;
76 void performResize() {
77 // default behaviour for subclasses that have sizedByParent = true
78 deltaRadius = constraints.constrainDeltaRadius(0.0);
79 deltaTheta = constraints.constrainDeltaTheta(0.0);
80 }
81 void performLayout() {
82 // descendants have to either override performLayout() to set both
83 // the dimensions and lay out children, or, set sizedByParent to
84 // true so that performResize()'s logic above does its thing.
85 assert(sizedByParent);
86 }
87
88 bool hitTest(HitTestResult result, { double radius, double theta }) {
89 assert(parentData is SectorParentData);
90 if (radius < parentData.radius || radius >= parentData.radius + deltaRadius ||
91 theta < parentData.theta || theta >= parentData.theta + deltaTheta)
92 return false;
93 hitTestChildren(result, radius: radius, theta: theta);
94 result.add(this);
95 return true;
96 }
97 void hitTestChildren(HitTestResult result, { double radius, double theta }) { }
98
99 double deltaRadius;
100 double deltaTheta;
101 }
102
103 class RenderDecoratedSector extends RenderSector {
104
105 RenderDecoratedSector(BoxDecoration decoration) : _decoration = decoration;
106
107 BoxDecoration _decoration;
108 BoxDecoration get decoration => _decoration;
109 void set decoration (BoxDecoration value) {
110 if (value == _decoration)
111 return;
112 _decoration = value;
113 markNeedsPaint();
114 }
115
116 // origin must be set to the center of the circle
117 void paint(RenderNodeDisplayList canvas) {
118 assert(deltaRadius != null);
119 assert(deltaTheta != null);
120 assert(parentData is SectorParentData);
121
122 if (_decoration == null)
123 return;
124
125 if (_decoration.backgroundColor != null) {
126 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor;
127 sky.Path path = new sky.Path();
128 double outerRadius = (parentData.radius + deltaRadius);
129 sky.Rect outerBounds = new sky.Rect.fromLTRB(-outerRadius, -outerRadius, o uterRadius, outerRadius);
130 path.arcTo(outerBounds, deg(parentData.theta), deg(deltaTheta), true);
131 double innerRadius = parentData.radius;
132 sky.Rect innerBounds = new sky.Rect.fromLTRB(-innerRadius, -innerRadius, i nnerRadius, innerRadius);
133 path.arcTo(innerBounds, deg(parentData.theta + deltaTheta), deg(-deltaThet a), false);
134 path.close();
135 canvas.drawPath(path, paint);
136 }
137 }
138 }
139
140 class SectorChildListParentData extends SectorParentData with ContainerParentDat aMixin<RenderSector> { }
141
142 class RenderSectorWithChildren extends RenderDecoratedSector with ContainerRende rNodeMixin<RenderSector, SectorChildListParentData> {
143 RenderSectorWithChildren(BoxDecoration decoration) : super(decoration);
144
145 void hitTestChildren(HitTestResult result, { double radius, double theta }) {
146 RenderSector child = lastChild;
147 while (child != null) {
148 assert(child.parentData is SectorChildListParentData);
149 if (child.hitTest(result, radius: radius, theta: theta))
150 return;
151 child = child.parentData.previousSibling;
152 }
153 }
154 }
155
156 class RenderSectorRing extends RenderSectorWithChildren {
157 // lays out RenderSector children in a ring
158
159 RenderSectorRing({
160 BoxDecoration decoration,
161 double deltaRadius: double.INFINITY,
162 double padding: 0.0
163 }) : super(decoration), _padding = padding, _desiredDeltaRadius = deltaRadius;
164
165 double _desiredDeltaRadius;
166 double get desiredDeltaRadius => _desiredDeltaRadius;
167 void set desiredDeltaRadius(double value) {
168 assert(value != null);
169 if (_desiredDeltaRadius != value) {
170 _desiredDeltaRadius = value;
171 markNeedsLayout();
172 }
173 }
174
175 double _padding;
176 double get padding => _padding;
177 void set padding(double value) {
178 // TODO(ianh): avoid code duplication
179 assert(value != null);
180 if (_padding != value) {
181 _padding = value;
182 markNeedsLayout();
183 }
184 }
185
186 void setParentData(RenderNode child) {
187 // TODO(ianh): avoid code duplication
188 if (child.parentData is! SectorChildListParentData)
189 child.parentData = new SectorChildListParentData();
190 }
191
192 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
193 double outerDeltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadiu s);
194 double innerDeltaRadius = outerDeltaRadius - padding * 2.0;
195 double childRadius = radius + padding;
196 double paddingTheta = math.atan(padding / (radius + outerDeltaRadius));
197 double innerTheta = paddingTheta; // increments with each child
198 double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddi ngTheta);
199 RenderSector child = firstChild;
200 while (child != null) {
201 SectorConstraints innerConstraints = new SectorConstraints(
202 maxDeltaRadius: innerDeltaRadius,
203 maxDeltaTheta: remainingDeltaTheta
204 );
205 SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConst raints, childRadius);
206 innerTheta += childDimensions.deltaTheta;
207 remainingDeltaTheta -= childDimensions.deltaTheta;
208 assert(child.parentData is SectorChildListParentData);
209 child = child.parentData.nextSibling;
210 if (child != null) {
211 innerTheta += paddingTheta;
212 remainingDeltaTheta -= paddingTheta;
213 }
214 }
215 return new SectorDimensions.withConstraints(constraints,
216 deltaRadius: outerDeltaRadius,
217 deltaTheta: innerTheta);
218 }
219
220 void performLayout() {
221 assert(this.parentData is SectorParentData);
222 deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius);
223 assert(deltaRadius < double.INFINITY);
224 double innerDeltaRadius = deltaRadius - padding * 2.0;
225 double childRadius = this.parentData.radius + padding;
226 double paddingTheta = math.atan(padding / (this.parentData.radius + deltaRad ius));
227 double innerTheta = paddingTheta; // increments with each child
228 double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddi ngTheta);
229 RenderSector child = firstChild;
230 while (child != null) {
231 SectorConstraints innerConstraints = new SectorConstraints(
232 maxDeltaRadius: innerDeltaRadius,
233 maxDeltaTheta: remainingDeltaTheta
234 );
235 assert(child.parentData is SectorParentData);
236 child.parentData.theta = innerTheta;
237 child.parentData.radius = childRadius;
238 child.layout(innerConstraints, parentUsesSize: true);
239 innerTheta += child.deltaTheta;
240 remainingDeltaTheta -= child.deltaTheta;
241 assert(child.parentData is SectorChildListParentData);
242 child = child.parentData.nextSibling;
243 if (child != null) {
244 innerTheta += paddingTheta;
245 remainingDeltaTheta -= paddingTheta;
246 }
247 }
248 deltaTheta = innerTheta;
249 }
250
251 // paint origin is 0,0 of our circle
252 // each sector then knows how to paint itself at its location
253 void paint(RenderNodeDisplayList canvas) {
254 // TODO(ianh): avoid code duplication
255 super.paint(canvas);
256 RenderSector child = firstChild;
257 while (child != null) {
258 assert(child.parentData is SectorChildListParentData);
259 canvas.paintChild(child, new sky.Point(0.0, 0.0));
260 child = child.parentData.nextSibling;
261 }
262 }
263
264 }
265
266 class RenderSectorSlice extends RenderSectorWithChildren {
267 // lays out RenderSector children in a stack
268
269 RenderSectorSlice({
270 BoxDecoration decoration,
271 double deltaTheta: kTwoPi,
272 double padding: 0.0
273 }) : super(decoration), _padding = padding, _desiredDeltaTheta = deltaTheta;
274
275 double _desiredDeltaTheta;
276 double get desiredDeltaTheta => _desiredDeltaTheta;
277 void set desiredDeltaTheta(double value) {
278 assert(value != null);
279 if (_desiredDeltaTheta != value) {
280 _desiredDeltaTheta = value;
281 markNeedsLayout();
282 }
283 }
284
285 double _padding;
286 double get padding => _padding;
287 void set padding(double value) {
288 // TODO(ianh): avoid code duplication
289 assert(value != null);
290 if (_padding != value) {
291 _padding = value;
292 markNeedsLayout();
293 }
294 }
295
296 void setParentData(RenderNode child) {
297 // TODO(ianh): avoid code duplication
298 if (child.parentData is! SectorChildListParentData)
299 child.parentData = new SectorChildListParentData();
300 }
301
302 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
303 assert(this.parentData is SectorParentData);
304 double paddingTheta = math.atan(padding / this.parentData.radius);
305 double outerDeltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
306 double innerDeltaTheta = outerDeltaTheta - paddingTheta * 2.0;
307 double childRadius = this.parentData.radius + padding;
308 double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0);
309 RenderSector child = firstChild;
310 while (child != null) {
311 SectorConstraints innerConstraints = new SectorConstraints(
312 maxDeltaRadius: remainingDeltaRadius,
313 maxDeltaTheta: innerDeltaTheta
314 );
315 SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConst raints, childRadius);
316 childRadius += childDimensions.deltaRadius;
317 remainingDeltaRadius -= childDimensions.deltaRadius;
318 assert(child.parentData is SectorChildListParentData);
319 child = child.parentData.nextSibling;
320 childRadius += padding;
321 remainingDeltaRadius -= padding;
322 }
323 return new SectorDimensions.withConstraints(constraints,
324 deltaRadius: childRadius - this. parentData.radius,
325 deltaTheta: outerDeltaTheta);
326 }
327
328 void performLayout() {
329 assert(this.parentData is SectorParentData);
330 deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
331 assert(deltaTheta <= kTwoPi);
332 double paddingTheta = math.atan(padding / this.parentData.radius);
333 double innerTheta = this.parentData.theta + paddingTheta;
334 double innerDeltaTheta = deltaTheta - paddingTheta * 2.0;
335 double childRadius = this.parentData.radius + padding;
336 double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0);
337 RenderSector child = firstChild;
338 while (child != null) {
339 SectorConstraints innerConstraints = new SectorConstraints(
340 maxDeltaRadius: remainingDeltaRadius,
341 maxDeltaTheta: innerDeltaTheta
342 );
343 child.parentData.theta = innerTheta;
344 child.parentData.radius = childRadius;
345 child.layout(innerConstraints, parentUsesSize: true);
346 childRadius += child.deltaRadius;
347 remainingDeltaRadius -= child.deltaRadius;
348 assert(child.parentData is SectorChildListParentData);
349 child = child.parentData.nextSibling;
350 childRadius += padding;
351 remainingDeltaRadius -= padding;
352 }
353 deltaRadius = childRadius - this.parentData.radius;
354 }
355
356 // paint origin is 0,0 of our circle
357 // each sector then knows how to paint itself at its location
358 void paint(RenderNodeDisplayList canvas) {
359 // TODO(ianh): avoid code duplication
360 super.paint(canvas);
361 RenderSector child = firstChild;
362 while (child != null) {
363 assert(child.parentData is SectorChildListParentData);
364 canvas.paintChild(child, new sky.Point(0.0, 0.0));
365 child = child.parentData.nextSibling;
366 }
367 }
368
369 }
370
371 class RenderBoxToRenderSectorAdapter extends RenderBox {
372
373 RenderBoxToRenderSectorAdapter({ double innerRadius: 0.0, RenderSector child } ) :
374 _innerRadius = innerRadius {
375 _child = child;
376 adoptChild(_child);
377 }
378
379 double _innerRadius;
380 double get innerRadius => _innerRadius;
381 void set innerRadius(double value) {
382 _innerRadius = value;
383 markNeedsLayout();
384 }
385
386 RenderSector _child;
387 RenderSector get child => _child;
388 void set child(RenderSector value) {
389 if (_child != null)
390 dropChild(_child);
391 _child = value;
392 adoptChild(_child);
393 markNeedsLayout();
394 }
395
396 void setParentData(RenderNode child) {
397 if (child.parentData is! SectorParentData)
398 child.parentData = new SectorParentData();
399 }
400
401 sky.Size getIntrinsicDimensions(BoxConstraints constraints) {
402 if (child == null)
403 return constraints.constrain(new sky.Size(0.0, 0.0));
404 assert(child is RenderSector);
405 assert(child.parentData is SectorParentData);
406 assert(!constraints.isInfinite);
407 double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxH eight) / 2.0 - innerRadius;
408 SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorCo nstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
409 double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
410 return constraints.constrain(new sky.Size(dimension, dimension));
411 }
412
413 void performLayout() {
414 if (child == null) {
415 size = constraints.constrain(new sky.Size(0.0, 0.0));
416 } else {
417 assert(child is RenderSector);
418 assert(!constraints.isInfinite);
419 print("constraint maxes: ${constraints.maxWidth} and ${constraints.maxHeig ht}");
420 double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.ma xHeight) / 2.0 - innerRadius;
421 print("maxChildDeltaRadius = $maxChildDeltaRadius");
422 assert(child.parentData is SectorParentData);
423 child.parentData.radius = innerRadius;
424 child.parentData.theta = 0.0;
425 child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), p arentUsesSize: true);
426 double dimension = (innerRadius + child.deltaRadius) * 2.0;
427 size = constraints.constrain(new sky.Size(dimension, dimension));
428 }
429 }
430
431 // paint origin is 0,0 of our circle
432 void paint(RenderNodeDisplayList canvas) {
433 super.paint(canvas);
434 if (child != null) {
435 sky.Rect bounds = new sky.Rect.fromSize(size);
436 canvas.paintChild(child, bounds.center);
437 }
438 }
439
440 bool hitTest(HitTestResult result, { sky.Point position }) {
441 double x = position.x;
442 double y = position.y;
443 if (child == null)
444 return false;
445 // translate to our origin
446 x -= size.width/2.0;
447 y -= size.height/2.0;
448 // convert to radius/theta
449 double radius = math.sqrt(x*x+y*y);
450 double theta = (math.atan2(x, -y) - math.PI/2.0) % kTwoPi;
451 if (radius < innerRadius)
452 return false;
453 if (radius >= innerRadius + child.deltaRadius)
454 return false;
455 if (theta > child.deltaTheta)
456 return false;
457 child.hitTest(result, radius: radius, theta: theta);
458 result.add(this);
459 return true;
460 }
461
462 }
463
464 class RenderSolidColor extends RenderDecoratedSector {
465 RenderSolidColor(int backgroundColor, {
466 this.desiredDeltaRadius: double.INFINITY,
467 this.desiredDeltaTheta: kTwoPi
468 }) : this.backgroundColor = backgroundColor,
469 super(new BoxDecoration(backgroundColor: backgroundColor));
470
471 double desiredDeltaRadius;
472 double desiredDeltaTheta;
473 final int backgroundColor;
474
475 SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) {
476 return new SectorDimensions.withConstraints(constraints, deltaTheta: 1.0); / / 1.0 radians
477 }
478
479 void performLayout() {
480 deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius);
481 deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
482 }
483
484 void handlePointer(sky.PointerEvent event) {
485 if (event.type == 'pointerdown')
486 decoration = new BoxDecoration(backgroundColor: 0xFFFF0000);
487 else if (event.type == 'pointerup')
488 decoration = new BoxDecoration(backgroundColor: backgroundColor);
489 }
490 }
491
492 AppView app;
493
494 void main() {
495
496 var rootCircle = new RenderSectorRing(padding: 20.0);
497 rootCircle.add(new RenderSolidColor(0xFF00FFFF, desiredDeltaTheta: kTwoPi * 0. 15));
498 rootCircle.add(new RenderSolidColor(0xFF0000FF, desiredDeltaTheta: kTwoPi * 0. 4));
499 var stack = new RenderSectorSlice(padding: 2.0);
500 stack.add(new RenderSolidColor(0xFFFFFF00, desiredDeltaRadius: 20.0));
501 stack.add(new RenderSolidColor(0xFFFF9000, desiredDeltaRadius: 20.0));
502 stack.add(new RenderSolidColor(0xFF00FF00));
503 rootCircle.add(stack);
504
505 var root = new RenderBoxToRenderSectorAdapter(innerRadius: 50.0, child: rootCi rcle);
506 app = new AppView(root);
507 }
OLDNEW
« no previous file with comments | « sky/examples/raw/render_paragraph.dart ('k') | sky/examples/raw/sector_layout.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698