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 |