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 |