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 }) { | |
| 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 { Row, Column } |
| 723 | 725 |
| 724 // TODO(ianh): FlexBox | 726 class RenderFlex extends RenderDecoratedBox with ContainerRenderNodeMixin<Render Box, FlexBoxParentData> { |
| 727 // lays out RenderBox children in a vertical stack using flexible layout | |
| 728 // uses the maximum width and height provided by the parent | |
| 725 | 729 |
| 730 RenderFlex({ | |
| 731 BoxDecoration decoration, | |
| 732 FlexDirection direction: FlexDirection.Row | |
| 733 }) : super(decoration), _direction = direction; | |
| 734 | |
| 735 FlexDirection _direction; | |
| 736 FlexDirection get direction => _direction; | |
| 737 void set direction (FlexDirection value) { | |
| 738 _direction = value; | |
|
abarth-chromium
2015/05/22 06:26:23
Should early out when the newDirection and _direct
jackson
2015/05/22 20:06:54
Acknowledged.
| |
| 739 relayout(); | |
|
abarth-chromium
2015/05/22 06:26:23
Should markForLayout instead of calling relayout.
jackson
2015/05/22 20:06:55
Acknowledged.
| |
| 740 } | |
| 741 | |
| 742 void setParentData(RenderBox child) { | |
| 743 if (child.parentData is! FlexBoxParentData) | |
| 744 child.parentData = new FlexBoxParentData(); | |
| 745 } | |
| 746 | |
| 747 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | |
| 748 width = clamp(min: constraints.minWidth, max: constraints.maxWidth); | |
| 749 height = clamp(min: constraints.minHeight, max: constraints.maxHeight); | |
| 750 relayout(); | |
| 751 } | |
| 752 | |
| 753 void relayout() { | |
| 754 internalLayout(this); | |
| 755 } | |
|
abarth-chromium
2015/05/22 06:26:22
layout and relayout don't quite seem right. You m
jackson
2015/05/22 20:06:54
Acknowledged.
| |
| 756 | |
| 757 int getFlex(RenderBox child) { | |
|
abarth-chromium
2015/05/22 06:26:22
s/getFlex/_getFlex/ to mark the function as privat
jackson
2015/05/22 20:06:54
Acknowledged.
| |
| 758 assert(child.parentData is FlexBoxParentData); | |
| 759 return (child.parentData.flex != null ? child.parentData.flex : 0); | |
| 760 } | |
| 761 | |
| 762 void internalLayout(RenderNode relayoutSubtreeRoot) { | |
| 763 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths | |
| 764 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space | |
| 765 int numFlexibleChildren = 0; | |
| 766 int totalFlex = 0; | |
| 767 double freeSpace = (_direction == FlexDirection.Row) ? width : height; | |
| 768 RenderBox child = _firstChild; | |
| 769 while (child != null) { | |
| 770 int flex = getFlex(child); | |
| 771 if (flex > 0) { | |
| 772 numFlexibleChildren++; | |
| 773 totalFlex += child.parentData.flex; | |
| 774 } else { | |
| 775 child.layout(new BoxConstraints(minWidth: width, maxWidth: width), | |
|
abarth-chromium
2015/05/22 06:26:23
Should the BoxConstraints depend on the flex direc
jackson
2015/05/22 20:06:54
Acknowledged.
| |
| 776 relayoutSubtreeRoot: relayoutSubtreeRoot); | |
|
abarth-chromium
2015/05/22 06:26:23
I think you're supposed to call getIntrinsicDimens
jackson
2015/05/22 20:06:54
I talked to hixie, he said that it's ok to call la
| |
| 777 freeSpace -= (_direction == FlexDirection.Row) ? child.width : child.hei ght; | |
| 778 } | |
| 779 child = child.parentData.nextSibling; | |
| 780 } | |
| 781 | |
| 782 // Steps 4-5. Distribute remaining space to flexible children. | |
| 783 double spacePerFlex = freeSpace / totalFlex; | |
| 784 double usedSpace = 0.0; | |
| 785 child = _firstChild; | |
| 786 while (child != null) { | |
| 787 int flex = getFlex(child); | |
| 788 if (flex > 0) { | |
| 789 double spaceForChild = spacePerFlex * flex; | |
| 790 BoxConstraints constraints; | |
| 791 switch (_direction) { | |
| 792 case FlexDirection.Row: | |
|
ojan
2015/05/22 06:48:11
Not directly related to this patch, but I noticed
jackson
2015/05/22 20:06:55
Acknowledged.
| |
| 793 constraints = new BoxConstraints(maxHeight: height, maxWidth: spaceF orChild); | |
|
abarth-chromium
2015/05/22 06:26:22
Do we want to set the minWidth to spaceForChild as
jackson
2015/05/22 20:06:54
Acknowledged.
| |
| 794 break; | |
| 795 case FlexDirection.Column: | |
| 796 constraints = new BoxConstraints(maxHeight: spaceForChild, maxWidth: width); | |
|
abarth-chromium
2015/05/22 06:26:22
Same here for minHeight?
jackson
2015/05/22 20:06:55
Acknowledged.
| |
| 797 break; | |
| 798 } | |
| 799 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); | |
| 800 } | |
| 801 | |
| 802 switch (_direction) { | |
| 803 // always center the item | |
| 804 case FlexDirection.Row: | |
| 805 child.parentData.x = usedSpace; | |
| 806 usedSpace += child.width; | |
| 807 child.parentData.y = height / 2 - child.height / 2; | |
| 808 break; | |
| 809 case FlexDirection.Column: | |
| 810 child.parentData.y = usedSpace; | |
| 811 usedSpace += child.height; | |
| 812 child.parentData.x = width / 2 - child.width / 2; | |
| 813 break; | |
| 814 } | |
| 815 child = child.parentData.nextSibling; | |
| 816 } | |
| 817 layoutDone(); | |
| 818 } | |
| 819 | |
| 820 void paint(RenderNodeDisplayList canvas) { | |
| 821 super.paint(canvas); | |
| 822 RenderBox child = _firstChild; | |
| 823 while (child != null) { | |
| 824 assert(child.parentData is FlexBoxParentData); | |
| 825 canvas.paintChild(child, child.parentData.x, child.parentData.y); | |
| 826 child = child.parentData.nextSibling; | |
| 827 } | |
| 828 } | |
| 829 } | |
| 726 | 830 |
| 727 // SCAFFOLD LAYOUT MANAGER | 831 // SCAFFOLD LAYOUT MANAGER |
| 728 | 832 |
| 729 // a sample special-purpose layout manager | 833 // a sample special-purpose layout manager |
| 730 | 834 |
| 731 class ScaffoldBox extends RenderBox { | 835 class ScaffoldBox extends RenderBox { |
| 732 | 836 |
| 733 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { | 837 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { |
| 734 assert(body != null); | 838 assert(body != null); |
| 735 } | 839 } |
| (...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); | 895 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parentDa ta as BoxParentData).y); |
| 792 if (statusbar != null) | 896 if (statusbar != null) |
| 793 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s tatusbar.parentData as BoxParentData).y); | 897 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s tatusbar.parentData as BoxParentData).y); |
| 794 if (toolbar != null) | 898 if (toolbar != null) |
| 795 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb ar.parentData as BoxParentData).y); | 899 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb ar.parentData as BoxParentData).y); |
| 796 if (drawer != null) | 900 if (drawer != null) |
| 797 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer. parentData as BoxParentData).y); | 901 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer. parentData as BoxParentData).y); |
| 798 } | 902 } |
| 799 | 903 |
| 800 } | 904 } |
| OLD | NEW |