| 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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 // GENERIC BOX RENDERING | 394 // GENERIC BOX RENDERING |
| 395 // Anything that has a concept of x, y, width, height is going to derive from th
is | 395 // Anything that has a concept of x, y, width, height is going to derive from th
is |
| 396 | 396 |
| 397 class BoxConstraints { | 397 class BoxConstraints { |
| 398 const BoxConstraints({ | 398 const BoxConstraints({ |
| 399 this.minWidth: 0.0, | 399 this.minWidth: 0.0, |
| 400 this.maxWidth: double.INFINITY, | 400 this.maxWidth: double.INFINITY, |
| 401 this.minHeight: 0.0, | 401 this.minHeight: 0.0, |
| 402 this.maxHeight: double.INFINITY}); | 402 this.maxHeight: double.INFINITY}); |
| 403 | 403 |
| 404 const BoxConstraints.tight({ width: width, height: height }) |
| 405 : minWidth = width, |
| 406 maxWidth = width, |
| 407 minHeight = height, |
| 408 maxHeight = height; |
| 409 |
| 404 final double minWidth; | 410 final double minWidth; |
| 405 final double maxWidth; | 411 final double maxWidth; |
| 406 final double minHeight; | 412 final double minHeight; |
| 407 final double maxHeight; | 413 final double maxHeight; |
| 414 |
| 415 double constrainWidth(double width) { |
| 416 return clamp(min: minWidth, max: maxWidth, value: width); |
| 417 } |
| 418 |
| 419 double constrainHeight(double height) { |
| 420 return clamp(min: minHeight, max: maxHeight, value: height); |
| 421 } |
| 408 } | 422 } |
| 409 | 423 |
| 410 class BoxDimensions { | 424 class BoxDimensions { |
| 411 const BoxDimensions({this.width, this.height}); | 425 const BoxDimensions({this.width, this.height}); |
| 412 | 426 |
| 413 BoxDimensions.withConstraints( | 427 BoxDimensions.withConstraints( |
| 414 BoxConstraints constraints, {double width: 0.0, double height: 0.0}) { | 428 BoxConstraints constraints, {double width: 0.0, double height: 0.0}) { |
| 415 this.width = clamp(min: minWidth, max: maxWidth, value: width); | 429 this.width = constraints.constrainWidth(width); |
| 416 this.height = clamp(min: minHeight, max: maxHeight, value: height); | 430 this.height = constraints.constrainHeight(height); |
| 417 } | 431 } |
| 418 | 432 |
| 419 final double width; | 433 final double width; |
| 420 final double height; | 434 final double height; |
| 421 } | 435 } |
| 422 | 436 |
| 423 class BoxParentData extends ParentData { | 437 class BoxParentData extends ParentData { |
| 424 double x = 0.0; | 438 double x = 0.0; |
| 425 double y = 0.0; | 439 double y = 0.0; |
| 426 } | 440 } |
| 427 | 441 |
| 428 abstract class RenderBox extends RenderNode { | 442 abstract class RenderBox extends RenderNode { |
| 429 | 443 |
| 430 void setParentData(RenderNode child) { | 444 void setParentData(RenderNode child) { |
| 431 if (child.parentData is! BoxParentData) | 445 if (child.parentData is! BoxParentData) |
| 432 child.parentData = new BoxParentData(); | 446 child.parentData = new BoxParentData(); |
| 433 } | 447 } |
| 434 | 448 |
| 435 // override this to report what dimensions you would have if you | 449 // override this to report what dimensions you would have if you |
| 436 // were laid out with the given constraints this can walk the tree | 450 // were laid out with the given constraints this can walk the tree |
| 437 // if it must, but it should be as cheap as possible; just get the | 451 // if it must, but it should be as cheap as possible; just get the |
| 438 // dimensions and nothing else (e.g. don't calculate hypothetical | 452 // dimensions and nothing else (e.g. don't calculate hypothetical |
| 439 // child positions if they're not needed to determine dimensions) | 453 // child positions if they're not needed to determine dimensions) |
| 440 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 454 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 441 return new BoxDimensions.withConstraints(constraints); | 455 return new BoxDimensions.withConstraints(constraints); |
| 442 } | 456 } |
| 443 | 457 |
| 444 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 458 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 445 setWidth(constraints, 0.0); | 459 width = constraints.constrainWidth(0.0); |
| 446 setHeight(constraints, 0.0); | 460 height = constraints.constrainHeight(0.0); |
| 447 layoutDone(); | 461 layoutDone(); |
| 448 } | 462 } |
| 449 | 463 |
| 450 double width; | 464 double width; |
| 451 double height; | 465 double height; |
| 452 | |
| 453 void setWidth(BoxConstraints constraints, double newWidth) { | |
| 454 width = clamp(min: constraints.minWidth, | |
| 455 max: constraints.maxWidth, | |
| 456 value: newWidth); | |
| 457 } | |
| 458 | |
| 459 void setHeight(BoxConstraints constraints, double newHeight) { | |
| 460 height = clamp(min: constraints.minHeight, | |
| 461 max: constraints.maxHeight, | |
| 462 value: newHeight); | |
| 463 } | |
| 464 } | 466 } |
| 465 | 467 |
| 466 class BoxDecoration { | 468 class BoxDecoration { |
| 467 BoxDecoration({ | 469 const BoxDecoration({ |
| 468 this.backgroundColor | 470 this.backgroundColor |
| 469 }); | 471 }); |
| 470 | 472 |
| 471 final int backgroundColor; | 473 final int backgroundColor; |
| 472 } | 474 } |
| 473 | 475 |
| 474 class RenderDecoratedBox extends RenderBox { | 476 class RenderDecoratedBox extends RenderBox { |
| 475 BoxDecoration _decoration; | 477 BoxDecoration _decoration; |
| 476 | 478 |
| 477 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; | 479 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 child.parentData = new BlockParentData(); | 623 child.parentData = new BlockParentData(); |
| 622 } | 624 } |
| 623 | 625 |
| 624 // override this to report what dimensions you would have if you | 626 // override this to report what dimensions you would have if you |
| 625 // were laid out with the given constraints this can walk the tree | 627 // were laid out with the given constraints this can walk the tree |
| 626 // if it must, but it should be as cheap as possible; just get the | 628 // if it must, but it should be as cheap as possible; just get the |
| 627 // dimensions and nothing else (e.g. don't calculate hypothetical | 629 // dimensions and nothing else (e.g. don't calculate hypothetical |
| 628 // child positions if they're not needed to determine dimensions) | 630 // child positions if they're not needed to determine dimensions) |
| 629 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 631 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 630 double outerHeight = _padding.top + _padding.bottom; | 632 double outerHeight = _padding.top + _padding.bottom; |
| 631 // TODO(abarth): Shouldn't this have a value: maxWidth? | 633 double outerWidth = constraints.constrainWidth(constraints.maxWidth); |
| 632 double outerWidth = clamp(min: constraints.minWidth, | 634 assert(outerWidth < double.INFINITY); |
| 633 max: constraints.maxWidth); | |
| 634 double innerWidth = outerWidth - (_padding.left + _padding.right); | 635 double innerWidth = outerWidth - (_padding.left + _padding.right); |
| 635 RenderBox child = _firstChild; | 636 RenderBox child = _firstChild; |
| 636 BoxConstraints constraints = new BoxConstraints(minWidth: innerWidth, | 637 BoxConstraints constraints = new BoxConstraints(minWidth: innerWidth, |
| 637 maxWidth: innerWidth); | 638 maxWidth: innerWidth); |
| 638 while (child != null) { | 639 while (child != null) { |
| 639 outerHeight += child.getIntrinsicDimensions(constraints).height; | 640 outerHeight += child.getIntrinsicDimensions(constraints).height; |
| 640 assert(child.parentData is BlockParentData); | 641 assert(child.parentData is BlockParentData); |
| 641 child = child.parentData.nextSibling; | 642 child = child.parentData.nextSibling; |
| 642 } | 643 } |
| 643 | 644 |
| 644 return new BoxDimensions( | 645 return new BoxDimensions(width: outerWidth, |
| 645 width: outerWidth, | 646 height: constraints.constrainHeight(outerHeight)); |
| 646 height: clamp(min: constraints.minHeight, | |
| 647 max: constraints.maxHeight, | |
| 648 value: outerHeight) | |
| 649 ); | |
| 650 } | 647 } |
| 651 | 648 |
| 652 double _minHeight; // value cached from parent for relayout call | 649 double _minHeight; // value cached from parent for relayout call |
| 653 double _maxHeight; // value cached from parent for relayout call | 650 double _maxHeight; // value cached from parent for relayout call |
| 654 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 651 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 655 if (relayoutSubtreeRoot != null) | 652 if (relayoutSubtreeRoot != null) |
| 656 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | 653 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); |
| 657 relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRo
ot; | 654 relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRo
ot; |
| 658 // TODO(abarth): Shouldn't this be setWidth(constaints, constraints.maxWidth
)? | 655 width = constraints.constrainWidth(constraints.maxWidth); |
| 659 width = clamp(min: constraints.minWidth, max: constraints.maxWidth); | 656 assert(width < double.INFINITY); |
| 660 _minHeight = constraints.minHeight; | 657 _minHeight = constraints.minHeight; |
| 661 _maxHeight = constraints.maxHeight; | 658 _maxHeight = constraints.maxHeight; |
| 662 internalLayout(relayoutSubtreeRoot); | 659 internalLayout(relayoutSubtreeRoot); |
| 663 } | 660 } |
| 664 | 661 |
| 665 void relayout() { | 662 void relayout() { |
| 666 internalLayout(this); | 663 internalLayout(this); |
| 667 } | 664 } |
| 668 | 665 |
| 669 void internalLayout(RenderNode relayoutSubtreeRoot) { | 666 void internalLayout(RenderNode relayoutSubtreeRoot) { |
| 670 assert(_minHeight != null); | 667 assert(_minHeight != null); |
| 671 assert(_maxHeight != null); | 668 assert(_maxHeight != null); |
| 672 double y = _padding.top; | 669 double y = _padding.top; |
| 673 double innerWidth = width - (_padding.left + _padding.right); | 670 double innerWidth = width - (_padding.left + _padding.right); |
| 674 RenderBox child = _firstChild; | 671 RenderBox child = _firstChild; |
| 675 while (child != null) { | 672 while (child != null) { |
| 676 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), | 673 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), |
| 677 relayoutSubtreeRoot: relayoutSubtreeRoot); | 674 relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 678 assert(child.parentData is BlockParentData); | 675 assert(child.parentData is BlockParentData); |
| 679 child.parentData.x = 0.0; // TODO(abarth): Shouldn't this be _padding.left
? | 676 child.parentData.x = _padding.left; |
| 680 child.parentData.y = y; | 677 child.parentData.y = y; |
| 681 y += child.height; | 678 y += child.height; |
| 682 child = child.parentData.nextSibling; | 679 child = child.parentData.nextSibling; |
| 683 } | 680 } |
| 684 height = clamp(min: _minHeight, value: y + _padding.bottom, max: _maxHeight)
; | 681 height = clamp(min: _minHeight, value: y + _padding.bottom, max: _maxHeight)
; |
| 685 layoutDone(); | 682 layoutDone(); |
| 686 } | 683 } |
| 687 | 684 |
| 688 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { | 685 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { |
| 689 // the x, y parameters have the top left of the node's box as the origin | 686 // the x, y parameters have the top left of the node's box as the origin |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { | 733 ScaffoldBox(this.toolbar, this.body, this.statusbar, this.drawer) { |
| 737 assert(body != null); | 734 assert(body != null); |
| 738 } | 735 } |
| 739 | 736 |
| 740 final RenderBox toolbar; | 737 final RenderBox toolbar; |
| 741 final RenderBox body; | 738 final RenderBox body; |
| 742 final RenderBox statusbar; | 739 final RenderBox statusbar; |
| 743 final RenderBox drawer; | 740 final RenderBox drawer; |
| 744 | 741 |
| 745 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 742 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 746 setHeight(constraints, 0.0); | 743 width = constraints.constrainWidth(0.0); |
| 747 setWidth(constraints, 0.0); | 744 height = constraints.constrainHeight(0.0); |
| 748 relayout(); | 745 relayout(); |
| 749 } | 746 } |
| 750 | 747 |
| 751 static const kToolbarHeight = 100.0; | 748 static const kToolbarHeight = 100.0; |
| 752 static const kStatusbarHeight = 50.0; | 749 static const kStatusbarHeight = 50.0; |
| 753 | 750 |
| 754 void relayout() { | 751 void relayout() { |
| 755 double bodyHeight = height; | 752 double bodyHeight = height; |
| 756 if (toolbar != null) { | 753 if (toolbar != null) { |
| 757 toolbar.layout(new BoxConstraints(minWidth: width, maxWidth: width, minHei
ght: kToolbarHeight, maxHeight: kToolbarHeight)); | 754 toolbar.layout(new BoxConstraints.tight(width: width, height: kToolbarHeig
ht)); |
| 758 assert(toolbar.parentData is BoxParentData); | 755 assert(toolbar.parentData is BoxParentData); |
| 759 toolbar.parentData.x = 0.0; | 756 toolbar.parentData.x = 0.0; |
| 760 toolbar.parentData.y = 0.0; | 757 toolbar.parentData.y = 0.0; |
| 761 bodyHeight -= kToolbarHeight; | 758 bodyHeight -= kToolbarHeight; |
| 762 } | 759 } |
| 763 if (statusbar != null) { | 760 if (statusbar != null) { |
| 764 statusbar.layout(new BoxConstraints(minWidth: width, maxWidth: width, minH
eight: kStatusbarHeight, maxHeight: kStatusbarHeight)); | 761 statusbar.layout(new BoxConstraints.tight(width: width, height: kStatusbar
Height)); |
| 765 assert(statusbar.parentData is BoxParentData); | 762 assert(statusbar.parentData is BoxParentData); |
| 766 statusbar.parentData.x = 0.0; | 763 statusbar.parentData.x = 0.0; |
| 767 statusbar.parentData.y = height - kStatusbarHeight; | 764 statusbar.parentData.y = height - kStatusbarHeight; |
| 768 bodyHeight -= kStatusbarHeight; | 765 bodyHeight -= kStatusbarHeight; |
| 769 } | 766 } |
| 770 body.layout(new BoxConstraints(minWidth: width, maxWidth: width, minHeight:
bodyHeight, maxHeight: bodyHeight)); | 767 body.layout(new BoxConstraints.tight(width: width, height: bodyHeight)); |
| 771 if (drawer != null) | 768 if (drawer != null) |
| 772 drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: width, minHeight
: height, maxHeight: height)); | 769 drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: width, minHeight
: height, maxHeight: height)); |
| 773 layoutDone(); | 770 layoutDone(); |
| 774 } | 771 } |
| 775 | 772 |
| 776 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { | 773 bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { |
| 777 if ((drawer != null) && (x < drawer.width)) { | 774 if ((drawer != null) && (x < drawer.width)) { |
| 778 if (drawer.handlePointer(event, x: x, y: y)) | 775 if (drawer.handlePointer(event, x: x, y: y)) |
| 779 return true; | 776 return true; |
| 780 } else if ((toolbar != null) && (y < toolbar.height)) { | 777 } else if ((toolbar != null) && (y < toolbar.height)) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 794 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parentDa
ta as BoxParentData).y); | 791 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parentDa
ta as BoxParentData).y); |
| 795 if (statusbar != null) | 792 if (statusbar != null) |
| 796 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s
tatusbar.parentData as BoxParentData).y); | 793 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s
tatusbar.parentData as BoxParentData).y); |
| 797 if (toolbar != null) | 794 if (toolbar != null) |
| 798 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb
ar.parentData as BoxParentData).y); | 795 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb
ar.parentData as BoxParentData).y); |
| 799 if (drawer != null) | 796 if (drawer != null) |
| 800 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer.
parentData as BoxParentData).y); | 797 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer.
parentData as BoxParentData).y); |
| 801 } | 798 } |
| 802 | 799 |
| 803 } | 800 } |
| OLD | NEW |