Chromium Code Reviews| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 255 class HitTestResult { | 255 class HitTestResult { |
| 256 final List<RenderNode> path = new List<RenderNode>(); | 256 final List<RenderNode> path = new List<RenderNode>(); |
| 257 | 257 |
| 258 RenderNode get result => path.first; | 258 RenderNode get result => path.first; |
| 259 | 259 |
| 260 void add(RenderNode node) { | 260 void add(RenderNode node) { |
| 261 path.add(node); | 261 path.add(node); |
| 262 } | 262 } |
| 263 } | 263 } |
| 264 | 264 |
| 265 | |
| 266 // GENERIC MIXIN FOR RENDER NODES WITH ONE CHILD | |
| 267 | |
| 265 abstract class RenderNodeWithChildMixin<ChildType extends RenderNode> { | 268 abstract class RenderNodeWithChildMixin<ChildType extends RenderNode> { |
| 266 ChildType _child; | 269 ChildType _child; |
| 267 ChildType get child => _child; | 270 ChildType get child => _child; |
| 268 void set child (ChildType value) { | 271 void set child (ChildType value) { |
| 269 if (_child != null) | 272 if (_child != null) |
| 270 dropChild(_child); | 273 dropChild(_child); |
| 271 _child = value; | 274 _child = value; |
| 272 if (_child != null) | 275 if (_child != null) |
| 273 adoptChild(_child); | 276 adoptChild(_child); |
| 274 markNeedsLayout(); | 277 markNeedsLayout(); |
| 275 } | 278 } |
| 276 } | 279 } |
| 277 | 280 |
| 278 // GENERIC MIXIN FOR RENDER NODES THAT TAKE A LIST OF CHILDREN | 281 |
| 282 // GENERIC MIXIN FOR RENDER NODES WITH A LIST OF CHILDREN | |
| 279 | 283 |
| 280 abstract class ContainerParentDataMixin<ChildType extends RenderNode> { | 284 abstract class ContainerParentDataMixin<ChildType extends RenderNode> { |
| 281 ChildType previousSibling; | 285 ChildType previousSibling; |
| 282 ChildType nextSibling; | 286 ChildType nextSibling; |
| 283 void detachSiblings() { | 287 void detachSiblings() { |
| 284 if (previousSibling != null) { | 288 if (previousSibling != null) { |
| 285 assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>); | 289 assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>); |
| 286 assert(previousSibling != this); | 290 assert(previousSibling != this); |
| 287 assert(previousSibling.parentData.nextSibling == this); | 291 assert(previousSibling.parentData.nextSibling == this); |
| 288 previousSibling.parentData.nextSibling = nextSibling; | 292 previousSibling.parentData.nextSibling = nextSibling; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 assert(child.parentData is ParentDataType); | 427 assert(child.parentData is ParentDataType); |
| 424 return child.parentData.nextSibling; | 428 return child.parentData.nextSibling; |
| 425 } | 429 } |
| 426 | 430 |
| 427 } | 431 } |
| 428 | 432 |
| 429 | 433 |
| 430 // GENERIC BOX RENDERING | 434 // GENERIC BOX RENDERING |
| 431 // Anything that has a concept of x, y, width, height is going to derive from th is | 435 // Anything that has a concept of x, y, width, height is going to derive from th is |
| 432 | 436 |
| 437 class EdgeDims { | |
| 438 // used for e.g. padding | |
| 439 const EdgeDims(this.top, this.right, this.bottom, this.left); | |
| 440 final double top; | |
| 441 final double right; | |
| 442 final double bottom; | |
| 443 final double left; | |
| 444 operator ==(EdgeDims other) => (top == other.top) || | |
| 445 (right == other.right) || | |
| 446 (bottom == other.bottom) || | |
| 447 (left == other.left); | |
| 448 } | |
| 449 | |
| 433 class BoxConstraints { | 450 class BoxConstraints { |
| 434 const BoxConstraints({ | 451 const BoxConstraints({ |
| 435 this.minWidth: 0.0, | 452 this.minWidth: 0.0, |
| 436 this.maxWidth: double.INFINITY, | 453 this.maxWidth: double.INFINITY, |
| 437 this.minHeight: 0.0, | 454 this.minHeight: 0.0, |
| 438 this.maxHeight: double.INFINITY}); | 455 this.maxHeight: double.INFINITY}); |
| 439 | 456 |
| 440 const BoxConstraints.tight({ double width: 0.0, double height: 0.0 }) | 457 const BoxConstraints.tight({ double width: 0.0, double height: 0.0 }) |
| 441 : minWidth = width, | 458 : minWidth = width, |
| 442 maxWidth = width, | 459 maxWidth = width, |
| 443 minHeight = height, | 460 minHeight = height, |
| 444 maxHeight = height; | 461 maxHeight = height; |
| 445 | 462 |
| 463 BoxConstraints deflate(EdgeDims edges) { | |
| 464 assert(edges != null); | |
| 465 return new BoxConstraints( | |
| 466 minWidth: minWidth, | |
| 467 maxWidth: maxWidth - (edges.left + edges.right), | |
| 468 minHeight: minHeight, | |
| 469 maxHeight: maxHeight - (edges.top + edges.bottom) | |
| 470 ); | |
| 471 } | |
| 472 | |
| 446 final double minWidth; | 473 final double minWidth; |
| 447 final double maxWidth; | 474 final double maxWidth; |
| 448 final double minHeight; | 475 final double minHeight; |
| 449 final double maxHeight; | 476 final double maxHeight; |
| 450 | 477 |
| 451 double constrainWidth(double width) { | 478 double constrainWidth(double width) { |
| 452 return clamp(min: minWidth, max: maxWidth, value: width); | 479 return clamp(min: minWidth, max: maxWidth, value: width); |
| 453 } | 480 } |
| 454 | 481 |
| 455 double constrainHeight(double height) { | 482 double constrainHeight(double height) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 hitTestChildren(result, x: x, y: y); | 532 hitTestChildren(result, x: x, y: y); |
| 506 result.add(this); | 533 result.add(this); |
| 507 return true; | 534 return true; |
| 508 } | 535 } |
| 509 void hitTestChildren(HitTestResult result, { double x, double y }) { } | 536 void hitTestChildren(HitTestResult result, { double x, double y }) { } |
| 510 | 537 |
| 511 double width; | 538 double width; |
| 512 double height; | 539 double height; |
| 513 } | 540 } |
| 514 | 541 |
| 542 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { | |
| 543 | |
| 544 RenderPadding(EdgeDims padding, RenderBox child) { | |
| 545 assert(padding != null); | |
| 546 this.padding = padding; | |
| 547 this.child = child; | |
| 548 } | |
| 549 | |
| 550 EdgeDims _padding; | |
| 551 EdgeDims get padding => _padding; | |
| 552 void set padding (EdgeDims value) { | |
| 553 assert(value != null); | |
| 554 if (_padding != value) { | |
| 555 _padding = value; | |
| 556 markNeedsLayout(); | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | |
| 561 assert(padding != null); | |
| 562 constraints = constraints.deflate(padding); | |
| 563 if (child == null) | |
| 564 return super.getIntrinsicDimensions(constraints); | |
| 565 return child.getIntrinsicDimensions(constraints); | |
| 566 } | |
| 567 | |
| 568 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | |
| 569 assert(padding != null); | |
| 570 constraints = constraints.deflate(padding); | |
| 571 if (child == null) { | |
| 572 width = constraints.constrainWidth(padding.left + padding.right); | |
| 573 height = constraints.constrainHeight(padding.top + padding.bottom); | |
| 574 return; | |
| 575 } | |
| 576 if (relayoutSubtreeRoot != null) | |
| 577 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | |
| 578 else | |
| 579 relayoutSubtreeRoot = this; | |
| 580 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); | |
| 581 assert(child.parentData is BoxParentData); | |
| 582 child.parentData.x = padding.left; | |
| 583 child.parentData.y = padding.top; | |
| 584 width = constraints.constrainWidth(padding.left + child.width + padding.righ t); | |
| 585 height = constraints.constrainHeight(padding.top + child.height + padding.bo ttom); | |
| 586 } | |
| 587 | |
| 588 void paint(RenderNodeDisplayList canvas) { | |
| 589 if (child != null) | |
| 590 canvas.paintChild(child, child.parentData.x, child.parentData.y); | |
| 591 } | |
|
abarth-chromium
2015/05/27 23:50:03
hitTestChildren?
| |
| 592 | |
| 593 } | |
| 594 | |
| 515 // This must be immutable, because we won't notice when it changes | 595 // This must be immutable, because we won't notice when it changes |
| 516 class BoxDecoration { | 596 class BoxDecoration { |
| 517 const BoxDecoration({ | 597 const BoxDecoration({ |
| 518 this.backgroundColor | 598 this.backgroundColor |
| 519 }); | 599 }); |
| 520 | 600 |
| 521 final int backgroundColor; | 601 final int backgroundColor; |
| 522 } | 602 } |
| 523 | 603 |
| 524 class RenderDecoratedBox extends RenderBox { | 604 class RenderDecoratedBox extends RenderBox { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 _width = newWidth; | 686 _width = newWidth; |
| 607 _height = newHeight; | 687 _height = newHeight; |
| 608 relayout(); | 688 relayout(); |
| 609 } else { | 689 } else { |
| 610 layoutDone(); | 690 layoutDone(); |
| 611 } | 691 } |
| 612 } | 692 } |
| 613 | 693 |
| 614 void relayout() { | 694 void relayout() { |
| 615 if (child != null) { | 695 if (child != null) { |
| 616 child.layout(new BoxConstraints( | 696 child.layout(new BoxConstraints.tight(width: width, height: height)); |
| 617 minWidth: width, | |
| 618 maxWidth: width, | |
| 619 minHeight: height, | |
| 620 maxHeight: height | |
| 621 )); | |
| 622 assert(child.width == width); | 697 assert(child.width == width); |
| 623 assert(child.height == height); | 698 assert(child.height == height); |
| 624 } | 699 } |
| 625 layoutDone(); | 700 layoutDone(); |
| 626 } | 701 } |
| 627 | 702 |
| 628 void rotate({ int oldAngle, int newAngle, Duration time }) { | 703 void rotate({ int oldAngle, int newAngle, Duration time }) { |
| 629 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our layout() | 704 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our layout() |
| 630 } | 705 } |
| 631 | 706 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 while (child != null) { | 752 while (child != null) { |
| 678 assert(child.parentData is BoxParentData); | 753 assert(child.parentData is BoxParentData); |
| 679 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 754 canvas.paintChild(child, child.parentData.x, child.parentData.y); |
| 680 child = child.parentData.nextSibling; | 755 child = child.parentData.nextSibling; |
| 681 } | 756 } |
| 682 } | 757 } |
| 683 } | 758 } |
| 684 | 759 |
| 685 // BLOCK LAYOUT MANAGER | 760 // BLOCK LAYOUT MANAGER |
| 686 | 761 |
| 687 class EdgeDims { | |
| 688 // used for e.g. padding | |
| 689 const EdgeDims(this.top, this.right, this.bottom, this.left); | |
| 690 final double top; | |
| 691 final double right; | |
| 692 final double bottom; | |
| 693 final double left; | |
| 694 operator ==(EdgeDims other) => (top == other.top) || | |
| 695 (right == other.right) || | |
| 696 (bottom == other.bottom) || | |
| 697 (left == other.left); | |
| 698 } | |
| 699 | |
| 700 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render Box> { } | 762 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render Box> { } |
| 701 | 763 |
| 702 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende rBox, BlockParentData>, | 764 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende rBox, BlockParentData>, |
| 703 RenderBoxContainerDefaultsMixi n<RenderBox, BlockParentData> { | 765 RenderBoxContainerDefaultsMixi n<RenderBox, BlockParentData> { |
| 704 // lays out RenderBox children in a vertical stack | 766 // lays out RenderBox children in a vertical stack |
| 705 // uses the maximum width provided by the parent | 767 // uses the maximum width provided by the parent |
| 706 // sizes itself to the height of its child stack | 768 // sizes itself to the height of its child stack |
| 707 | 769 |
| 708 RenderBlock({ | 770 RenderBlock({ |
| 709 BoxDecoration decoration, | 771 BoxDecoration decoration |
| 710 EdgeDims padding: const EdgeDims(0.0, 0.0, 0.0, 0.0) | 772 }) : super(decoration); |
| 711 }) : super(decoration), _padding = padding; | |
| 712 | |
| 713 EdgeDims _padding; | |
| 714 EdgeDims get padding => _padding; | |
| 715 void set padding (EdgeDims value) { | |
| 716 assert(value != null); | |
| 717 if (_padding != value) { | |
| 718 _padding = value; | |
| 719 markNeedsLayout(); | |
| 720 } | |
| 721 } | |
| 722 | 773 |
| 723 void setParentData(RenderBox child) { | 774 void setParentData(RenderBox child) { |
| 724 if (child.parentData is! BlockParentData) | 775 if (child.parentData is! BlockParentData) |
| 725 child.parentData = new BlockParentData(); | 776 child.parentData = new BlockParentData(); |
| 726 } | 777 } |
| 727 | 778 |
| 728 // override this to report what dimensions you would have if you | 779 // override this to report what dimensions you would have if you |
| 729 // were laid out with the given constraints this can walk the tree | 780 // were laid out with the given constraints this can walk the tree |
| 730 // if it must, but it should be as cheap as possible; just get the | 781 // if it must, but it should be as cheap as possible; just get the |
| 731 // dimensions and nothing else (e.g. don't calculate hypothetical | 782 // dimensions and nothing else (e.g. don't calculate hypothetical |
| 732 // child positions if they're not needed to determine dimensions) | 783 // child positions if they're not needed to determine dimensions) |
| 733 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 784 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 734 double outerHeight = _padding.top + _padding.bottom; | 785 double outerHeight = 0.0; |
| 735 double outerWidth = constraints.constrainWidth(constraints.maxWidth); | 786 double outerWidth = constraints.constrainWidth(constraints.maxWidth); |
| 736 assert(outerWidth < double.INFINITY); | 787 assert(outerWidth < double.INFINITY); |
| 737 double innerWidth = outerWidth - (_padding.left + _padding.right); | 788 double innerWidth = outerWidth; |
| 738 RenderBox child = firstChild; | 789 RenderBox child = firstChild; |
| 739 BoxConstraints innerConstraints = new BoxConstraints(minWidth: innerWidth, | 790 BoxConstraints innerConstraints = new BoxConstraints(minWidth: innerWidth, |
| 740 maxWidth: innerWidth); | 791 maxWidth: innerWidth); |
| 741 while (child != null) { | 792 while (child != null) { |
| 742 outerHeight += child.getIntrinsicDimensions(innerConstraints).height; | 793 outerHeight += child.getIntrinsicDimensions(innerConstraints).height; |
| 743 assert(child.parentData is BlockParentData); | 794 assert(child.parentData is BlockParentData); |
| 744 child = child.parentData.nextSibling; | 795 child = child.parentData.nextSibling; |
| 745 } | 796 } |
| 746 | 797 |
| 747 return new BoxDimensions(width: outerWidth, | 798 return new BoxDimensions(width: outerWidth, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 759 _constraints = constraints; | 810 _constraints = constraints; |
| 760 internalLayout(relayoutSubtreeRoot); | 811 internalLayout(relayoutSubtreeRoot); |
| 761 } | 812 } |
| 762 | 813 |
| 763 void relayout() { | 814 void relayout() { |
| 764 internalLayout(this); | 815 internalLayout(this); |
| 765 } | 816 } |
| 766 | 817 |
| 767 void internalLayout(RenderNode relayoutSubtreeRoot) { | 818 void internalLayout(RenderNode relayoutSubtreeRoot) { |
| 768 assert(_constraints != null); | 819 assert(_constraints != null); |
| 769 double y = _padding.top; | 820 double y = 0.0; |
| 770 double innerWidth = width - (_padding.left + _padding.right); | 821 double innerWidth = width; |
| 771 RenderBox child = firstChild; | 822 RenderBox child = firstChild; |
| 772 while (child != null) { | 823 while (child != null) { |
| 773 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), | 824 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), |
| 774 relayoutSubtreeRoot: relayoutSubtreeRoot); | 825 relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 775 assert(child.parentData is BlockParentData); | 826 assert(child.parentData is BlockParentData); |
| 776 child.parentData.x = _padding.left; | 827 child.parentData.x = 0.0; |
| 777 child.parentData.y = y; | 828 child.parentData.y = y; |
| 778 y += child.height; | 829 y += child.height; |
| 779 child = child.parentData.nextSibling; | 830 child = child.parentData.nextSibling; |
| 780 } | 831 } |
| 781 height = _constraints.constrainHeight(y + _padding.bottom); | 832 height = _constraints.constrainHeight(y); |
| 782 layoutDone(); | 833 layoutDone(); |
| 783 } | 834 } |
| 784 | 835 |
| 785 void hitTestChildren(HitTestResult result, { double x, double y }) { | 836 void hitTestChildren(HitTestResult result, { double x, double y }) { |
| 786 defaultHitTestChildren(result, x: x, y: y); | 837 defaultHitTestChildren(result, x: x, y: y); |
| 787 } | 838 } |
| 788 | 839 |
| 789 void paint(RenderNodeDisplayList canvas) { | 840 void paint(RenderNodeDisplayList canvas) { |
| 790 super.paint(canvas); | 841 super.paint(canvas); |
| 791 defaultPaint(canvas); | 842 defaultPaint(canvas); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 917 | 968 |
| 918 void hitTestChildren(HitTestResult result, { double x, double y }) { | 969 void hitTestChildren(HitTestResult result, { double x, double y }) { |
| 919 defaultHitTestChildren(result, x: x, y: y); | 970 defaultHitTestChildren(result, x: x, y: y); |
| 920 } | 971 } |
| 921 | 972 |
| 922 void paint(RenderNodeDisplayList canvas) { | 973 void paint(RenderNodeDisplayList canvas) { |
| 923 super.paint(canvas); | 974 super.paint(canvas); |
| 924 defaultPaint(canvas); | 975 defaultPaint(canvas); |
| 925 } | 976 } |
| 926 } | 977 } |
| OLD | NEW |