| 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); |
| 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 // HIT TESTING | 191 // HIT TESTING |
| 192 | 192 |
| 193 void handlePointer(sky.PointerEvent event) { | 193 void handlePointer(sky.PointerEvent event) { |
| 194 // override this if you have a client, to hand it to the client | 194 // override this if you have a client, to hand it to the client |
| 195 // override this if you want to do anything with the pointer event | 195 // override this if you want to do anything with the pointer event |
| 196 } | 196 } |
| 197 | 197 |
| 198 // RenderNode subclasses are expected to have a method like the | 198 // RenderNode subclasses are expected to have a method like the |
| 199 // following (with the signature being whatever passes for coordinates | 199 // following (with the signature being whatever passes for coordinates |
| 200 // for this particular class): | 200 // for this particular class): |
| 201 // bool hitTest(HitTestResult result, { double x, double y }) { | 201 // bool hitTest(HitTestResult result, { sky.Point position }) { |
| 202 // // If (x,y) is not inside this node, then return false. (You | 202 // // If (x,y) is not inside this node, then return false. (You |
| 203 // // can assume that the given coordinate is inside your | 203 // // can assume that the given coordinate is inside your |
| 204 // // dimensions. You only need to check this if you're an | 204 // // dimensions. You only need to check this if you're an |
| 205 // // irregular shape, e.g. if you have a hole.) | 205 // // irregular shape, e.g. if you have a hole.) |
| 206 // // Otherwise: | 206 // // Otherwise: |
| 207 // // For each child that intersects x,y, in z-order starting from the top, | 207 // // For each child that intersects x,y, in z-order starting from the top, |
| 208 // // call hitTest() for that child, passing it /result/, and the coordinate
s | 208 // // call hitTest() for that child, passing it /result/, and the coordinate
s |
| 209 // // converted to the child's coordinate origin, and stop at the first chil
d | 209 // // converted to the child's coordinate origin, and stop at the first chil
d |
| 210 // // that returns true. | 210 // // that returns true. |
| 211 // // Then, add yourself to /result/, and return true. | 211 // // Then, add yourself to /result/, and return true. |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 final double maxHeight; | 438 final double maxHeight; |
| 439 | 439 |
| 440 double constrainWidth(double width) { | 440 double constrainWidth(double width) { |
| 441 return clamp(min: minWidth, max: maxWidth, value: width); | 441 return clamp(min: minWidth, max: maxWidth, value: width); |
| 442 } | 442 } |
| 443 | 443 |
| 444 double constrainHeight(double height) { | 444 double constrainHeight(double height) { |
| 445 return clamp(min: minHeight, max: maxHeight, value: height); | 445 return clamp(min: minHeight, max: maxHeight, value: height); |
| 446 } | 446 } |
| 447 | 447 |
| 448 sky.Size constrain(sky.Size size) { |
| 449 return new sky.Size(constrainWidth(size.width), constrainHeight(size.height)
); |
| 450 } |
| 451 |
| 448 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI
NITY; | 452 bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFI
NITY; |
| 449 } | 453 } |
| 450 | 454 |
| 455 // TODO(abarth): Replace with sky.Size. |
| 451 class BoxDimensions { | 456 class BoxDimensions { |
| 452 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); | 457 const BoxDimensions({ this.width: 0.0, this.height: 0.0 }); |
| 453 | 458 |
| 454 BoxDimensions.withConstraints( | 459 BoxDimensions.withConstraints( |
| 455 BoxConstraints constraints, | 460 BoxConstraints constraints, |
| 456 { double width: 0.0, double height: 0.0 } | 461 { double width: 0.0, double height: 0.0 } |
| 457 ) : width = constraints.constrainWidth(width), | 462 ) : width = constraints.constrainWidth(width), |
| 458 height = constraints.constrainHeight(height); | 463 height = constraints.constrainHeight(height); |
| 459 | 464 |
| 460 final double width; | 465 final double width; |
| 461 final double height; | 466 final double height; |
| 462 } | 467 } |
| 463 | 468 |
| 464 class BoxParentData extends ParentData { | 469 class BoxParentData extends ParentData { |
| 465 double x = 0.0; | 470 sky.Point position = new sky.Point(0.0, 0.0); |
| 466 double y = 0.0; | |
| 467 } | 471 } |
| 468 | 472 |
| 469 abstract class RenderBox extends RenderNode { | 473 abstract class RenderBox extends RenderNode { |
| 470 | 474 |
| 471 void setParentData(RenderNode child) { | 475 void setParentData(RenderNode child) { |
| 472 if (child.parentData is! BoxParentData) | 476 if (child.parentData is! BoxParentData) |
| 473 child.parentData = new BoxParentData(); | 477 child.parentData = new BoxParentData(); |
| 474 } | 478 } |
| 475 | 479 |
| 476 // override this to report what dimensions you would have if you | 480 // override this to report what dimensions you would have if you |
| 477 // were laid out with the given constraints this can walk the tree | 481 // were laid out with the given constraints this can walk the tree |
| 478 // if it must, but it should be as cheap as possible; just get the | 482 // if it must, but it should be as cheap as possible; just get the |
| 479 // dimensions and nothing else (e.g. don't calculate hypothetical | 483 // dimensions and nothing else (e.g. don't calculate hypothetical |
| 480 // child positions if they're not needed to determine dimensions) | 484 // child positions if they're not needed to determine dimensions) |
| 481 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { | 485 BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| 482 return new BoxDimensions.withConstraints(constraints); | 486 return new BoxDimensions.withConstraints(constraints); |
| 483 } | 487 } |
| 484 | 488 |
| 485 BoxConstraints get constraints => super.constraints as BoxConstraints; | 489 BoxConstraints get constraints => super.constraints as BoxConstraints; |
| 486 void performResize() { | 490 void performResize() { |
| 487 // default behaviour for subclasses that have sizedByParent = true | 491 // default behaviour for subclasses that have sizedByParent = true |
| 488 width = constraints.constrainWidth(0.0); | 492 size = constraints.constrain(new sky.Size(0.0, 0.0)); |
| 489 height = constraints.constrainHeight(0.0); | 493 assert(size.height < double.INFINITY); |
| 490 assert(height < double.INFINITY); | 494 assert(size.width < double.INFINITY); |
| 491 assert(width < double.INFINITY); | |
| 492 } | 495 } |
| 493 void performLayout() { | 496 void performLayout() { |
| 494 // descendants have to either override performLayout() to set both | 497 // descendants have to either override performLayout() to set both |
| 495 // width and height and lay out children, or, set sizedByParent to | 498 // width and height and lay out children, or, set sizedByParent to |
| 496 // true so that performResize()'s logic above does its thing. | 499 // true so that performResize()'s logic above does its thing. |
| 497 assert(sizedByParent); | 500 assert(sizedByParent); |
| 498 } | 501 } |
| 499 | 502 |
| 500 bool hitTest(HitTestResult result, { double x, double y }) { | 503 bool hitTest(HitTestResult result, { sky.Point position }) { |
| 501 hitTestChildren(result, x: x, y: y); | 504 hitTestChildren(result, position: position); |
| 502 result.add(this); | 505 result.add(this); |
| 503 return true; | 506 return true; |
| 504 } | 507 } |
| 505 void hitTestChildren(HitTestResult result, { double x, double y }) { } | 508 void hitTestChildren(HitTestResult result, { sky.Point position }) { } |
| 506 | 509 |
| 507 double width; | 510 sky.Size size = new sky.Size(0.0, 0.0); |
| 508 double height; | |
| 509 } | 511 } |
| 510 | 512 |
| 511 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { | 513 class RenderPadding extends RenderBox with RenderNodeWithChildMixin<RenderBox> { |
| 512 | 514 |
| 513 RenderPadding(EdgeDims padding, RenderBox child) { | 515 RenderPadding(EdgeDims padding, RenderBox child) { |
| 514 assert(padding != null); | 516 assert(padding != null); |
| 515 this.padding = padding; | 517 this.padding = padding; |
| 516 this.child = child; | 518 this.child = child; |
| 517 } | 519 } |
| 518 | 520 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 531 constraints = constraints.deflate(padding); | 533 constraints = constraints.deflate(padding); |
| 532 if (child == null) | 534 if (child == null) |
| 533 return super.getIntrinsicDimensions(constraints); | 535 return super.getIntrinsicDimensions(constraints); |
| 534 return child.getIntrinsicDimensions(constraints); | 536 return child.getIntrinsicDimensions(constraints); |
| 535 } | 537 } |
| 536 | 538 |
| 537 void performLayout() { | 539 void performLayout() { |
| 538 assert(padding != null); | 540 assert(padding != null); |
| 539 BoxConstraints innerConstraints = constraints.deflate(padding); | 541 BoxConstraints innerConstraints = constraints.deflate(padding); |
| 540 if (child == null) { | 542 if (child == null) { |
| 541 width = innerConstraints.constrainWidth(padding.left + padding.right); | 543 size = innerConstraints.constrain( |
| 542 height = innerConstraints.constrainHeight(padding.top + padding.bottom); | 544 new sky.Size(padding.left + padding.right, padding.top + padding.botto
m)); |
| 543 return; | 545 return; |
| 544 } | 546 } |
| 545 child.layout(innerConstraints, parentUsesSize: true); | 547 child.layout(innerConstraints, parentUsesSize: true); |
| 546 assert(child.parentData is BoxParentData); | 548 assert(child.parentData is BoxParentData); |
| 547 child.parentData.x = padding.left; | 549 child.parentData.position = new sky.Point(padding.left, padding.top); |
| 548 child.parentData.y = padding.top; | 550 size = constraints.constrain(new sky.Size(padding.left + child.size.width +
padding.right, |
| 549 width = constraints.constrainWidth(padding.left + child.width + padding.righ
t); | 551 padding.top + child.size.height +
padding.bottom)); |
| 550 height = constraints.constrainHeight(padding.top + child.height + padding.bo
ttom); | |
| 551 } | 552 } |
| 552 | 553 |
| 553 void paint(RenderNodeDisplayList canvas) { | 554 void paint(RenderNodeDisplayList canvas) { |
| 554 if (child != null) | 555 if (child != null) |
| 555 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 556 canvas.paintChild(child, child.parentData.position); |
| 556 } | 557 } |
| 557 | 558 |
| 558 void hitTestChildren(HitTestResult result, { double x, double y }) { | 559 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 559 if (child != null) { | 560 if (child != null) { |
| 560 assert(child.parentData is BoxParentData); | 561 assert(child.parentData is BoxParentData); |
| 561 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 562 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi
on, child.size); |
| 562 (y >= child.parentData.y) && (y < child.parentData.y + child.height)) | 563 if (childRect.contains(position)) { |
| 563 child.hitTest(result, x: x+child.parentData.x, y: y+child.parentData.y); | 564 child.hitTest(result, position: new sky.Point(position.x - child.parentD
ata.position.x, |
| 565 position.y - child.parentD
ata.position.y)); |
| 566 } |
| 564 } | 567 } |
| 565 } | 568 } |
| 566 | 569 |
| 567 } | 570 } |
| 568 | 571 |
| 569 // This must be immutable, because we won't notice when it changes | 572 // This must be immutable, because we won't notice when it changes |
| 570 class BoxDecoration { | 573 class BoxDecoration { |
| 571 const BoxDecoration({ | 574 const BoxDecoration({ |
| 572 this.backgroundColor | 575 this.backgroundColor |
| 573 }); | 576 }); |
| 574 | 577 |
| 575 final int backgroundColor; | 578 final int backgroundColor; |
| 576 } | 579 } |
| 577 | 580 |
| 578 class RenderDecoratedBox extends RenderBox { | 581 class RenderDecoratedBox extends RenderBox { |
| 579 | 582 |
| 580 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; | 583 RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; |
| 581 | 584 |
| 582 BoxDecoration _decoration; | 585 BoxDecoration _decoration; |
| 583 BoxDecoration get decoration => _decoration; | 586 BoxDecoration get decoration => _decoration; |
| 584 void set decoration (BoxDecoration value) { | 587 void set decoration (BoxDecoration value) { |
| 585 if (value == _decoration) | 588 if (value == _decoration) |
| 586 return; | 589 return; |
| 587 _decoration = value; | 590 _decoration = value; |
| 588 markNeedsPaint(); | 591 markNeedsPaint(); |
| 589 } | 592 } |
| 590 | 593 |
| 591 void paint(RenderNodeDisplayList canvas) { | 594 void paint(RenderNodeDisplayList canvas) { |
| 592 assert(width != null); | 595 assert(size.width != null); |
| 593 assert(height != null); | 596 assert(size.height != null); |
| 594 | 597 |
| 595 if (_decoration == null) | 598 if (_decoration == null) |
| 596 return; | 599 return; |
| 597 | 600 |
| 598 if (_decoration.backgroundColor != null) { | 601 if (_decoration.backgroundColor != null) { |
| 599 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 602 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
| 600 canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint); | 603 canvas.drawRect(new sky.Rect.fromLTRB(0.0, 0.0, size.width, size.height),
paint); |
| 601 } | 604 } |
| 602 } | 605 } |
| 603 | 606 |
| 604 } | 607 } |
| 605 | 608 |
| 606 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM
ixin<RenderBox> { | 609 class RenderDecoratedCircle extends RenderDecoratedBox with RenderNodeWithChildM
ixin<RenderBox> { |
| 607 RenderDecoratedCircle({ | 610 RenderDecoratedCircle({ |
| 608 BoxDecoration decoration, | 611 BoxDecoration decoration, |
| 609 RenderBox child | 612 RenderBox child |
| 610 }) : super(decoration) { | 613 }) : super(decoration) { |
| 611 this.child = child; | 614 this.child = child; |
| 612 } | 615 } |
| 613 | 616 |
| 614 void paint(RenderNodeDisplayList canvas) { | 617 void paint(RenderNodeDisplayList canvas) { |
| 615 assert(width != null); | 618 assert(size.width != null); |
| 616 assert(height != null); | 619 assert(size.height != null); |
| 617 | 620 |
| 618 if (_decoration == null) | 621 if (_decoration == null) |
| 619 return; | 622 return; |
| 620 | 623 |
| 621 if (_decoration.backgroundColor != null) { | 624 if (_decoration.backgroundColor != null) { |
| 622 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; | 625 sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; |
| 623 canvas.drawCircle(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint)
; | 626 canvas.drawCircle(0.0, 0.0, (size.width + size.height) / 2, paint); |
| 624 } | 627 } |
| 625 } | 628 } |
| 626 } | 629 } |
| 627 | 630 |
| 628 | 631 |
| 629 // RENDER VIEW LAYOUT MANAGER | 632 // RENDER VIEW LAYOUT MANAGER |
| 630 | 633 |
| 631 class ViewConstraints { | 634 class ViewConstraints { |
| 632 | 635 |
| 633 const ViewConstraints({ | 636 const ViewConstraints({ |
| 634 this.width: 0.0, this.height: 0.0, this.orientation: null | 637 this.width: 0.0, this.height: 0.0, this.orientation: null |
| 635 }); | 638 }); |
| 636 | 639 |
| 637 final double width; | 640 final double width; |
| 638 final double height; | 641 final double height; |
| 639 final int orientation; | 642 final int orientation; |
| 640 | 643 |
| 641 } | 644 } |
| 642 | 645 |
| 643 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { | 646 class RenderView extends RenderNode with RenderNodeWithChildMixin<RenderBox> { |
| 644 | 647 |
| 645 RenderView({ | 648 RenderView({ |
| 646 RenderBox child, | 649 RenderBox child, |
| 647 this.timeForRotation: const Duration(microseconds: 83333) | 650 this.timeForRotation: const Duration(microseconds: 83333) |
| 648 }) { | 651 }) { |
| 649 this.child = child; | 652 this.child = child; |
| 650 } | 653 } |
| 651 | 654 |
| 652 double _width; | 655 sky.Size _size = new sky.Size(0.0, 0.0); |
| 653 double get width => _width; | 656 double get width => _size.width; |
| 654 double _height; | 657 double get height => _size.height; |
| 655 double get height => _height; | |
| 656 | 658 |
| 657 int _orientation; // 0..3 | 659 int _orientation; // 0..3 |
| 658 int get orientation => _orientation; | 660 int get orientation => _orientation; |
| 659 Duration timeForRotation; | 661 Duration timeForRotation; |
| 660 | 662 |
| 661 ViewConstraints get constraints => super.constraints as ViewConstraints; | 663 ViewConstraints get constraints => super.constraints as ViewConstraints; |
| 662 bool get sizedByParent => true; | 664 bool get sizedByParent => true; |
| 663 void performResize() { | 665 void performResize() { |
| 664 if (constraints.orientation != _orientation) { | 666 if (constraints.orientation != _orientation) { |
| 665 if (_orientation != null && child != null) | 667 if (_orientation != null && child != null) |
| 666 child.rotate(oldAngle: _orientation, newAngle: constraints.orientation,
time: timeForRotation); | 668 child.rotate(oldAngle: _orientation, newAngle: constraints.orientation,
time: timeForRotation); |
| 667 _orientation = constraints.orientation; | 669 _orientation = constraints.orientation; |
| 668 } | 670 } |
| 669 _width = constraints.width; | 671 _size = new sky.Size(constraints.width, constraints.height); |
| 670 _height = constraints.height; | 672 assert(_size.height < double.INFINITY); |
| 671 assert(height < double.INFINITY); | 673 assert(_size.width < double.INFINITY); |
| 672 assert(width < double.INFINITY); | |
| 673 } | 674 } |
| 674 void performLayout() { | 675 void performLayout() { |
| 675 if (child != null) { | 676 if (child != null) { |
| 676 child.layout(new BoxConstraints.tight(width: width, height: height)); | 677 child.layout(new BoxConstraints.tight(width: width, height: height)); |
| 677 assert(child.width == width); | 678 assert(child.size.width == width); |
| 678 assert(child.height == height); | 679 assert(child.size.height == height); |
| 679 } | 680 } |
| 680 } | 681 } |
| 681 | 682 |
| 682 void rotate({ int oldAngle, int newAngle, Duration time }) { | 683 void rotate({ int oldAngle, int newAngle, Duration time }) { |
| 683 assert(false); // nobody tells the screen to rotate, the whole rotate() danc
e is started from our performResize() | 684 assert(false); // nobody tells the screen to rotate, the whole rotate() danc
e is started from our performResize() |
| 684 } | 685 } |
| 685 | 686 |
| 686 bool hitTest(HitTestResult result, { double x, double y }) { | 687 bool hitTest(HitTestResult result, { sky.Point position }) { |
| 687 if (child != null && x >= 0.0 && x < child.width && y >= 0.0 && y < child.he
ight) | 688 if (child != null) { |
| 688 child.hitTest(result, x: x, y: y); | 689 sky.Rect childRect = new sky.Rect.fromPointAndSize(new sky.Point(0.0, 0.0)
, child.size); |
| 690 if (childRect.contains(position)) |
| 691 child.hitTest(result, position: position); |
| 692 } |
| 689 result.add(this); | 693 result.add(this); |
| 690 return true; | 694 return true; |
| 691 } | 695 } |
| 692 | 696 |
| 693 void paint(RenderNodeDisplayList canvas) { | 697 void paint(RenderNodeDisplayList canvas) { |
| 694 if (child != null) | 698 if (child != null) |
| 695 canvas.paintChild(child, 0.0, 0.0); | 699 canvas.paintChild(child, new sky.Point(0.0, 0.0)); |
| 696 } | 700 } |
| 697 | 701 |
| 698 void paintFrame() { | 702 void paintFrame() { |
| 699 RenderNode._debugDoingPaint = true; | 703 RenderNode._debugDoingPaint = true; |
| 700 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); | 704 var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); |
| 701 paint(canvas); | 705 paint(canvas); |
| 702 sky.view.picture = canvas.endRecording(); | 706 sky.view.picture = canvas.endRecording(); |
| 703 RenderNode._debugDoingPaint = false; | 707 RenderNode._debugDoingPaint = false; |
| 704 } | 708 } |
| 705 | 709 |
| 706 } | 710 } |
| 707 | 711 |
| 708 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS | 712 // DEFAULT BEHAVIORS FOR RENDERBOX CONTAINERS |
| 709 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend
erNodeMixin<ChildType, ParentDataType> { | 713 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend
erNodeMixin<ChildType, ParentDataType> { |
| 710 | 714 |
| 711 void defaultHitTestChildren(HitTestResult result, { double x, double y }) { | 715 void defaultHitTestChildren(HitTestResult result, { sky.Point position }) { |
| 712 // the x, y parameters have the top left of the node's box as the origin | 716 // the x, y parameters have the top left of the node's box as the origin |
| 713 ChildType child = lastChild; | 717 ChildType child = lastChild; |
| 714 while (child != null) { | 718 while (child != null) { |
| 715 assert(child.parentData is BoxParentData); | 719 assert(child.parentData is BoxParentData); |
| 716 if ((x >= child.parentData.x) && (x < child.parentData.x + child.width) && | 720 sky.Rect childRect = new sky.Rect.fromPointAndSize(child.parentData.positi
on, child.size); |
| 717 (y >= child.parentData.y) && (y < child.parentData.y + child.height))
{ | 721 if (childRect.contains(position)) { |
| 718 if (child.hitTest(result, x: x-child.parentData.x, y: y-child.parentData
.y)) | 722 if (child.hitTest(result, position: new sky.Point(position.x - child.par
entData.position.x, |
| 723 position.y - child.par
entData.position.y))) |
| 719 break; | 724 break; |
| 720 } | 725 } |
| 721 child = child.parentData.previousSibling; | 726 child = child.parentData.previousSibling; |
| 722 } | 727 } |
| 723 } | 728 } |
| 724 | 729 |
| 725 void defaultPaint(RenderNodeDisplayList canvas) { | 730 void defaultPaint(RenderNodeDisplayList canvas) { |
| 726 RenderBox child = firstChild; | 731 RenderBox child = firstChild; |
| 727 while (child != null) { | 732 while (child != null) { |
| 728 assert(child.parentData is BoxParentData); | 733 assert(child.parentData is BoxParentData); |
| 729 canvas.paintChild(child, child.parentData.x, child.parentData.y); | 734 canvas.paintChild(child, child.parentData.position); |
| 730 child = child.parentData.nextSibling; | 735 child = child.parentData.nextSibling; |
| 731 } | 736 } |
| 732 } | 737 } |
| 733 } | 738 } |
| 734 | 739 |
| 735 // BLOCK LAYOUT MANAGER | 740 // BLOCK LAYOUT MANAGER |
| 736 | 741 |
| 737 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render
Box> { } | 742 class BlockParentData extends BoxParentData with ContainerParentDataMixin<Render
Box> { } |
| 738 | 743 |
| 739 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
rBox, BlockParentData>, | 744 class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<Rende
rBox, BlockParentData>, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 769 assert(child.parentData is BlockParentData); | 774 assert(child.parentData is BlockParentData); |
| 770 child = child.parentData.nextSibling; | 775 child = child.parentData.nextSibling; |
| 771 } | 776 } |
| 772 | 777 |
| 773 return new BoxDimensions(width: outerWidth, | 778 return new BoxDimensions(width: outerWidth, |
| 774 height: constraints.constrainHeight(outerHeight)); | 779 height: constraints.constrainHeight(outerHeight)); |
| 775 } | 780 } |
| 776 | 781 |
| 777 void performLayout() { | 782 void performLayout() { |
| 778 assert(constraints is BoxConstraints); | 783 assert(constraints is BoxConstraints); |
| 779 width = constraints.constrainWidth(constraints.maxWidth); | 784 size.width = constraints.constrainWidth(constraints.maxWidth); |
| 780 assert(width < double.INFINITY); | 785 assert(size.width < double.INFINITY); |
| 781 double y = 0.0; | 786 double y = 0.0; |
| 782 double innerWidth = width; | 787 double innerWidth = size.width; |
| 783 RenderBox child = firstChild; | 788 RenderBox child = firstChild; |
| 784 while (child != null) { | 789 while (child != null) { |
| 785 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), parentUsesSize: true); | 790 child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth
), parentUsesSize: true); |
| 786 assert(child.parentData is BlockParentData); | 791 assert(child.parentData is BlockParentData); |
| 787 child.parentData.x = 0.0; | 792 child.parentData.position = new sky.Point(0.0, y); |
| 788 child.parentData.y = y; | 793 y += child.size.height; |
| 789 y += child.height; | |
| 790 child = child.parentData.nextSibling; | 794 child = child.parentData.nextSibling; |
| 791 } | 795 } |
| 792 height = constraints.constrainHeight(y); | 796 size.height = constraints.constrainHeight(y); |
| 793 } | 797 } |
| 794 | 798 |
| 795 void hitTestChildren(HitTestResult result, { double x, double y }) { | 799 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 796 defaultHitTestChildren(result, x: x, y: y); | 800 defaultHitTestChildren(result, position: position); |
| 797 } | 801 } |
| 798 | 802 |
| 799 void paint(RenderNodeDisplayList canvas) { | 803 void paint(RenderNodeDisplayList canvas) { |
| 800 super.paint(canvas); | 804 super.paint(canvas); |
| 801 defaultPaint(canvas); | 805 defaultPaint(canvas); |
| 802 } | 806 } |
| 803 | 807 |
| 804 } | 808 } |
| 805 | 809 |
| 806 // FLEXBOX LAYOUT MANAGER | 810 // FLEXBOX LAYOUT MANAGER |
| (...skipping 27 matching lines...) Expand all Loading... |
| 834 } | 838 } |
| 835 } | 839 } |
| 836 | 840 |
| 837 void setParentData(RenderBox child) { | 841 void setParentData(RenderBox child) { |
| 838 if (child.parentData is! FlexBoxParentData) | 842 if (child.parentData is! FlexBoxParentData) |
| 839 child.parentData = new FlexBoxParentData(); | 843 child.parentData = new FlexBoxParentData(); |
| 840 } | 844 } |
| 841 | 845 |
| 842 bool get sizedByParent => true; | 846 bool get sizedByParent => true; |
| 843 void performResize() { | 847 void performResize() { |
| 844 width = _constraints.constrainWidth(_constraints.maxWidth); | 848 size = _constraints.constrain(new sky.Size(_constraints.maxWidth, _constrain
ts.maxHeight)); |
| 845 height = _constraints.constrainHeight(_constraints.maxHeight); | 849 assert(size.height < double.INFINITY); |
| 846 assert(height < double.INFINITY); | 850 assert(size.width < double.INFINITY); |
| 847 assert(width < double.INFINITY); | |
| 848 } | 851 } |
| 849 | 852 |
| 850 int _getFlex(RenderBox child) { | 853 int _getFlex(RenderBox child) { |
| 851 assert(child.parentData is FlexBoxParentData); | 854 assert(child.parentData is FlexBoxParentData); |
| 852 return child.parentData.flex != null ? child.parentData.flex : 0; | 855 return child.parentData.flex != null ? child.parentData.flex : 0; |
| 853 } | 856 } |
| 854 | 857 |
| 855 void performLayout() { | 858 void performLayout() { |
| 856 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib
le Lengths | 859 // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexib
le Lengths |
| 857 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f
ree space | 860 // Steps 1-3. Determine used flex factor, size inflexible items, calculate f
ree space |
| 858 int totalFlex = 0; | 861 int totalFlex = 0; |
| 859 assert(constraints != null); | 862 assert(constraints != null); |
| 860 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma
xWidth : constraints.maxHeight; | 863 double freeSpace = (_direction == FlexDirection.Horizontal) ? constraints.ma
xWidth : constraints.maxHeight; |
| 861 RenderBox child = firstChild; | 864 RenderBox child = firstChild; |
| 862 while (child != null) { | 865 while (child != null) { |
| 863 int flex = _getFlex(child); | 866 int flex = _getFlex(child); |
| 864 if (flex > 0) { | 867 if (flex > 0) { |
| 865 totalFlex += child.parentData.flex; | 868 totalFlex += child.parentData.flex; |
| 866 } else { | 869 } else { |
| 867 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai
nts.maxHeight, | 870 BoxConstraints innerConstraints = new BoxConstraints(maxHeight: constrai
nts.maxHeight, |
| 868 maxWidth: constrain
ts.maxWidth); | 871 maxWidth: constrain
ts.maxWidth); |
| 869 child.layout(innerConstraints, parentUsesSize: true); | 872 child.layout(innerConstraints, parentUsesSize: true); |
| 870 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.width : ch
ild.height; | 873 freeSpace -= (_direction == FlexDirection.Horizontal) ? child.size.width
: child.size.height; |
| 871 } | 874 } |
| 872 child = child.parentData.nextSibling; | 875 child = child.parentData.nextSibling; |
| 873 } | 876 } |
| 874 | 877 |
| 875 // Steps 4-5. Distribute remaining space to flexible children. | 878 // Steps 4-5. Distribute remaining space to flexible children. |
| 876 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; | 879 double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0; |
| 877 double usedSpace = 0.0; | 880 double usedSpace = 0.0; |
| 878 child = firstChild; | 881 child = firstChild; |
| 879 while (child != null) { | 882 while (child != null) { |
| 880 int flex = _getFlex(child); | 883 int flex = _getFlex(child); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 892 maxHeight: spaceForChild, | 895 maxHeight: spaceForChild, |
| 893 maxWidth: constraints.maxWidth
); | 896 maxWidth: constraints.maxWidth
); |
| 894 break; | 897 break; |
| 895 } | 898 } |
| 896 child.layout(innerConstraints, parentUsesSize: true); | 899 child.layout(innerConstraints, parentUsesSize: true); |
| 897 } | 900 } |
| 898 | 901 |
| 899 // For now, center the flex items in the cross direction | 902 // For now, center the flex items in the cross direction |
| 900 switch (_direction) { | 903 switch (_direction) { |
| 901 case FlexDirection.Horizontal: | 904 case FlexDirection.Horizontal: |
| 902 child.parentData.x = usedSpace; | 905 child.parentData.position = new sky.Point(usedSpace, size.height / 2.0
- child.size.height / 2.0); |
| 903 usedSpace += child.width; | 906 usedSpace += child.size.width; |
| 904 child.parentData.y = height / 2.0 - child.height / 2.0; | |
| 905 break; | 907 break; |
| 906 case FlexDirection.Vertical: | 908 case FlexDirection.Vertical: |
| 907 child.parentData.y = usedSpace; | 909 child.parentData.position = new sky.Point(size.width / 2.0 - child.siz
e.width / 2.0, usedSpace); |
| 908 usedSpace += child.height; | 910 usedSpace += child.size.height; |
| 909 child.parentData.x = width / 2.0 - child.width / 2.0; | |
| 910 break; | 911 break; |
| 911 } | 912 } |
| 912 child = child.parentData.nextSibling; | 913 child = child.parentData.nextSibling; |
| 913 } | 914 } |
| 914 } | 915 } |
| 915 | 916 |
| 916 void hitTestChildren(HitTestResult result, { double x, double y }) { | 917 void hitTestChildren(HitTestResult result, { sky.Point position }) { |
| 917 defaultHitTestChildren(result, x: x, y: y); | 918 defaultHitTestChildren(result, position: position); |
| 918 } | 919 } |
| 919 | 920 |
| 920 void paint(RenderNodeDisplayList canvas) { | 921 void paint(RenderNodeDisplayList canvas) { |
| 921 super.paint(canvas); | 922 super.paint(canvas); |
| 922 defaultPaint(canvas); | 923 defaultPaint(canvas); |
| 923 } | 924 } |
| 924 } | 925 } |
| OLD | NEW |