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 |