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 'dart:sky' as sky; | 6 import 'dart:sky' as sky; |
7 | 7 |
8 // ABSTRACT LAYOUT | 8 // ABSTRACT LAYOUT |
9 | 9 |
10 class ParentData { | 10 class ParentData { |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 if (value > max) | 28 if (value > max) |
29 value = max; | 29 value = max; |
30 if (value < min) | 30 if (value < min) |
31 value = min; | 31 value = min; |
32 return value; | 32 return value; |
33 } | 33 } |
34 | 34 |
35 class RenderNodeDisplayList extends sky.PictureRecorder { | 35 class RenderNodeDisplayList extends sky.PictureRecorder { |
36 RenderNodeDisplayList(double width, double height) : super(width, height); | 36 RenderNodeDisplayList(double width, double height) : super(width, height); |
37 void paintChild(RenderNode child, double x, double y) { | 37 void paintChild(RenderNode child, sky.Point position) { |
38 save(); | 38 save(); |
39 translate(x, y); | 39 translate(position.x, position.y); |
40 child.paint(this); | 40 child.paint(this); |
41 restore(); | 41 restore(); |
42 } | 42 } |
43 } | 43 } |
44 | 44 |
45 abstract class RenderNode extends AbstractNode { | 45 abstract class RenderNode extends AbstractNode { |
46 | 46 |
47 // LAYOUT | 47 // LAYOUT |
48 | 48 |
49 // parentData is only for use by the RenderNode that actually lays this | 49 // parentData is only for use by the RenderNode that actually lays this |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 // HIT TESTING | 191 // HIT TESTING |
192 | 192 |
193 void handlePointer(sky.PointerEvent event) { | 193 void handlePointer(sky.PointerEvent event) { |
194 // override this if you have a client, to hand it to the client | 194 // override this if you have a client, to hand it to the client |
195 // override this if you want to do anything with the pointer event | 195 // override this if you want to do anything with the pointer event |
196 } | 196 } |
197 | 197 |
198 // RenderNode subclasses are expected to have a method like the | 198 // RenderNode subclasses are expected to have a method like the |
199 // following (with the signature being whatever passes for coordinates | 199 // following (with the signature being whatever passes for coordinates |
200 // for this particular class): | 200 // for this particular class): |
201 // bool hitTest(HitTestResult result, { double x, double y }) { | 201 // bool hitTest(HitTestResult result, { sky.Point position }) { |
202 // // If (x,y) is not inside this node, then return false. (You | 202 // // If (x,y) is not inside this node, then return false. (You |
203 // // can assume that the given coordinate is inside your | 203 // // can assume that the given coordinate is inside your |
204 // // dimensions. You only need to check this if you're an | 204 // // dimensions. You only need to check this if you're an |
205 // // irregular shape, e.g. if you have a hole.) | 205 // // irregular shape, e.g. if you have a hole.) |
206 // // Otherwise: | 206 // // Otherwise: |
207 // // For each child that intersects x,y, in z-order starting from the top, | 207 // // For each child that intersects x,y, in z-order starting from the top, |
208 // // call hitTest() for that child, passing it /result/, and the coordinate
s | 208 // // call hitTest() for that child, passing it /result/, and the coordinate
s |
209 // // converted to the child's coordinate origin, and stop at the first chil
d | 209 // // converted to the child's coordinate origin, and stop at the first chil
d |
210 // // that returns true. | 210 // // that returns true. |
211 // // Then, add yourself to /result/, and return true. | 211 // // Then, add yourself to /result/, and return true. |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 final double maxHeight; | 438 final double maxHeight; |
439 | 439 |
440 double constrainWidth(double width) { | 440 double constrainWidth(double width) { |
441 return clamp(min: minWidth, max: maxWidth, value: width); | 441 return clamp(min: minWidth, max: maxWidth, value: width); |
442 } | 442 } |
443 | 443 |
444 double constrainHeight(double height) { | 444 double constrainHeight(double height) { |
445 return clamp(min: minHeight, max: maxHeight, value: height); | 445 return clamp(min: minHeight, max: maxHeight, value: height); |
446 } | 446 } |
447 | 447 |
| 448 sky.Size constrain(sky.Size size) { |
| 449 return new sky.Size(constrainWidth(size.width), constrainHeight(size.height)
); |
| 450 } |
| 451 |
448 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI
NITY; | 452 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI
NITY; |
449 } | 453 } |
450 | 454 |
| 455 // TODO(abarth): Replace with sky.Size. |
451 class BoxDimensions { | 456 class BoxDimensions { |
452 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); | 457 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); |
453 | 458 |
454 BoxDimensions.withConstraints( | 459 BoxDimensions.withConstraints( |
455 BoxConstraints constraints, | 460 BoxConstraints constraints, |
456 { double width: 0.0, double height: 0.0 } | 461 { double width: 0.0, double height: 0.0 } |
457 ) : width = constraints.constrainWidth(width), | 462 ) : width = constraints.constrainWidth(width), |
458 height = constraints.constrainHeight(height); | 463 height = constraints.constrainHeight(height); |
459 | 464 |
460 final double width; | 465 final double width; |
461 final double height; | 466 final double height; |
462 } | 467 } |
463 | 468 |
464 class BoxParentData extends ParentData { | 469 class BoxParentData extends ParentData { |
465 double x = 0.0; | 470 sky.Point position = new sky.Point(0.0, 0.0); |
466 double y = 0.0; | |
467 } | 471 } |
468 | 472 |
469 abstract class RenderBox extends RenderNode { | 473 abstract class RenderBox extends RenderNode { |
470 | 474 |
471 void setParentData(RenderNode child) { | 475 void setParentData(RenderNode child) { |
472 if (child.parentData is! BoxParentData) | 476 if (child.parentData is! BoxParentData) |
473 child.parentData = new BoxParentData(); | 477 child.parentData = new BoxParentData(); |
474 } | 478 } |
475 | 479 |
476 // override this to report what dimensions you would have if you | 480 // override this to report what dimensions you would have if you |
477 // were laid out with the given constraints this can walk the tree | 481 // were laid out with the given constraints this can walk the tree |
478 // if it must, but it should be as cheap as possible; just get the | 482 // if it must, but it should be as cheap as possible; just get the |
479 // dimensions and nothing else (e.g. don't calculate hypothetical | 483 // dimensions and nothing else (e.g. don't calculate hypothetical |
480 // child positions if they're not needed to determine dimensions) | 484 // child positions if they're not needed to determine dimensions) |
481 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 485 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
482 return new BoxDimensions.withConstraints(constraints); | 486 return new BoxDimensions.withConstraints(constraints); |
483 } | 487 } |
484 | 488 |
485 BoxConstraints get constraints => super.constraints as BoxConstraints; | 489 BoxConstraints get constraints => super.constraints as BoxConstraints; |
486 void performResize() { | 490 void performResize() { |
487 // default behaviour for subclasses that have sizedByParent = true | 491 // default behaviour for subclasses that have sizedByParent = true |
488 width = constraints.constrainWidth(0.0); | 492 size = constraints.constrain(new sky.Size(0.0, 0.0)); |
489 height = constraints.constrainHeight(0.0); | 493 assert(size.height < double.INFINITY); |
490 assert(height < double.INFINITY); | 494 assert(size.width < double.INFINITY); |
491 assert(width < double.INFINITY); | |
492 } | 495 } |
493 void performLayout() { | 496 void performLayout() { |
494 // descendants have to either override performLayout() to set both | 497 // descendants have to either override performLayout() to set both |
495 // width and height and lay out children, or, set sizedByParent to | 498 // width and height and lay out children, or, set sizedByParent to |
496 // true so that performResize()'s logic above does its thing. | 499 // true so that performResize()'s logic above does its thing. |
497 assert(sizedByParent); | 500 assert(sizedByParent); |
498 } | 501 } |
499 | 502 |
500 bool hitTest(HitTestResult result, { double x, double y }) { | 503 bool hitTest(HitTestResult result, { sky.Point position }) { |
501 hitTestChildren(result, x: x, y: y); | 504 hitTestChildren(result, position: position); |
502 result.add(this); | 505 result.add(this); |
503 return true; | 506 return true; |
504 } | 507 } |
505 void hitTestChildren(HitTestResult result, { double x, double y }) { } | 508 void hitTestChildren(HitTestResult result, { sky.Point position }) { } |
506 | 509 |
507 double width; | 510 sky.Size size = new sky.Size(0.0, 0.0); |
508 double height; | |
509 } | 511 } |
510 | 512 |
511 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { | 513 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { |
512 | 514 |
513 RenderPadding(EdgeDims padding, RenderBox child) { | 515 RenderPadding(EdgeDims padding, RenderBox child) { |
514 assert(padding != null); | 516 assert(padding != null); |
515 this.padding = padding; | 517 this.padding = padding; |
516 this.child = child; | 518 this.child = child; |
517 } | 519 } |
518 | 520 |
(...skipping 12 matching lines...) Expand all Loading... |
531 constraints = constraints.deflate(padding); | 533 constraints = constraints.deflate(padding); |
532 if (child == null) | 534 if (child == null) |
533 return super.getIntrinsicDimensions(constraints); | 535 return super.getIntrinsicDimensions(constraints); |
534 return child.getIntrinsicDimensions(constraints); | 536 return child.getIntrinsicDimensions(constraints); |
535 } | 537 } |
536 | 538 |
537 void performLayout() { | 539 void performLayout() { |
538 assert(padding != null); | 540 assert(padding != null); |
539 BoxConstraints innerConstraints = constraints.deflate(padding); | 541 BoxConstraints innerConstraints = constraints.deflate(padding); |
540 if (child == null) { | 542 if (child == null) { |
541 width = innerConstraints.constrainWidth(padding.left + padding.right); | 543 size = innerConstraints.constrain( |
542 height = innerConstraints.constrainHeight(padding.top + padding.bottom); | 544 new sky.Size(padding.left + padding.right, padding.top + padding.botto
m)); |
543 return; | 545 return; |
544 } | 546 } |
545 child.layout(innerConstraints, parentUsesSize: true); | 547 child.layout(innerConstraints, parentUsesSize: true); |
546 assert(child.parentData is BoxParentData); | 548 assert(child.parentData is BoxParentData); |
547 child.parentData.x = padding.left; | 549 child.parentData.position = new sky.Point(padding.left, padding.top); |
548 child.parentData.y = padding.top; | 550 size = constraints.constrain(new sky.Size(padding.left + child.size.width +
padding.right, |
549 width = constraints.constrainWidth(padding.left + child.width + padding.righ
t); | 551 padding.top + child.size.height +
padding.bottom)); |
550 height = constraints.constrainHeight(padding.top + child.height + padding.bo
ttom); | |
551 } | 552 } |
552 | 553 |
553 void paint(RenderNodeDisplayList canvas) { | 554 void paint(RenderNodeDisplayList canvas) { |
554 if (child != null) | 555 if (child != null) |
555 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 556 canvas.paintChild(child, child.parentData.position); |
556 } | 557 } |
557 | 558 |
558 void hitTestChildren(HitTestResult result, { double x, double y }) { | 559 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
559 if (child != null) { | 560 if (child != null) { |
560 assert(child.parentData is BoxParentData); | 561 assert(child.parentData is BoxParentData); |
561 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 562 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi
on, child.size); |
562 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) | 563 if (childRect.contains(position)) { |
563 child.hitTest(result, x: x+child.parentData.x, y: y+child.parentData.y); | 564 child.hitTest(result, position: new sky.Point(position.x - child.parentD
ata.position.x, |
| 565 position.y - child.parentD
ata.position.y)); |
| 566 } |
564 } | 567 } |
565 } | 568 } |
566 | 569 |
567 } | 570 } |
568 | 571 |
569 // This must be immutable, because we won't notice when it changes | 572 // This must be immutable, because we won't notice when it changes |
570 class BoxDecoration { | 573 class BoxDecoration { |
571 const BoxDecoration({ | 574 const BoxDecoration({ |
572 this.backgroundColor | 575 this.backgroundColor |
573 }); | 576 }); |
574 | 577 |
575 final int backgroundColor; | 578 final int backgroundColor; |
576 } | 579 } |
577 | 580 |
578 class RenderDecoratedBox extends RenderBox { | 581 class RenderDecoratedBox extends RenderBox { |
579 | 582 |
580 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; | 583 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; |
581 | 584 |
582 BoxDecoration _decoration; | 585 BoxDecoration _decoration; |
583 BoxDecoration get decoration => _decoration; | 586 BoxDecoration get decoration => _decoration; |
584 void set decoration (BoxDecoration value) { | 587 void set decoration (BoxDecoration value) { |
585 if (value == _decoration) | 588 if (value == _decoration) |
586 return; | 589 return; |
587 _decoration = value; | 590 _decoration = value; |
588 markNeedsPaint(); | 591 markNeedsPaint(); |
589 } | 592 } |
590 | 593 |
591 void paint(RenderNodeDisplayList canvas) { | 594 void paint(RenderNodeDisplayList canvas) { |
592 assert(width != null); | 595 assert(size.width != null); |
593 assert(height != null); | 596 assert(size.height != null); |
594 | 597 |
595 if (_decoration == null) | 598 if (_decoration == null) |
596 return; | 599 return; |
597 | 600 |
598 if (_decoration.backgroundColor != null) { | 601 if (_decoration.backgroundColor != null) { |
599 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 602 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
600 canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint); | 603 canvas.drawRect(new sky.Rect.fromLTRB(0.0, 0.0, size.width, size.height),
paint); |
601 } | 604 } |
602 } | 605 } |
603 | 606 |
604 } | 607 } |
605 | 608 |
606 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM
ixin<RenderBox> { | 609 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM
ixin<RenderBox> { |
607 RenderDecoratedCircle({ | 610 RenderDecoratedCircle({ |
608 BoxDecoration decoration, | 611 BoxDecoration decoration, |
609 RenderBox child | 612 RenderBox child |
610 }) : super(decoration) { | 613 }) : super(decoration) { |
611 this.child = child; | 614 this.child = child; |
612 } | 615 } |
613 | 616 |
614 void paint(RenderNodeDisplayList canvas) { | 617 void paint(RenderNodeDisplayList canvas) { |
615 assert(width != null); | 618 assert(size.width != null); |
616 assert(height != null); | 619 assert(size.height != null); |
617 | 620 |
618 if (_decoration == null) | 621 if (_decoration == null) |
619 return; | 622 return; |
620 | 623 |
621 if (_decoration.backgroundColor != null) { | 624 if (_decoration.backgroundColor != null) { |
622 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 625 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
623 canvas.drawCircle(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint)
; | 626 canvas.drawCircle(0.0, 0.0, (size.width + size.height) / 2, paint); |
624 } | 627 } |
625 } | 628 } |
626 } | 629 } |
627 | 630 |
628 | 631 |
629 // RENDER VIEW LAYOUT MANAGER | 632 // RENDER VIEW LAYOUT MANAGER |
630 | 633 |
631 class ViewConstraints { | 634 class ViewConstraints { |
632 | 635 |
633 const ViewConstraints({ | 636 const ViewConstraints({ |
634 this.width: 0.0, this.height: 0.0, this.orientation: null | 637 this.width: 0.0, this.height: 0.0, this.orientation: null |
635 }); | 638 }); |
636 | 639 |
637 final double width; | 640 final double width; |
638 final double height; | 641 final double height; |
639 final int orientation; | 642 final int orientation; |
640 | 643 |
641 } | 644 } |
642 | 645 |
643 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { | 646 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { |
644 | 647 |
645 RenderView({ | 648 RenderView({ |
646 RenderBox child, | 649 RenderBox child, |
647 this.timeForRotation: const Duration(microseconds: 83333) | 650 this.timeForRotation: const Duration(microseconds: 83333) |
648 }) { | 651 }) { |
649 this.child = child; | 652 this.child = child; |
650 } | 653 } |
651 | 654 |
652 double _width; | 655 sky.Size _size = new sky.Size(0.0, 0.0); |
653 double get width => _width; | 656 double get width => _size.width; |
654 double _height; | 657 double get height => _size.height; |
655 double get height => _height; | |
656 | 658 |
657 int _orientation; // 0..3 | 659 int _orientation; // 0..3 |
658 int get orientation => _orientation; | 660 int get orientation => _orientation; |
659 Duration timeForRotation; | 661 Duration timeForRotation; |
660 | 662 |
661 ViewConstraints get constraints => super.constraints as ViewConstraints; | 663 ViewConstraints get constraints => super.constraints as ViewConstraints; |
662 bool get sizedByParent => true; | 664 bool get sizedByParent => true; |
663 void performResize() { | 665 void performResize() { |
664 if (constraints.orientation != _orientation) { | 666 if (constraints.orientation != _orientation) { |
665 if (_orientation != null && child != null) | 667 if (_orientation != null && child != null) |
666 child.rotate(oldAngle: _orientation, newAngle: constraints.orientation,
time: timeForRotation); | 668 child.rotate(oldAngle: _orientation, newAngle: constraints.orientation,
time: timeForRotation); |
667 _orientation = constraints.orientation; | 669 _orientation = constraints.orientation; |
668 } | 670 } |
669 _width = constraints.width; | 671 _size = new sky.Size(constraints.width, constraints.height); |
670 _height = constraints.height; | 672 assert(_size.height < double.INFINITY); |
671 assert(height < double.INFINITY); | 673 assert(_size.width < double.INFINITY); |
672 assert(width < double.INFINITY); | |
673 } | 674 } |
674 void performLayout() { | 675 void performLayout() { |
675 if (child != null) { | 676 if (child != null) { |
676 child.layout(new BoxConstraints.tight(width: width, height: height)); | 677 child.layout(new BoxConstraints.tight(width: width, height: height)); |
677 assert(child.width == width); | 678 assert(child.size.width == width); |
678 assert(child.height == height); | 679 assert(child.size.height == height); |
679 } | 680 } |
680 } | 681 } |
681 | 682 |
682 void rotate({ int oldAngle, int newAngle, Duration time }) { | 683 void rotate({ int oldAngle, int newAngle, Duration time }) { |
683 assert(false); // nobody tells the screen to rotate, the whole rotate() danc
e is started from our performResize() | 684 assert(false); // nobody tells the screen to rotate, the whole rotate() danc
e is started from our performResize() |
684 } | 685 } |
685 | 686 |
686 bool hitTest(HitTestResult result, { double x, double y }) { | 687 bool hitTest(HitTestResult result, { sky.Point position }) { |
687 if (child != null && x >= 0.0 && x < child.width && y >= 0.0 && y < child.he
ight) | 688 if (child != null) { |
688 child.hitTest(result, x: x, y: y); | 689 sky.Rect childRect = new sky.Rect.fromPointAndSize(new sky.Point(0.0, 0.0)
, child.size); |
| 690 if (childRect.contains(position)) |
| 691 child.hitTest(result, position: position); |
| 692 } |
689 result.add(this); | 693 result.add(this); |
690 return true; | 694 return true; |
691 } | 695 } |
692 | 696 |
693 void paint(RenderNodeDisplayList canvas) { | 697 void paint(RenderNodeDisplayList canvas) { |
694 if (child != null) | 698 if (child != null) |
695 canvas.paintChild(child, 0.0, 0.0); | 699 canvas.paintChild(child, new sky.Point(0.0, 0.0)); |
696 } | 700 } |
697 | 701 |
698 void paintFrame() { | 702 void paintFrame() { |
699 RenderNode._debugDoingPaint = true; | 703 RenderNode._debugDoingPaint = true; |
700 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); | 704 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); |
701 paint(canvas); | 705 paint(canvas); |
702 sky.view.picture = canvas.endRecording(); | 706 sky.view.picture = canvas.endRecording(); |
703 RenderNode._debugDoingPaint = false; | 707 RenderNode._debugDoingPaint = false; |
704 } | 708 } |
705 | 709 |
706 } | 710 } |
707 | 711 |
708 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS | 712 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS |
709 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend
erNodeMixin<ChildType, ParentDataType> { | 713 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend
erNodeMixin<ChildType, ParentDataType> { |
710 | 714 |
711 void defaultHitTestChildren(HitTestResult result, { double x, double y }) { | 715 void defaultHitTestChildren(HitTestResult result, { sky.Point position }) { |
712 // the x, y parameters have the top left of the node's box as the origin | 716 // the x, y parameters have the top left of the node's box as the origin |
713 ChildType child = lastChild; | 717 ChildType child = lastChild; |
714 while (child != null) { | 718 while (child != null) { |
715 assert(child.parentData is BoxParentData); | 719 assert(child.parentData is BoxParentData); |
716 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 720 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi
on, child.size); |
717 (y >= child.parentData.y) && (y < child.parentData.y + child.height))
{ | 721 if (childRect.contains(position)) { |
718 if (child.hitTest(result, x: x-child.parentData.x, y: y-child.parentData
.y)) | 722 if (child.hitTest(result, position: new sky.Point(position.x - child.par
entData.position.x, |
| 723 position.y - child.par
entData.position.y))) |
719 break; | 724 break; |
720 } | 725 } |
721 child = child.parentData.previousSibling; | 726 child = child.parentData.previousSibling; |
722 } | 727 } |
723 } | 728 } |
724 | 729 |
725 void defaultPaint(RenderNodeDisplayList canvas) { | 730 void defaultPaint(RenderNodeDisplayList canvas) { |
726 RenderBox child = firstChild; | 731 RenderBox child = firstChild; |
727 while (child != null) { | 732 while (child != null) { |
728 assert(child.parentData is BoxParentData); | 733 assert(child.parentData is BoxParentData); |
729 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 734 canvas.paintChild(child, child.parentData.position); |
730 child = child.parentData.nextSibling; | 735 child = child.parentData.nextSibling; |
731 } | 736 } |
732 } | 737 } |
733 } | 738 } |
734 | 739 |
735 // BLOCK LAYOUT MANAGER | 740 // BLOCK LAYOUT MANAGER |
736 | 741 |
737 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render
Box> { } | 742 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render
Box> { } |
738 | 743 |
739 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
rBox, BlockParentData>, | 744 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
rBox, BlockParentData>, |
(...skipping 29 matching lines...) Expand all Loading... |
769 assert(child.parentData is BlockParentData); | 774 assert(child.parentData is BlockParentData); |
770 child = child.parentData.nextSibling; | 775 child = child.parentData.nextSibling; |
771 } | 776 } |
772 | 777 |
773 return new BoxDimensions(width: outerWidth, | 778 return new BoxDimensions(width: outerWidth, |
774 height: constraints.constrainHeight(outerHeight)); | 779 height: constraints.constrainHeight(outerHeight)); |
775 } | 780 } |
776 | 781 |
777 void performLayout() { | 782 void performLayout() { |
778 assert(constraints is BoxConstraints); | 783 assert(constraints is BoxConstraints); |
779 width = constraints.constrainWidth(constraints.maxWidth); | 784 size.width = constraints.constrainWidth(constraints.maxWidth); |
780 assert(width < double.INFINITY); | 785 assert(size.width < double.INFINITY); |
781 double y = 0.0; | 786 double y = 0.0; |
782 double innerWidth = width; | 787 double innerWidth = size.width; |
783 RenderBox child = firstChild; | 788 RenderBox child = firstChild; |
784 while (child != null) { | 789 while (child != null) { |
785 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), parentUsesSize: true); | 790 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), parentUsesSize: true); |
786 assert(child.parentData is BlockParentData); | 791 assert(child.parentData is BlockParentData); |
787 child.parentData.x = 0.0; | 792 child.parentData.position = new sky.Point(0.0, y); |
788 child.parentData.y = y; | 793 y += child.size.height; |
789 y += child.height; | |
790 child = child.parentData.nextSibling; | 794 child = child.parentData.nextSibling; |
791 } | 795 } |
792 height = constraints.constrainHeight(y); | 796 size.height = constraints.constrainHeight(y); |
793 } | 797 } |
794 | 798 |
795 void hitTestChildren(HitTestResult result, { double x, double y }) { | 799 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
796 defaultHitTestChildren(result, x: x, y: y); | 800 defaultHitTestChildren(result, position: position); |
797 } | 801 } |
798 | 802 |
799 void paint(RenderNodeDisplayList canvas) { | 803 void paint(RenderNodeDisplayList canvas) { |
800 super.paint(canvas); | 804 super.paint(canvas); |
801 defaultPaint(canvas); | 805 defaultPaint(canvas); |
802 } | 806 } |
803 | 807 |
804 } | 808 } |
805 | 809 |
806 // FLEXBOX LAYOUT MANAGER | 810 // FLEXBOX LAYOUT MANAGER |
(...skipping 27 matching lines...) Expand all Loading... |
834 } | 838 } |
835 } | 839 } |
836 | 840 |
837 void setParentData(RenderBox child) { | 841 void setParentData(RenderBox child) { |
838 if (child.parentData is! FlexBoxParentData) | 842 if (child.parentData is! FlexBoxParentData) |
839 child.parentData = new FlexBoxParentData(); | 843 child.parentData = new FlexBoxParentData(); |
840 } | 844 } |
841 | 845 |
842 bool get sizedByParent => true; | 846 bool get sizedByParent => true; |
843 void performResize() { | 847 void performResize() { |
844 width = _constraints.constrainWidth(_constraints.maxWidth); | 848 size = _constraints.constrain(new sky.Size(_constraints.maxWidth, _constrain
ts.maxHeight)); |
845 height = _constraints.constrainHeight(_constraints.maxHeight); | 849 assert(size.height < double.INFINITY); |
846 assert(height < double.INFINITY); | 850 assert(size.width < double.INFINITY); |
847 assert(width < double.INFINITY); | |
848 } | 851 } |
849 | 852 |
850 int _getFlex(RenderBox child) { | 853 int _getFlex(RenderBox child) { |
851 assert(child.parentData is FlexBoxParentData); | 854 assert(child.parentData is FlexBoxParentData); |
852 return child.parentData.flex != null ? child.parentData.flex : 0; | 855 return child.parentData.flex != null ? child.parentData.flex : 0; |
853 } | 856 } |
854 | 857 |
855 void performLayout() { | 858 void performLayout() { |
856 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib
le Lengths | 859 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib
le Lengths |
857 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f
ree space | 860 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f
ree space |
858 int totalFlex = 0; | 861 int totalFlex = 0; |
859 assert(constraints != null); | 862 assert(constraints != null); |
860 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma
xWidth : constraints.maxHeight; | 863 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma
xWidth : constraints.maxHeight; |
861 RenderBox child = firstChild; | 864 RenderBox child = firstChild; |
862 while (child != null) { | 865 while (child != null) { |
863 int flex = _getFlex(child); | 866 int flex = _getFlex(child); |
864 if (flex > 0) { | 867 if (flex > 0) { |
865 totalFlex += child.parentData.flex; | 868 totalFlex += child.parentData.flex; |
866 } else { | 869 } else { |
867 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai
nts.maxHeight, | 870 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai
nts.maxHeight, |
868 maxWidth: constrain
ts.maxWidth); | 871 maxWidth: constrain
ts.maxWidth); |
869 child.layout(innerConstraints, parentUsesSize: true); | 872 child.layout(innerConstraints, parentUsesSize: true); |
870 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch
ild.height; | 873 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.size.width
: child.size.height; |
871 } | 874 } |
872 child = child.parentData.nextSibling; | 875 child = child.parentData.nextSibling; |
873 } | 876 } |
874 | 877 |
875 // Steps 4-5. Distribute remaining space to flexible children. | 878 // Steps 4-5. Distribute remaining space to flexible children. |
876 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; | 879 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; |
877 double usedSpace = 0.0; | 880 double usedSpace = 0.0; |
878 child = firstChild; | 881 child = firstChild; |
879 while (child != null) { | 882 while (child != null) { |
880 int flex = _getFlex(child); | 883 int flex = _getFlex(child); |
(...skipping 11 matching lines...) Expand all Loading... |
892 maxHeight: spaceForChild, | 895 maxHeight: spaceForChild, |
893 maxWidth: constraints.maxWidth
); | 896 maxWidth: constraints.maxWidth
); |
894 break; | 897 break; |
895 } | 898 } |
896 child.layout(innerConstraints, parentUsesSize: true); | 899 child.layout(innerConstraints, parentUsesSize: true); |
897 } | 900 } |
898 | 901 |
899 // For now, center the flex items in the cross direction | 902 // For now, center the flex items in the cross direction |
900 switch (_direction) { | 903 switch (_direction) { |
901 case FlexDirection.Horizontal: | 904 case FlexDirection.Horizontal: |
902 child.parentData.x = usedSpace; | 905 child.parentData.position = new sky.Point(usedSpace, size.height / 2.0
- child.size.height / 2.0); |
903 usedSpace += child.width; | 906 usedSpace += child.size.width; |
904 child.parentData.y = height / 2.0 - child.height / 2.0; | |
905 break; | 907 break; |
906 case FlexDirection.Vertical: | 908 case FlexDirection.Vertical: |
907 child.parentData.y = usedSpace; | 909 child.parentData.position = new sky.Point(size.width / 2.0 - child.siz
e.width / 2.0, usedSpace); |
908 usedSpace += child.height; | 910 usedSpace += child.size.height; |
909 child.parentData.x = width / 2.0 - child.width / 2.0; | |
910 break; | 911 break; |
911 } | 912 } |
912 child = child.parentData.nextSibling; | 913 child = child.parentData.nextSibling; |
913 } | 914 } |
914 } | 915 } |
915 | 916 |
916 void hitTestChildren(HitTestResult result, { double x, double y }) { | 917 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
917 defaultHitTestChildren(result, x: x, y: y); | 918 defaultHitTestChildren(result, position: position); |
918 } | 919 } |
919 | 920 |
920 void paint(RenderNodeDisplayList canvas) { | 921 void paint(RenderNodeDisplayList canvas) { |
921 super.paint(canvas); | 922 super.paint(canvas); |
922 defaultPaint(canvas); | 923 defaultPaint(canvas); |
923 } | 924 } |
924 } | 925 } |
OLD | NEW |