Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'node.dart'; | 5 import 'node.dart'; |
| 6 import 'dart:sky' as sky; | 6 import 'dart:sky' as sky; |
| 7 | 7 |
| 8 // ABSTRACT LAYOUT | 8 // ABSTRACT LAYOUT |
| 9 | 9 |
| 10 class ParentData { | 10 class ParentData { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 if (value > max) | 28 if (value > max) |
| 29 value = max; | 29 value = max; |
| 30 if (value < min) | 30 if (value < min) |
| 31 value = min; | 31 value = min; |
| 32 return value; | 32 return value; |
| 33 } | 33 } |
| 34 | 34 |
| 35 class RenderNodeDisplayList extends sky.PictureRecorder { | 35 class RenderNodeDisplayList extends sky.PictureRecorder { |
| 36 RenderNodeDisplayList(double width, double height) : super(width, height); | 36 RenderNodeDisplayList(double width, double height) : super(width, height); |
| 37 void paintChild(RenderNode child, double x, double y) { | 37 void paintChild(RenderNode child, sky.Point position) { |
| 38 save(); | 38 save(); |
| 39 translate(x, y); | 39 translate(position.x, position.y); |
|
Hixie
2015/05/28 18:45:22
translate() should take a Point. :-)
| |
| 40 child.paint(this); | 40 child.paint(this); |
| 41 restore(); | 41 restore(); |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 | 44 |
| 45 abstract class RenderNode extends AbstractNode { | 45 abstract class RenderNode extends AbstractNode { |
| 46 | 46 |
| 47 // LAYOUT | 47 // LAYOUT |
| 48 | 48 |
| 49 // parentData is only for use by the RenderNode that actually lays this | 49 // parentData is only for use by the RenderNode that actually lays this |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 // HIT TESTING | 232 // HIT TESTING |
| 233 | 233 |
| 234 void handlePointer(sky.PointerEvent event) { | 234 void handlePointer(sky.PointerEvent event) { |
| 235 // override this if you have a client, to hand it to the client | 235 // override this if you have a client, to hand it to the client |
| 236 // override this if you want to do anything with the pointer event | 236 // override this if you want to do anything with the pointer event |
| 237 } | 237 } |
| 238 | 238 |
| 239 // RenderNode subclasses are expected to have a method like the | 239 // RenderNode subclasses are expected to have a method like the |
| 240 // following (with the signature being whatever passes for coordinates | 240 // following (with the signature being whatever passes for coordinates |
| 241 // for this particular class): | 241 // for this particular class): |
| 242 // bool hitTest(HitTestResult result, { double x, double y }) { | 242 // bool hitTest(HitTestResult result, { sky.Point position }) { |
| 243 // // If (x,y) is not inside this node, then return false. (You | 243 // // If (x,y) is not inside this node, then return false. (You |
| 244 // // can assume that the given coordinate is inside your | 244 // // can assume that the given coordinate is inside your |
| 245 // // dimensions. You only need to check this if you're an | 245 // // dimensions. You only need to check this if you're an |
| 246 // // irregular shape, e.g. if you have a hole.) | 246 // // irregular shape, e.g. if you have a hole.) |
| 247 // // Otherwise: | 247 // // Otherwise: |
| 248 // // For each child that intersects x,y, in z-order starting from the top, | 248 // // For each child that intersects x,y, in z-order starting from the top, |
| 249 // // call hitTest() for that child, passing it /result/, and the coordinate s | 249 // // call hitTest() for that child, passing it /result/, and the coordinate s |
| 250 // // converted to the child's coordinate origin, and stop at the first chil d | 250 // // converted to the child's coordinate origin, and stop at the first chil d |
| 251 // // that returns true. | 251 // // that returns true. |
| 252 // // Then, add yourself to /result/, and return true. | 252 // // Then, add yourself to /result/, and return true. |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 final double maxHeight; | 479 final double maxHeight; |
| 480 | 480 |
| 481 double constrainWidth(double width) { | 481 double constrainWidth(double width) { |
| 482 return clamp(min: minWidth, max: maxWidth, value: width); | 482 return clamp(min: minWidth, max: maxWidth, value: width); |
| 483 } | 483 } |
| 484 | 484 |
| 485 double constrainHeight(double height) { | 485 double constrainHeight(double height) { |
| 486 return clamp(min: minHeight, max: maxHeight, value: height); | 486 return clamp(min: minHeight, max: maxHeight, value: height); |
| 487 } | 487 } |
| 488 | 488 |
| 489 sky.Size constrain(sky.Size size) { | |
| 490 return new sky.Size(constrainWidth(size.width), constrainHeight(size.height) ); | |
| 491 } | |
| 492 | |
| 489 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI NITY; | 493 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI NITY; |
| 490 } | 494 } |
| 491 | 495 |
| 496 // TODO(abarth): Replace with sky.Size. | |
| 492 class BoxDimensions { | 497 class BoxDimensions { |
| 493 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); | 498 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); |
| 494 | 499 |
| 495 BoxDimensions.withConstraints( | 500 BoxDimensions.withConstraints( |
| 496 BoxConstraints constraints, | 501 BoxConstraints constraints, |
| 497 { double width: 0.0, double height: 0.0 } | 502 { double width: 0.0, double height: 0.0 } |
| 498 ) : width = constraints.constrainWidth(width), | 503 ) : width = constraints.constrainWidth(width), |
| 499 height = constraints.constrainHeight(height); | 504 height = constraints.constrainHeight(height); |
| 500 | 505 |
| 501 final double width; | 506 final double width; |
| 502 final double height; | 507 final double height; |
| 503 } | 508 } |
| 504 | 509 |
| 505 class BoxParentData extends ParentData { | 510 class BoxParentData extends ParentData { |
| 506 double x = 0.0; | 511 sky.Point position = new sky.Point(); |
|
Hixie
2015/05/28 18:45:22
It's tempting to suggest that BoxParentData should
| |
| 507 double y = 0.0; | |
| 508 } | 512 } |
| 509 | 513 |
| 510 abstract class RenderBox extends RenderNode { | 514 abstract class RenderBox extends RenderNode { |
| 511 | 515 |
| 512 void setParentData(RenderNode child) { | 516 void setParentData(RenderNode child) { |
| 513 if (child.parentData is! BoxParentData) | 517 if (child.parentData is! BoxParentData) |
| 514 child.parentData = new BoxParentData(); | 518 child.parentData = new BoxParentData(); |
| 515 } | 519 } |
| 516 | 520 |
| 517 // override this to report what dimensions you would have if you | 521 // override this to report what dimensions you would have if you |
| 518 // were laid out with the given constraints this can walk the tree | 522 // were laid out with the given constraints this can walk the tree |
| 519 // if it must, but it should be as cheap as possible; just get the | 523 // if it must, but it should be as cheap as possible; just get the |
| 520 // dimensions and nothing else (e.g. don't calculate hypothetical | 524 // dimensions and nothing else (e.g. don't calculate hypothetical |
| 521 // child positions if they're not needed to determine dimensions) | 525 // child positions if they're not needed to determine dimensions) |
| 522 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 526 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 523 return new BoxDimensions.withConstraints(constraints); | 527 return new BoxDimensions.withConstraints(constraints); |
| 524 } | 528 } |
| 525 | 529 |
| 526 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 530 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 527 width = constraints.constrainWidth(0.0); | 531 size = constraints.constrain(new sky.Size()); |
| 528 height = constraints.constrainHeight(0.0); | |
| 529 layoutDone(); | 532 layoutDone(); |
| 530 } | 533 } |
| 531 | 534 |
| 532 bool hitTest(HitTestResult result, { double x, double y }) { | 535 bool hitTest(HitTestResult result, { sky.Point position }) { |
| 533 hitTestChildren(result, x: x, y: y); | 536 hitTestChildren(result, position: position); |
| 534 result.add(this); | 537 result.add(this); |
| 535 return true; | 538 return true; |
| 536 } | 539 } |
| 537 void hitTestChildren(HitTestResult result, { double x, double y }) { } | 540 void hitTestChildren(HitTestResult result, { sky.Point position }) { } |
| 538 | 541 |
| 539 double width; | 542 sky.Size size = new sky.Size(); |
| 540 double height; | |
| 541 } | 543 } |
| 542 | 544 |
| 543 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { | 545 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { |
| 544 | 546 |
| 545 RenderPadding(EdgeDims padding, RenderBox child) { | 547 RenderPadding(EdgeDims padding, RenderBox child) { |
| 546 assert(padding != null); | 548 assert(padding != null); |
| 547 this.padding = padding; | 549 this.padding = padding; |
| 548 this.child = child; | 550 this.child = child; |
| 549 } | 551 } |
| 550 | 552 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 563 constraints = constraints.deflate(padding); | 565 constraints = constraints.deflate(padding); |
| 564 if (child == null) | 566 if (child == null) |
| 565 return super.getIntrinsicDimensions(constraints); | 567 return super.getIntrinsicDimensions(constraints); |
| 566 return child.getIntrinsicDimensions(constraints); | 568 return child.getIntrinsicDimensions(constraints); |
| 567 } | 569 } |
| 568 | 570 |
| 569 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 571 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 570 assert(padding != null); | 572 assert(padding != null); |
| 571 constraints = constraints.deflate(padding); | 573 constraints = constraints.deflate(padding); |
| 572 if (child == null) { | 574 if (child == null) { |
| 573 width = constraints.constrainWidth(padding.left + padding.right); | 575 size = constraints.constrain(new sky.Size(padding.left + padding.right, |
| 574 height = constraints.constrainHeight(padding.top + padding.bottom); | 576 padding.top + padding.bottom)); |
| 575 return; | 577 return; |
| 576 } | 578 } |
| 577 if (relayoutSubtreeRoot != null) | 579 if (relayoutSubtreeRoot != null) |
| 578 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | 580 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); |
| 579 else | 581 else |
| 580 relayoutSubtreeRoot = this; | 582 relayoutSubtreeRoot = this; |
| 581 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); | 583 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 582 assert(child.parentData is BoxParentData); | 584 assert(child.parentData is BoxParentData); |
| 583 child.parentData.x = padding.left; | 585 child.parentData.position = new sky.Point(padding.left, padding.top); |
| 584 child.parentData.y = padding.top; | 586 size = constraints.constrain(new sky.Size(padding.left + child.size.width + padding.right, |
| 585 width = constraints.constrainWidth(padding.left + child.width + padding.righ t); | 587 padding.top + child.size.height + padding.bottom)); |
| 586 height = constraints.constrainHeight(padding.top + child.height + padding.bo ttom); | |
| 587 } | 588 } |
| 588 | 589 |
| 589 void paint(RenderNodeDisplayList canvas) { | 590 void paint(RenderNodeDisplayList canvas) { |
| 590 if (child != null) | 591 if (child != null) |
| 591 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 592 canvas.paintChild(child, child.parentData.position); |
| 592 } | 593 } |
| 593 | 594 |
| 594 void hitTestChildren(HitTestResult result, { double x, double y }) { | 595 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 595 if (child != null) { | 596 if (child != null) { |
| 596 assert(child.parentData is BoxParentData); | 597 assert(child.parentData is BoxParentData); |
| 597 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 598 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi on, child.size); |
| 598 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) | 599 if (childRect.contains(position)) { |
| 599 child.hitTest(result, x: x+child.parentData.x, y: y+child.parentData.y); | 600 child.hitTest(result, position: new sky.Point(position.x - child.parentD ata.position.x, |
| 601 position.y - child.parentD ata.position.y)); | |
| 602 } | |
| 600 } | 603 } |
| 601 } | 604 } |
| 602 | 605 |
| 603 } | 606 } |
| 604 | 607 |
| 605 // This must be immutable, because we won't notice when it changes | 608 // This must be immutable, because we won't notice when it changes |
| 606 class BoxDecoration { | 609 class BoxDecoration { |
| 607 const BoxDecoration({ | 610 const BoxDecoration({ |
| 608 this.backgroundColor | 611 this.backgroundColor |
| 609 }); | 612 }); |
| 610 | 613 |
| 611 final int backgroundColor; | 614 final int backgroundColor; |
| 612 } | 615 } |
| 613 | 616 |
| 614 class RenderDecoratedBox extends RenderBox { | 617 class RenderDecoratedBox extends RenderBox { |
| 615 | 618 |
| 616 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; | 619 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; |
| 617 | 620 |
| 618 BoxDecoration _decoration; | 621 BoxDecoration _decoration; |
| 619 BoxDecoration get decoration => _decoration; | 622 BoxDecoration get decoration => _decoration; |
| 620 void set decoration (BoxDecoration value) { | 623 void set decoration (BoxDecoration value) { |
| 621 if (value == _decoration) | 624 if (value == _decoration) |
| 622 return; | 625 return; |
| 623 _decoration = value; | 626 _decoration = value; |
| 624 markNeedsPaint(); | 627 markNeedsPaint(); |
| 625 } | 628 } |
| 626 | 629 |
| 627 void paint(RenderNodeDisplayList canvas) { | 630 void paint(RenderNodeDisplayList canvas) { |
| 628 assert(width != null); | 631 assert(size.width != null); |
| 629 assert(height != null); | 632 assert(size.height != null); |
| 630 | 633 |
| 631 if (_decoration == null) | 634 if (_decoration == null) |
| 632 return; | 635 return; |
| 633 | 636 |
| 634 if (_decoration.backgroundColor != null) { | 637 if (_decoration.backgroundColor != null) { |
| 635 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 638 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
| 636 canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint); | 639 canvas.drawRect(new sky.Rect.fromLTRB(0.0, 0.0, size.width, size.height), paint); |
| 637 } | 640 } |
| 638 } | 641 } |
| 639 | 642 |
| 640 } | 643 } |
| 641 | 644 |
| 642 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM ixin<RenderBox> { | 645 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM ixin<RenderBox> { |
| 643 RenderDecoratedCircle({ | 646 RenderDecoratedCircle({ |
| 644 BoxDecoration decoration, | 647 BoxDecoration decoration, |
| 645 RenderBox child | 648 RenderBox child |
| 646 }) : super(decoration) { | 649 }) : super(decoration) { |
| 647 this.child = child; | 650 this.child = child; |
| 648 } | 651 } |
| 649 | 652 |
| 650 void paint(RenderNodeDisplayList canvas) { | 653 void paint(RenderNodeDisplayList canvas) { |
| 651 assert(width != null); | 654 assert(size.width != null); |
| 652 assert(height != null); | 655 assert(size.height != null); |
| 653 | 656 |
| 654 if (_decoration == null) | 657 if (_decoration == null) |
| 655 return; | 658 return; |
| 656 | 659 |
| 657 if (_decoration.backgroundColor != null) { | 660 if (_decoration.backgroundColor != null) { |
| 658 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 661 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
| 659 canvas.drawCircle(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint) ; | 662 canvas.drawCircle(0.0, 0.0, (size.width + size.height) / 2, paint); |
| 660 } | 663 } |
| 661 } | 664 } |
| 662 } | 665 } |
| 663 | 666 |
| 664 | 667 |
| 665 // RENDER VIEW LAYOUT MANAGER | 668 // RENDER VIEW LAYOUT MANAGER |
| 666 | 669 |
| 667 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { | 670 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { |
| 668 | 671 |
| 669 RenderView({ | 672 RenderView({ |
| 670 RenderBox child, | 673 RenderBox child, |
| 671 this.timeForRotation: const Duration(microseconds: 83333) | 674 this.timeForRotation: const Duration(microseconds: 83333) |
| 672 }) { | 675 }) { |
| 673 this.child = child; | 676 this.child = child; |
| 674 } | 677 } |
| 675 | 678 |
| 676 double _width; | 679 sky.Size _size = new sky.Size(); |
| 677 double get width => _width; | 680 double get width => _size.width; |
| 678 double _height; | 681 double get height => _size.height; |
| 679 double get height => _height; | |
| 680 | 682 |
| 681 int _orientation; // 0..3 | 683 int _orientation; // 0..3 |
| 682 int get orientation => _orientation; | 684 int get orientation => _orientation; |
| 683 Duration timeForRotation; | 685 Duration timeForRotation; |
| 684 | 686 |
| 685 void layout({ | 687 void layout({ |
| 686 double newWidth, | 688 double newWidth, |
| 687 double newHeight, | 689 double newHeight, |
| 688 int newOrientation | 690 int newOrientation |
| 689 }) { | 691 }) { |
| 690 if (newOrientation != orientation) { | 692 if (newOrientation != orientation) { |
| 691 if (orientation != null && child != null) | 693 if (orientation != null && child != null) |
| 692 child.rotate(oldAngle: orientation, newAngle: newOrientation, time: time ForRotation); | 694 child.rotate(oldAngle: orientation, newAngle: newOrientation, time: time ForRotation); |
| 693 _orientation = newOrientation; | 695 _orientation = newOrientation; |
| 694 } | 696 } |
| 695 if ((newWidth != width) || (newHeight != height)) { | 697 if ((newWidth != width) || (newHeight != height)) { |
| 696 _width = newWidth; | 698 _size = new sky.Size(newWidth, newHeight); |
| 697 _height = newHeight; | |
| 698 relayout(); | 699 relayout(); |
| 699 } else { | 700 } else { |
| 700 layoutDone(); | 701 layoutDone(); |
| 701 } | 702 } |
| 702 } | 703 } |
| 703 | 704 |
| 704 void relayout() { | 705 void relayout() { |
| 705 if (child != null) { | 706 if (child != null) { |
| 706 child.layout(new BoxConstraints.tight(width: width, height: height)); | 707 child.layout(new BoxConstraints.tight(width: width, height: height)); |
| 707 assert(child.width == width); | 708 assert(child.size.width == width); |
| 708 assert(child.height == height); | 709 assert(child.size.height == height); |
| 709 } | 710 } |
| 710 layoutDone(); | 711 layoutDone(); |
| 711 } | 712 } |
| 712 | 713 |
| 713 void rotate({ int oldAngle, int newAngle, Duration time }) { | 714 void rotate({ int oldAngle, int newAngle, Duration time }) { |
| 714 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our layout() | 715 assert(false); // nobody tells the screen to rotate, the whole rotate() danc e is started from our layout() |
| 715 } | 716 } |
| 716 | 717 |
| 717 bool hitTest(HitTestResult result, { double x, double y }) { | 718 bool hitTest(HitTestResult result, { sky.Point position }) { |
| 718 if (child != null && x >= 0.0 && x < child.width && y >= 0.0 && y < child.he ight) | 719 if (child != null) { |
| 719 child.hitTest(result, x: x, y: y); | 720 sky.Rect childRect = new sky.Rect.fromPointAndSize(new sky.Point(), child. size); |
| 721 if (childRect.contains(position)) | |
| 722 child.hitTest(result, position: position); | |
| 723 } | |
| 720 result.add(this); | 724 result.add(this); |
| 721 return true; | 725 return true; |
| 722 } | 726 } |
| 723 | 727 |
| 724 void paint(RenderNodeDisplayList canvas) { | 728 void paint(RenderNodeDisplayList canvas) { |
| 725 if (child != null) | 729 if (child != null) |
| 726 canvas.paintChild(child, 0.0, 0.0); | 730 canvas.paintChild(child, new sky.Point()); |
| 727 } | 731 } |
| 728 | 732 |
| 729 void paintFrame() { | 733 void paintFrame() { |
| 730 RenderNode._debugDoingPaint = true; | 734 RenderNode._debugDoingPaint = true; |
| 731 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); | 735 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); |
| 732 paint(canvas); | 736 paint(canvas); |
| 733 sky.view.picture = canvas.endRecording(); | 737 sky.view.picture = canvas.endRecording(); |
| 734 RenderNode._debugDoingPaint = false; | 738 RenderNode._debugDoingPaint = false; |
| 735 } | 739 } |
| 736 | 740 |
| 737 } | 741 } |
| 738 | 742 |
| 739 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS | 743 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS |
| 740 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend erNodeMixin<ChildType, ParentDataType> { | 744 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend erNodeMixin<ChildType, ParentDataType> { |
| 741 | 745 |
| 742 void defaultHitTestChildren(HitTestResult result, { double x, double y }) { | 746 void defaultHitTestChildren(HitTestResult result, { sky.Point position }) { |
| 743 // the x, y parameters have the top left of the node's box as the origin | 747 // the x, y parameters have the top left of the node's box as the origin |
| 744 ChildType child = lastChild; | 748 ChildType child = lastChild; |
| 745 while (child != null) { | 749 while (child != null) { |
| 746 assert(child.parentData is BoxParentData); | 750 assert(child.parentData is BoxParentData); |
| 747 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 751 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi on, child.size); |
| 748 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) { | 752 if (childRect.contains(position)) { |
| 749 if (child.hitTest(result, x: x-child.parentData.x, y: y-child.parentData .y)) | 753 if (child.hitTest(result, position: new sky.Point(position.x - child.par entData.position.x, |
| 754 position.y - child.par entData.position.y))) | |
| 750 break; | 755 break; |
| 751 } | 756 } |
| 752 child = child.parentData.previousSibling; | 757 child = child.parentData.previousSibling; |
| 753 } | 758 } |
| 754 } | 759 } |
| 755 | 760 |
| 756 void defaultPaint(RenderNodeDisplayList canvas) { | 761 void defaultPaint(RenderNodeDisplayList canvas) { |
| 757 RenderBox child = firstChild; | 762 RenderBox child = firstChild; |
| 758 while (child != null) { | 763 while (child != null) { |
| 759 assert(child.parentData is BoxParentData); | 764 assert(child.parentData is BoxParentData); |
| 760 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 765 canvas.paintChild(child, child.parentData.position); |
| 761 child = child.parentData.nextSibling; | 766 child = child.parentData.nextSibling; |
| 762 } | 767 } |
| 763 } | 768 } |
| 764 } | 769 } |
| 765 | 770 |
| 766 // BLOCK LAYOUT MANAGER | 771 // BLOCK LAYOUT MANAGER |
| 767 | 772 |
| 768 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render Box> { } | 773 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render Box> { } |
| 769 | 774 |
| 770 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende rBox, BlockParentData>, | 775 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende rBox, BlockParentData>, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 return new BoxDimensions(width: outerWidth, | 809 return new BoxDimensions(width: outerWidth, |
| 805 height: constraints.constrainHeight(outerHeight)); | 810 height: constraints.constrainHeight(outerHeight)); |
| 806 } | 811 } |
| 807 | 812 |
| 808 BoxConstraints _constraints; // value cached from parent for relayout call | 813 BoxConstraints _constraints; // value cached from parent for relayout call |
| 809 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 814 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 810 if (relayoutSubtreeRoot != null) | 815 if (relayoutSubtreeRoot != null) |
| 811 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | 816 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); |
| 812 else | 817 else |
| 813 relayoutSubtreeRoot = this; | 818 relayoutSubtreeRoot = this; |
| 814 width = constraints.constrainWidth(constraints.maxWidth); | 819 size.width = constraints.constrainWidth(constraints.maxWidth); |
| 815 assert(width < double.INFINITY); | 820 assert(size.width < double.INFINITY); |
| 816 _constraints = constraints; | 821 _constraints = constraints; |
| 817 internalLayout(relayoutSubtreeRoot); | 822 internalLayout(relayoutSubtreeRoot); |
| 818 } | 823 } |
| 819 | 824 |
| 820 void relayout() { | 825 void relayout() { |
| 821 internalLayout(this); | 826 internalLayout(this); |
| 822 } | 827 } |
| 823 | 828 |
| 824 void internalLayout(RenderNode relayoutSubtreeRoot) { | 829 void internalLayout(RenderNode relayoutSubtreeRoot) { |
| 825 assert(_constraints != null); | 830 assert(_constraints != null); |
| 826 double y = 0.0; | 831 double y = 0.0; |
| 827 double innerWidth = width; | 832 double innerWidth = size.width; |
| 828 RenderBox child = firstChild; | 833 RenderBox child = firstChild; |
| 829 while (child != null) { | 834 while (child != null) { |
| 830 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), | 835 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth ), |
| 831 relayoutSubtreeRoot: relayoutSubtreeRoot); | 836 relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 832 assert(child.parentData is BlockParentData); | 837 assert(child.parentData is BlockParentData); |
| 833 child.parentData.x = 0.0; | 838 child.parentData.position = new sky.Point(0.0, y); |
| 834 child.parentData.y = y; | 839 y += child.size.height; |
| 835 y += child.height; | |
| 836 child = child.parentData.nextSibling; | 840 child = child.parentData.nextSibling; |
| 837 } | 841 } |
| 838 height = _constraints.constrainHeight(y); | 842 size.height = _constraints.constrainHeight(y); |
| 839 layoutDone(); | 843 layoutDone(); |
| 840 } | 844 } |
| 841 | 845 |
| 842 void hitTestChildren(HitTestResult result, { double x, double y }) { | 846 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 843 defaultHitTestChildren(result, x: x, y: y); | 847 defaultHitTestChildren(result, position: position); |
| 844 } | 848 } |
| 845 | 849 |
| 846 void paint(RenderNodeDisplayList canvas) { | 850 void paint(RenderNodeDisplayList canvas) { |
| 847 super.paint(canvas); | 851 super.paint(canvas); |
| 848 defaultPaint(canvas); | 852 defaultPaint(canvas); |
| 849 } | 853 } |
| 850 | 854 |
| 851 } | 855 } |
| 852 | 856 |
| 853 // FLEXBOX LAYOUT MANAGER | 857 // FLEXBOX LAYOUT MANAGER |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 child.parentData = new FlexBoxParentData(); | 890 child.parentData = new FlexBoxParentData(); |
| 887 } | 891 } |
| 888 | 892 |
| 889 BoxConstraints _constraints; // value cached from parent for relayout call | 893 BoxConstraints _constraints; // value cached from parent for relayout call |
| 890 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { | 894 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 891 if (relayoutSubtreeRoot != null) | 895 if (relayoutSubtreeRoot != null) |
| 892 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); | 896 saveRelayoutSubtreeRoot(relayoutSubtreeRoot); |
| 893 else | 897 else |
| 894 relayoutSubtreeRoot = this; | 898 relayoutSubtreeRoot = this; |
| 895 _constraints = constraints; | 899 _constraints = constraints; |
| 896 width = _constraints.constrainWidth(_constraints.maxWidth); | 900 size = _constraints.constrain(new sky.Size(_constraints.maxWidth, _constrain ts.maxHeight)); |
| 897 height = _constraints.constrainHeight(_constraints.maxHeight); | 901 assert(size.width < double.INFINITY); |
| 898 assert(height < double.INFINITY); | 902 assert(size.height < double.INFINITY); |
| 899 assert(width < double.INFINITY); | |
| 900 internalLayout(relayoutSubtreeRoot); | 903 internalLayout(relayoutSubtreeRoot); |
| 901 } | 904 } |
| 902 | 905 |
| 903 void relayout() { | 906 void relayout() { |
| 904 internalLayout(this); | 907 internalLayout(this); |
| 905 } | 908 } |
| 906 | 909 |
| 907 int _getFlex(RenderBox child) { | 910 int _getFlex(RenderBox child) { |
| 908 assert(child.parentData is FlexBoxParentData); | 911 assert(child.parentData is FlexBoxParentData); |
| 909 return child.parentData.flex != null ? child.parentData.flex : 0; | 912 return child.parentData.flex != null ? child.parentData.flex : 0; |
| 910 } | 913 } |
| 911 | 914 |
| 912 void internalLayout(RenderNode relayoutSubtreeRoot) { | 915 void internalLayout(RenderNode relayoutSubtreeRoot) { |
| 913 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths | 916 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib le Lengths |
| 914 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space | 917 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f ree space |
| 915 int totalFlex = 0; | 918 int totalFlex = 0; |
| 916 assert(_constraints != null); | 919 assert(_constraints != null); |
| 917 double freeSpace = (_direction == FlexDirection.Horizontal) ? _constraints.m axWidth : _constraints.maxHeight; | 920 double freeSpace = (_direction == FlexDirection.Horizontal) ? _constraints.m axWidth : _constraints.maxHeight; |
| 918 RenderBox child = firstChild; | 921 RenderBox child = firstChild; |
| 919 while (child != null) { | 922 while (child != null) { |
| 920 int flex = _getFlex(child); | 923 int flex = _getFlex(child); |
| 921 if (flex > 0) { | 924 if (flex > 0) { |
| 922 totalFlex += child.parentData.flex; | 925 totalFlex += child.parentData.flex; |
| 923 } else { | 926 } else { |
| 924 BoxConstraints constraints = new BoxConstraints(maxHeight: _constraints. maxHeight, | 927 BoxConstraints constraints = new BoxConstraints(maxHeight: _constraints. maxHeight, |
| 925 maxWidth: _constraints.m axWidth); | 928 maxWidth: _constraints.m axWidth); |
| 926 child.layout(constraints, | 929 child.layout(constraints, |
| 927 relayoutSubtreeRoot: relayoutSubtreeRoot); | 930 relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 928 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch ild.height; | 931 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.size.width : child.size.height; |
| 929 } | 932 } |
| 930 child = child.parentData.nextSibling; | 933 child = child.parentData.nextSibling; |
| 931 } | 934 } |
| 932 | 935 |
| 933 // Steps 4-5. Distribute remaining space to flexible children. | 936 // Steps 4-5. Distribute remaining space to flexible children. |
| 934 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; | 937 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; |
| 935 double usedSpace = 0.0; | 938 double usedSpace = 0.0; |
| 936 child = firstChild; | 939 child = firstChild; |
| 937 while (child != null) { | 940 while (child != null) { |
| 938 int flex = _getFlex(child); | 941 int flex = _getFlex(child); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 950 maxHeight: spaceForChild, | 953 maxHeight: spaceForChild, |
| 951 maxWidth: _constraints.maxWidth); | 954 maxWidth: _constraints.maxWidth); |
| 952 break; | 955 break; |
| 953 } | 956 } |
| 954 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); | 957 child.layout(constraints, relayoutSubtreeRoot: relayoutSubtreeRoot); |
| 955 } | 958 } |
| 956 | 959 |
| 957 // For now, center the flex items in the cross direction | 960 // For now, center the flex items in the cross direction |
| 958 switch (_direction) { | 961 switch (_direction) { |
| 959 case FlexDirection.Horizontal: | 962 case FlexDirection.Horizontal: |
| 960 child.parentData.x = usedSpace; | 963 child.parentData.position = new sky.Point(usedSpace, size.height / 2 - child.size.height / 2); |
| 961 usedSpace += child.width; | 964 usedSpace += child.size.width; |
| 962 child.parentData.y = height / 2 - child.height / 2; | |
| 963 break; | 965 break; |
| 964 case FlexDirection.Vertical: | 966 case FlexDirection.Vertical: |
| 965 child.parentData.y = usedSpace; | 967 child.parentData.position = new sky.Point(size.width / 2 - child.size. width / 2, usedSpace); |
| 966 usedSpace += child.height; | 968 usedSpace += child.size.height; |
| 967 child.parentData.x = width / 2 - child.width / 2; | |
| 968 break; | 969 break; |
| 969 } | 970 } |
| 970 child = child.parentData.nextSibling; | 971 child = child.parentData.nextSibling; |
| 971 } | 972 } |
| 972 layoutDone(); | 973 layoutDone(); |
| 973 } | 974 } |
| 974 | 975 |
| 975 void hitTestChildren(HitTestResult result, { double x, double y }) { | 976 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 976 defaultHitTestChildren(result, x: x, y: y); | 977 defaultHitTestChildren(result, position: position); |
| 977 } | 978 } |
| 978 | 979 |
| 979 void paint(RenderNodeDisplayList canvas) { | 980 void paint(RenderNodeDisplayList canvas) { |
| 980 super.paint(canvas); | 981 super.paint(canvas); |
| 981 defaultPaint(canvas); | 982 defaultPaint(canvas); |
| 982 } | 983 } |
| 983 } | 984 } |
| OLD | NEW |