Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 library layout; | 1 library layout; |
| 2 | 2 |
| 3 // This version of layout.dart is an update to the other one, this one using new APIs. | 3 // This version of layout.dart is an update to the other one, this one using new APIs. |
| 4 // It will not work in a stock Sky setup currently. | 4 // It will not work in a stock Sky setup currently. |
| 5 | 5 |
| 6 import 'node.dart'; | 6 import 'node.dart'; |
| 7 | 7 |
| 8 import 'dart:sky' as sky; | 8 import 'dart:sky' as sky; |
| 9 | 9 |
| 10 // ABSTRACT LAYOUT | 10 // ABSTRACT LAYOUT |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 454 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 455 return new BoxDimensions.withConstraints(constraints); | 455 return new BoxDimensions.withConstraints(constraints); |
| 456 } | 456 } |
| 457 | 457 |
| 458 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 458 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 459 width = constraints.constrainWidth(0.0); | 459 width = constraints.constrainWidth(0.0); |
| 460 height = constraints.constrainHeight(0.0); | 460 height = constraints.constrainHeight(0.0); |
| 461 layoutDone(); | 461 layoutDone(); |
| 462 } | 462 } |
| 463 | 463 |
| 464 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { | |
|
Hixie
2015/05/22 20:32:16
This can't be in a class above ContainerRenderNode
jackson
2015/05/23 00:21:04
Acknowledged.
| |
| 465 // the x, y parameters have the top left of the node's box as the origin | |
| 466 RenderBox child = _lastChild; | |
| 467 while (child != null) { | |
| 468 assert(child.parentData is BoxParentData); | |
| 469 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | |
| 470 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) { | |
| 471 if (child.handlePointer(event, x: x-child.parentData.x, y: y-child.paren tData.y)) | |
| 472 return true; | |
| 473 break; | |
| 474 } | |
| 475 child = child.parentData.previousSibling; | |
| 476 } | |
| 477 return super.handlePointer(event, x: x, y: y); | |
| 478 } | |
| 479 | |
| 464 double width; | 480 double width; |
| 465 double height; | 481 double height; |
| 466 } | 482 } |
| 467 | 483 |
| 468 class BoxDecoration { | 484 class BoxDecoration { |
| 469 const BoxDecoration({ | 485 const BoxDecoration({ |
| 470 this.backgroundColor | 486 this.backgroundColor |
| 471 }); | 487 }); |
| 472 | 488 |
| 473 final int backgroundColor; | 489 final int backgroundColor; |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 assert(child.parentData is BlockParentData); | 691 assert(child.parentData is BlockParentData); |
| 676 child.parentData.x = _padding.left; | 692 child.parentData.x = _padding.left; |
| 677 child.parentData.y = y; | 693 child.parentData.y = y; |
| 678 y += child.height; | 694 y += child.height; |
| 679 child = child.parentData.nextSibling; | 695 child = child.parentData.nextSibling; |
| 680 } | 696 } |
| 681 height = clamp(min: _minHeight, value: y + _padding.bottom, max: _maxHeight) ; | 697 height = clamp(min: _minHeight, value: y + _padding.bottom, max: _maxHeight) ; |
| 682 layoutDone(); | 698 layoutDone(); |
| 683 } | 699 } |
| 684 | 700 |
| 685 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { | |
| 686 // the x, y parameters have the top left of the node's box as the origin | |
| 687 RenderBox child = _lastChild; | |
| 688 while (child != null) { | |
| 689 assert(child.parentData is BlockParentData); | |
| 690 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | |
| 691 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) { | |
| 692 if (child.handlePointer(event, x: x-child.parentData.x, y: y-child.paren tData.y)) | |
| 693 return true; | |
| 694 break; | |
| 695 } | |
| 696 child = child.parentData.previousSibling; | |
| 697 } | |
| 698 return super.handlePointer(event, x: x, y: y); | |
| 699 } | |
| 700 | |
| 701 void paint(RenderNodeDisplayList canvas) { | 701 void paint(RenderNodeDisplayList canvas) { |
| 702 super.paint(canvas); | 702 super.paint(canvas); |
| 703 RenderBox child = _firstChild; | 703 RenderBox child = _firstChild; |
| 704 while (child != null) { | 704 while (child != null) { |
| 705 assert(child.parentData is BlockParentData); | 705 assert(child.parentData is BlockParentData); |
| 706 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 706 canvas.paintChild(child, child.parentData.x, child.parentData.y); |
| 707 child = child.parentData.nextSibling; | 707 child = child.parentData.nextSibling; |
| 708 } | 708 } |
| 709 } | 709 } |
| 710 | 710 |
| 711 } | 711 } |
| 712 | 712 |
| 713 class FlexBoxParentData extends BoxParentData { | 713 // FLEXBOX LAYOUT MANAGER |
| 714 | |
| 715 class FlexBoxParentData extends BoxParentData with ContainerParentDataMixin<Rend erBox> { | |
| 714 int flex; | 716 int flex; |
| 715 void merge(FlexBoxParentData other) { | 717 void merge(FlexBoxParentData other) { |
| 716 if (other.flex != null) | 718 if (other.flex != null) |
| 717 flex = other.flex; | 719 flex = other.flex; |
| 718 super.merge(other); | 720 super.merge(other); |
| 719 } | 721 } |
| 720 } | 722 } |
| 721 | 723 |
| 722 enum FlexDirection { Row, Column } | 724 enum FlexDirection { Horizontal, Vertical } |
| 723 | 725 |
| 724 // TODO(ianh): FlexBox | 726 class RenderFlex extends RenderDecoratedBox with ContainerRenderNodeMixin<Render Box, FlexBoxParentData> { |
| 727 // lays out RenderBox children using flexible layout | |
| 725 | 728 |
| 729 RenderFlex({ | |
| 730 BoxDecoration decoration, | |
| 731 FlexDirection direction: FlexDirection.Horizontal | |
| 732 }) : super(decoration), _direction = direction; | |
| 733 | |
| 734 FlexDirection _direction; | |
| 735 FlexDirection get direction => _direction; | |
| 736 void set direction (FlexDirection value) { | |
| 737 if (_direction != value) { | |
| 738 _direction = value; | |
| 739 markNeedsLayout(); | |
| 740 } | |
| 741 } | |
| 742 | |
| 743 void setParentData(RenderBox child) { | |
| 744 if (child.parentData is! FlexBoxParentData) | |
| 745 child.parentData = new FlexBoxParentData(); | |
| 746 } | |
| 747 | |
| 748 BoxConstraints _constraints; // value cached from parent for relayout call | |
| 749 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | |
| 750 if (relayoutSubtreeRoot != null) | |
| 751 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | |
| 752 relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRo ot; | |
| 753 _constraints = constraints; | |
| 754 width = clamp(min: _constraints.minWidth, max: _constraints.maxWidth); | |
|
Hixie
2015/05/22 20:32:16
width = _constraints.constrainWidth(0.0);
jackson
2015/05/23 00:21:04
Acknowledged.
| |
| 755 height = clamp(min: _constraints.minHeight, max: _constraints.maxHeight); | |
| 756 assert(height < double.INFINITY); | |
| 757 assert(width < double.INFINITY); | |
| 758 internalLayout(relayoutSubtreeRoot); | |
| 759 } | |
| 760 | |
| 761 void relayout() { | |
| 762 internalLayout(this); | |
| 763 } | |
| 764 | |
| 765 int _getFlex(RenderBox child) { | |
| 766 assert(child.parentData is FlexBoxParentData); | |
| 767 return (child.parentData.flex != null ? child.parentData.flex : 0); | |
| 768 } | |
| 769 | |
| 770 void internalLayout(RenderNode relayoutSubtreeRoot) { | |
| 771 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths | |
| 772 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space | |
| 773 int numFlexibleChildren = 0; | |
| 774 int totalFlex = 0; | |
| 775 assert(_constraints != null); | |
| 776 double freeSpace = (_direction == FlexDirection.Horizontal) ? _constraints.m axWidth : _constraints.maxHeight; | |
| 777 RenderBox child = _firstChild; | |
| 778 while (child != null) { | |
| 779 int flex = _getFlex(child); | |
| 780 if (flex > 0) { | |
| 781 numFlexibleChildren++; | |
| 782 totalFlex += child.parentData.flex; | |
| 783 } else { | |
| 784 BoxConstraints constraints = new BoxConstraints(maxHeight: _constraints. maxHeight, | |
| 785 maxWidth: _constraints.m axWidth); | |
| 786 child.layout(constraints, | |
| 787 relayoutSubtreeRoot: relayoutSubtreeRoot); | |
| 788 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch ild.height; | |
| 789 } | |
| 790 child = child.parentData.nextSibling; | |
| 791 } | |
| 792 | |
| 793 // Steps 4-5. Distribute remaining space to flexible children. | |
| 794 double spacePerFlex = freeSpace / totalFlex; | |
|
Hixie
2015/05/22 20:32:16
check what happens when totalFlex is 0.0 and eithe
jackson
2015/05/23 00:21:04
Acknowledged.
| |
| 795 double usedSpace = 0.0; | |
| 796 child = _firstChild; | |
| 797 while (child != null) { | |
| 798 int flex = _getFlex(child); | |
| 799 if (flex > 0) { | |
| 800 double spaceForChild = spacePerFlex * flex; | |
| 801 BoxConstraints constraints; | |
| 802 switch (_direction) { | |
| 803 case FlexDirection.Horizontal: | |
| 804 constraints = new BoxConstraints(maxHeight: _constraints.maxHeight, | |
| 805 minWidth: spaceForChild, | |
| 806 maxWidth: spaceForChild); | |
| 807 break; | |
| 808 case FlexDirection.Vertical: | |
| 809 constraints = new BoxConstraints(minHeight: spaceForChild, | |
| 810 maxHeight: spaceForChild, | |
| 811 maxWidth: _constraints.maxWidth); | |
| 812 break; | |
| 813 } | |
| 814 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); | |
| 815 } | |
| 816 | |
| 817 // For now, center the flex items in the cross direction | |
| 818 switch (_direction) { | |
| 819 case FlexDirection.Horizontal: | |
| 820 child.parentData.x = usedSpace; | |
| 821 usedSpace += child.width; | |
| 822 child.parentData.y = height / 2 - child.height / 2; | |
| 823 break; | |
| 824 case FlexDirection.Vertical: | |
| 825 child.parentData.y = usedSpace; | |
| 826 usedSpace += child.height; | |
| 827 child.parentData.x = width / 2 - child.width / 2; | |
| 828 break; | |
| 829 } | |
| 830 child = child.parentData.nextSibling; | |
| 831 } | |
| 832 layoutDone(); | |
| 833 } | |
| 834 | |
| 835 void paint(RenderNodeDisplayList canvas) { | |
| 836 super.paint(canvas); | |
| 837 RenderBox child = _firstChild; | |
|
Hixie
2015/05/22 20:32:16
maybe do the same as for handlePointer() (with a h
jackson
2015/05/23 00:21:04
Acknowledged.
| |
| 838 while (child != null) { | |
| 839 assert(child.parentData is FlexBoxParentData); | |
| 840 canvas.paintChild(child, child.parentData.x, child.parentData.y); | |
| 841 child = child.parentData.nextSibling; | |
| 842 } | |
| 843 } | |
| 844 } | |
| 726 | 845 |
| 727 // SCAFFOLD LAYOUT MANAGER | 846 // SCAFFOLD LAYOUT MANAGER |
| 728 | 847 |
| 729 // a sample special-purpose layout manager | 848 // a sample special-purpose layout manager |
| 730 | 849 |
| 731 class ScaffoldBox extends RenderBox { | 850 class ScaffoldBox extends RenderBox { |
| 732 | 851 |
| 733 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { | 852 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { |
| 734 assert(body != null); | 853 assert(body != null); |
| 735 } | 854 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 791 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parentDa ta as BoxParentData).y); | 910 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parentDa ta as BoxParentData).y); |
| 792 if (statusbar != null) | 911 if (statusbar != null) |
| 793 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s tatusbar.parentData as BoxParentData).y); | 912 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s tatusbar.parentData as BoxParentData).y); |
| 794 if (toolbar != null) | 913 if (toolbar != null) |
| 795 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb ar.parentData as BoxParentData).y); | 914 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb ar.parentData as BoxParentData).y); |
| 796 if (drawer != null) | 915 if (drawer != null) |
| 797 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer. parentData as BoxParentData).y); | 916 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer. parentData as BoxParentData).y); |
| 798 } | 917 } |
| 799 | 918 |
| 800 } | 919 } |
| OLD | NEW |