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 'dart:math' as math; | 5 import 'dart:math' as math; |
| 6 import 'dart:sky' as sky; | 6 import 'dart:sky' as sky; |
| 7 | 7 |
| 8 import 'package:vector_math/vector_math.dart'; | 8 import 'package:vector_math/vector_math.dart'; |
| 9 | 9 |
| 10 import '../base/debug.dart'; | 10 import '../base/debug.dart'; |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 | 284 |
| 285 // getMaxIntrinsicHeight should return the smallest height beyond which | 285 // getMaxIntrinsicHeight should return the smallest height beyond which |
| 286 // increasing the height never decreases the width. | 286 // increasing the height never decreases the width. |
| 287 // If the layout algorithm used is width-in-height-out, i.e. the height | 287 // If the layout algorithm used is width-in-height-out, i.e. the height |
| 288 // depends on the width and not vice versa, then this will return the same | 288 // depends on the width and not vice versa, then this will return the same |
| 289 // as getMinIntrinsicHeight(). | 289 // as getMinIntrinsicHeight(). |
| 290 double getMaxIntrinsicHeight(BoxConstraints constraints) { | 290 double getMaxIntrinsicHeight(BoxConstraints constraints) { |
| 291 return constraints.constrainHeight(0.0); | 291 return constraints.constrainHeight(0.0); |
| 292 } | 292 } |
| 293 | 293 |
| 294 // getDistanceToBaseline() should return the distance from the | 294 Map<TextBaseline, double> _cachedBaselines; |
| 295 bool _ancestorUsesBaseline = false; | |
| 296 static bool _debugDoingBaseline = false; | |
| 297 static bool _debugSetDoingBaseline(bool value) { | |
| 298 _debugDoingBaseline = value; | |
| 299 return true; | |
| 300 } | |
| 301 // getDistanceToBaseline() returns the distance from the | |
| 295 // y-coordinate of the position of the box to the y-coordinate of | 302 // y-coordinate of the position of the box to the y-coordinate of |
| 296 // the first given baseline in the box's contents. This is used by | 303 // the first given baseline in the box's contents. This is used by |
| 297 // certain layout models to align adjacent boxes on a common | 304 // certain layout models to align adjacent boxes on a common |
| 298 // baseline, regardless of padding, font size differences, etc. If | 305 // baseline, regardless of padding, font size differences, etc. If |
| 299 // there is no baseline, then it should return the distance from the | 306 // there is no baseline, then it returns the distance from the |
| 300 // y-coordinate of the position of the box to the y-coordinate of | 307 // y-coordinate of the position of the box to the y-coordinate of |
| 301 // the bottom of the box, i.e., the height of the box. | 308 // the bottom of the box, i.e., the height of the box. Only call |
| 302 // Only call this after layout has been performed. | 309 // this after layout has been performed. You are only allowed to |
| 310 // call this from the parent of this node, and only during | |
| 311 // that parent's performLayout(). | |
| 303 double getDistanceToBaseline(TextBaseline baseline) { | 312 double getDistanceToBaseline(TextBaseline baseline) { |
| 304 assert(!needsLayout); | 313 assert(!needsLayout); |
| 314 assert(!_debugDoingBaseline); | |
| 315 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer | |
| 316 assert(parent is RenderObject); | |
| 317 assert(parent == RenderObject.debugActiveLayout); | |
| 318 assert(parent.debugDoingThisLayout); | |
| 319 assert(_debugSetDoingBaseline(true)); | |
| 305 double result = getDistanceToActualBaseline(baseline); | 320 double result = getDistanceToActualBaseline(baseline); |
| 321 assert(_debugSetDoingBaseline(false)); | |
| 322 assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer | |
| 306 if (result == null) | 323 if (result == null) |
| 307 return size.height; | 324 return size.height; |
| 308 return result; | 325 return result; |
| 309 } | 326 } |
| 310 // getDistanceToActualBaseline() should return the distance from the | 327 // getDistanceToActualBaseline() must only be called from |
| 311 // y-coordinate of the position of the box to the y-coordinate of | 328 // getDistanceToBaseline() and computeDistanceToActualBaseline(). Do |
| 312 // the first given baseline in the box's contents, if any, or null | 329 // not call it directly from outside those two methods. It just |
| 313 // otherwise. | 330 // calls computeDistanceToActualBaseline() and caches the result. |
| 314 double getDistanceToActualBaseline(TextBaseline baseline) { | 331 double getDistanceToActualBaseline(TextBaseline baseline) { |
| 315 assert(!needsLayout); | 332 assert(_debugDoingBaseline); |
| 333 _ancestorUsesBaseline = true; | |
| 334 if (_cachedBaselines == null) | |
| 335 _cachedBaselines = new Map<TextBaseline, double>(); | |
| 336 _cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline (baseline)); | |
| 337 return _cachedBaselines[baseline]; | |
| 338 } | |
| 339 // computeDistanceToActualBaseline() should return the distance from | |
| 340 // the y-coordinate of the position of the box to the y-coordinate | |
| 341 // of the first given baseline in the box's contents, if any, or | |
| 342 // null otherwise. This is the method that you should override in | |
| 343 // subclasses. This method (computeDistanceToActualBaseline()) | |
| 344 // should not be called directly. Use getDistanceToBaseline() if you | |
| 345 // need to know the baseline of a child from performLayout(). If you | |
| 346 // need the baseline during paint, cache it during performLayout(). | |
| 347 // Use getDistanceToActualBaseline() if you are implementing | |
| 348 // computeDistanceToActualBaseline() and need to defer to a child. | |
| 349 double computeDistanceToActualBaseline(TextBaseline baseline) { | |
| 350 assert(_debugDoingBaseline); | |
| 316 return null; | 351 return null; |
| 317 } | 352 } |
| 318 | 353 |
| 319 BoxConstraints get constraints => super.constraints; | 354 BoxConstraints get constraints => super.constraints; |
| 320 bool debugDoesMeetConstraints() { | 355 bool debugDoesMeetConstraints() { |
| 321 assert(constraints != null); | 356 assert(constraints != null); |
| 322 assert(_size != null); | 357 assert(_size != null); |
| 323 assert(!_size.isInfinite); | 358 assert(!_size.isInfinite); |
| 324 bool result = constraints.contains(_size); | 359 bool result = constraints.contains(_size); |
| 325 if (!result) | 360 if (!result) |
| 326 print("${this.runtimeType} does not meet its constraints. Constraints: $co nstraints, size: $_size"); | 361 print("${this.runtimeType} does not meet its constraints. Constraints: $co nstraints, size: $_size"); |
| 327 return result; | 362 return result; |
| 328 } | 363 } |
| 364 | |
| 365 bool debugAncestorsAlreadyClearedBaselineCache() { | |
| 366 if (!_ancestorUsesBaseline) | |
| 367 return true; // we haven't yet been asked for a baseline even once, so the re's nothing for us to do | |
| 368 RenderBox node = this; | |
|
abarth-chromium
2015/07/01 18:22:59
Is it possible to execute this line of code?
| |
| 369 while (node._ancestorUsesBaseline) { | |
| 370 if (node._cachedBaselines != null && node._cachedBaselines.isNotEmpty) | |
| 371 return false; | |
| 372 assert(node.parent != null); | |
| 373 if (node.parent is! RenderBox) { | |
| 374 assert(node.parent is RenderObject); | |
| 375 break; | |
| 376 } | |
| 377 node = node.parent; | |
| 378 } | |
| 379 if (node is RenderBox) { | |
| 380 assert(!node._ancestorUsesBaseline); | |
| 381 if (node._cachedBaselines != null && node._cachedBaselines.isNotEmpty) | |
| 382 return false; | |
| 383 } | |
| 384 return true; | |
| 385 } | |
| 386 void markNeedsLayout() { | |
| 387 assert(!RenderObject.debugDoingLayout); | |
| 388 assert(!RenderObject.debugDoingPaint); | |
| 389 if (_cachedBaselines != null && _cachedBaselines.isNotEmpty) { | |
| 390 _cachedBaselines.clear(); | |
| 391 if (_ancestorUsesBaseline) { | |
| 392 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer | |
| 393 assert(parent is RenderObject); | |
| 394 parent.markNeedsLayout(); | |
| 395 // Now that they're dirty, we can forget that they used the | |
| 396 // baseline. If they use it again, then we'll set the bit | |
| 397 // again, and if we get dirty again, we'll notify them again. | |
| 398 _ancestorUsesBaseline = false; | |
| 399 assert(parent == this.parent); // TODO(ianh): Remove this once the analy zer is cleverer | |
| 400 } | |
| 401 } else { | |
| 402 assert(debugAncestorsAlreadyClearedBaselineCache()); | |
| 403 } | |
| 404 super.markNeedsLayout(); | |
| 405 } | |
| 329 void performResize() { | 406 void performResize() { |
| 330 // default behaviour for subclasses that have sizedByParent = true | 407 // default behaviour for subclasses that have sizedByParent = true |
| 331 size = constraints.constrain(Size.zero); | 408 size = constraints.constrain(Size.zero); |
| 332 assert(!size.isInfinite); | 409 assert(!size.isInfinite); |
| 333 } | 410 } |
| 334 void performLayout() { | 411 void performLayout() { |
| 335 // descendants have to either override performLayout() to set both | 412 // descendants have to either override performLayout() to set both |
| 336 // width and height and lay out children, or, set sizedByParent to | 413 // width and height and lay out children, or, set sizedByParent to |
| 337 // true so that performResize()'s logic above does its thing. | 414 // true so that performResize()'s logic above does its thing. |
| 338 assert(sizedByParent); | 415 assert(sizedByParent); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 return child.getMinIntrinsicHeight(constraints); | 480 return child.getMinIntrinsicHeight(constraints); |
| 404 return super.getMinIntrinsicHeight(constraints); | 481 return super.getMinIntrinsicHeight(constraints); |
| 405 } | 482 } |
| 406 | 483 |
| 407 double getMaxIntrinsicHeight(BoxConstraints constraints) { | 484 double getMaxIntrinsicHeight(BoxConstraints constraints) { |
| 408 if (child != null) | 485 if (child != null) |
| 409 return child.getMaxIntrinsicHeight(constraints); | 486 return child.getMaxIntrinsicHeight(constraints); |
| 410 return super.getMaxIntrinsicHeight(constraints); | 487 return super.getMaxIntrinsicHeight(constraints); |
| 411 } | 488 } |
| 412 | 489 |
| 413 double getDistanceToActualBaseline(TextBaseline baseline) { | 490 double computeDistanceToActualBaseline(TextBaseline baseline) { |
| 414 if (child != null) | 491 if (child != null) |
| 415 return child.getDistanceToActualBaseline(baseline); | 492 return child.getDistanceToActualBaseline(baseline); |
| 416 return super.getDistanceToActualBaseline(baseline); | 493 return super.computeDistanceToActualBaseline(baseline); |
| 417 } | 494 } |
| 418 | 495 |
| 419 void performLayout() { | 496 void performLayout() { |
| 420 if (child != null) { | 497 if (child != null) { |
| 421 child.layout(constraints, parentUsesSize: true); | 498 child.layout(constraints, parentUsesSize: true); |
| 422 size = child.size; | 499 size = child.size; |
| 423 } else { | 500 } else { |
| 424 performResize(); | 501 performResize(); |
| 425 } | 502 } |
| 426 } | 503 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 size = child.size; | 564 size = child.size; |
| 488 } else { | 565 } else { |
| 489 size = _additionalConstraints.apply(constraints).constrain(Size.zero); | 566 size = _additionalConstraints.apply(constraints).constrain(Size.zero); |
| 490 } | 567 } |
| 491 } | 568 } |
| 492 | 569 |
| 493 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}additionalConstraints: ${additionalConstraints}\n'; | 570 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}additionalConstraints: ${additionalConstraints}\n'; |
| 494 } | 571 } |
| 495 | 572 |
| 496 class RenderShrinkWrapWidth extends RenderProxyBox { | 573 class RenderShrinkWrapWidth extends RenderProxyBox { |
| 574 | |
| 575 // This class will attempt to size its child to the child's maximum | |
| 576 // intrinsic width, snapped to a multiple of the stepWidth, if one | |
| 577 // is provided, and given the provided constraints; and will then | |
| 578 // adopt the child's resulting dimensions. | |
| 579 | |
| 580 // Note: laying out this class is relatively expensive. Avoid using | |
| 581 // it where possible. | |
| 582 | |
| 497 RenderShrinkWrapWidth({ | 583 RenderShrinkWrapWidth({ |
| 498 double stepWidth, | 584 double stepWidth, |
| 499 double stepHeight, | 585 double stepHeight, |
| 500 RenderBox child | 586 RenderBox child |
| 501 }) : _stepWidth = stepWidth, _stepHeight = stepHeight, super(child); | 587 }) : _stepWidth = stepWidth, _stepHeight = stepHeight, super(child); |
| 502 | 588 |
| 503 double _stepWidth; | 589 double _stepWidth; |
| 504 double get stepWidth => _stepWidth; | 590 double get stepWidth => _stepWidth; |
| 505 void set stepWidth(double value) { | 591 void set stepWidth(double value) { |
| 506 if (value == _stepWidth) | 592 if (value == _stepWidth) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 518 markNeedsLayout(); | 604 markNeedsLayout(); |
| 519 } | 605 } |
| 520 | 606 |
| 521 static double applyStep(double input, double step) { | 607 static double applyStep(double input, double step) { |
| 522 if (step == null) | 608 if (step == null) |
| 523 return input; | 609 return input; |
| 524 return (input / step).ceil() * step; | 610 return (input / step).ceil() * step; |
| 525 } | 611 } |
| 526 | 612 |
| 527 BoxConstraints _getInnerConstraints(BoxConstraints constraints) { | 613 BoxConstraints _getInnerConstraints(BoxConstraints constraints) { |
| 614 if (constraints.hasTightWidth) | |
| 615 return constraints; | |
| 528 double width = child.getMaxIntrinsicWidth(constraints); | 616 double width = child.getMaxIntrinsicWidth(constraints); |
| 529 assert(width == constraints.constrainWidth(width)); | 617 assert(width == constraints.constrainWidth(width)); |
| 530 return constraints.applyWidth(width); | 618 return constraints.applyWidth(applyStep(width, _stepWidth)); |
| 531 } | 619 } |
| 532 | 620 |
| 533 double getMinIntrinsicWidth(BoxConstraints constraints) { | 621 double getMinIntrinsicWidth(BoxConstraints constraints) { |
| 534 if (child == null) | 622 return getMaxIntrinsicWidth(constraints); |
| 535 return constraints.constrainWidth(0.0); | |
| 536 double childResult = child.getMinIntrinsicWidth(constraints); | |
| 537 return constraints.constrainWidth(applyStep(childResult, _stepWidth)); | |
| 538 } | 623 } |
| 539 | 624 |
| 540 double getMaxIntrinsicWidth(BoxConstraints constraints) { | 625 double getMaxIntrinsicWidth(BoxConstraints constraints) { |
| 541 if (child == null) | 626 if (child == null) |
| 542 return constraints.constrainWidth(0.0); | 627 return constraints.constrainWidth(0.0); |
| 543 double childResult = child.getMaxIntrinsicWidth(constraints); | 628 double childResult = child.getMaxIntrinsicWidth(constraints); |
| 544 return constraints.constrainWidth(applyStep(childResult, _stepWidth)); | 629 return constraints.constrainWidth(applyStep(childResult, _stepWidth)); |
| 545 } | 630 } |
| 546 | 631 |
| 547 double getMinIntrinsicHeight(BoxConstraints constraints) { | 632 double getMinIntrinsicHeight(BoxConstraints constraints) { |
| 548 if (child == null) | 633 if (child == null) |
| 549 return constraints.constrainWidth(0.0); | 634 return constraints.constrainWidth(0.0); |
| 550 double childResult = child.getMinIntrinsicHeight(_getInnerConstraints(constr aints)); | 635 double childResult = child.getMinIntrinsicHeight(_getInnerConstraints(constr aints)); |
| 551 return constraints.constrainHeight(applyStep(childResult, _stepHeight)); | 636 return constraints.constrainHeight(applyStep(childResult, _stepHeight)); |
| 552 } | 637 } |
| 553 | 638 |
| 554 double getMaxIntrinsicHeight(BoxConstraints constraints) { | 639 double getMaxIntrinsicHeight(BoxConstraints constraints) { |
| 555 if (child == null) | 640 if (child == null) |
| 556 return constraints.constrainWidth(0.0); | 641 return constraints.constrainWidth(0.0); |
| 557 double childResult = child.getMaxIntrinsicHeight(_getInnerConstraints(constr aints)); | 642 double childResult = child.getMaxIntrinsicHeight(_getInnerConstraints(constr aints)); |
| 558 return constraints.constrainHeight(applyStep(childResult, _stepHeight)); | 643 return constraints.constrainHeight(applyStep(childResult, _stepHeight)); |
| 559 } | 644 } |
| 560 | 645 |
| 561 void performLayout() { | 646 void performLayout() { |
| 562 if (child != null) { | 647 if (child != null) { |
| 563 child.layout(_getInnerConstraints(constraints), parentUsesSize: true); | 648 BoxConstraints childConstraints = _getInnerConstraints(constraints); |
| 564 size = new Size(applyStep(child.size.width, _stepWidth), applyStep(child.s ize.height, _stepHeight)); | 649 if (_stepHeight != null) |
| 650 childConstraints.applyHeight(getMaxIntrinsicHeight(childConstraints)); | |
| 651 child.layout(childConstraints, parentUsesSize: true); | |
| 652 size = child.size; | |
| 565 } else { | 653 } else { |
| 566 performResize(); | 654 performResize(); |
| 567 } | 655 } |
| 568 } | 656 } |
| 657 | |
| 658 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}stepWidth: ${stepWidth}\n${prefix}stepHeight: ${stepHeight}\n'; | |
| 659 | |
| 569 } | 660 } |
| 570 | 661 |
| 571 class RenderOpacity extends RenderProxyBox { | 662 class RenderOpacity extends RenderProxyBox { |
| 572 RenderOpacity({ RenderBox child, double opacity }) | 663 RenderOpacity({ RenderBox child, double opacity }) |
| 573 : this._opacity = opacity, super(child) { | 664 : this._opacity = opacity, super(child) { |
| 574 assert(opacity >= 0.0 && opacity <= 1.0); | 665 assert(opacity >= 0.0 && opacity <= 1.0); |
| 575 } | 666 } |
| 576 | 667 |
| 577 double _opacity; | 668 double _opacity; |
| 578 double get opacity => _opacity; | 669 double get opacity => _opacity; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 } | 803 } |
| 713 | 804 |
| 714 abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi n<RenderBox> { | 805 abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi n<RenderBox> { |
| 715 | 806 |
| 716 // Abstract class for one-child-layout render boxes | 807 // Abstract class for one-child-layout render boxes |
| 717 | 808 |
| 718 RenderShiftedBox(RenderBox child) { | 809 RenderShiftedBox(RenderBox child) { |
| 719 this.child = child; | 810 this.child = child; |
| 720 } | 811 } |
| 721 | 812 |
| 722 void paint(PaintingCanvas canvas, Offset offset) { | 813 double getMinIntrinsicWidth(BoxConstraints constraints) { |
| 723 if (child != null) | 814 if (child != null) |
| 724 canvas.paintChild(child, child.parentData.position + offset); | 815 return child.getMinIntrinsicWidth(constraints); |
| 816 return super.getMinIntrinsicWidth(constraints); | |
| 725 } | 817 } |
| 726 | 818 |
| 727 double getDistanceToActualBaseline(TextBaseline baseline) { | 819 double getMaxIntrinsicWidth(BoxConstraints constraints) { |
| 820 if (child != null) | |
| 821 return child.getMaxIntrinsicWidth(constraints); | |
| 822 return super.getMaxIntrinsicWidth(constraints); | |
| 823 } | |
| 824 | |
| 825 double getMinIntrinsicHeight(BoxConstraints constraints) { | |
| 826 if (child != null) | |
| 827 return child.getMinIntrinsicHeight(constraints); | |
| 828 return super.getMinIntrinsicHeight(constraints); | |
| 829 } | |
| 830 | |
| 831 double getMaxIntrinsicHeight(BoxConstraints constraints) { | |
| 832 if (child != null) | |
| 833 return child.getMaxIntrinsicHeight(constraints); | |
| 834 return super.getMaxIntrinsicHeight(constraints); | |
| 835 } | |
| 836 | |
| 837 double computeDistanceToActualBaseline(TextBaseline baseline) { | |
| 728 double result; | 838 double result; |
| 729 if (child != null) { | 839 if (child != null) { |
| 730 assert(!needsLayout); | 840 assert(!needsLayout); |
| 731 result = child.getDistanceToActualBaseline(baseline); | 841 result = child.getDistanceToActualBaseline(baseline); |
| 732 assert(child.parentData is BoxParentData); | 842 assert(child.parentData is BoxParentData); |
| 733 if (result != null) | 843 if (result != null) |
| 734 result += child.parentData.position.y; | 844 result += child.parentData.position.y; |
| 735 } else { | 845 } else { |
| 736 result = super.getDistanceToActualBaseline(baseline); | 846 result = super.computeDistanceToActualBaseline(baseline); |
| 737 } | 847 } |
| 738 return result; | 848 return result; |
| 739 } | 849 } |
| 740 | 850 |
| 851 void paint(PaintingCanvas canvas, Offset offset) { | |
| 852 if (child != null) | |
| 853 canvas.paintChild(child, child.parentData.position + offset); | |
| 854 } | |
| 855 | |
| 741 void hitTestChildren(HitTestResult result, { Point position }) { | 856 void hitTestChildren(HitTestResult result, { Point position }) { |
| 742 if (child != null) { | 857 if (child != null) { |
| 743 assert(child.parentData is BoxParentData); | 858 assert(child.parentData is BoxParentData); |
| 744 Rect childBounds = child.parentData.position & child.size; | 859 Rect childBounds = child.parentData.position & child.size; |
| 745 if (childBounds.contains(position)) { | 860 if (childBounds.contains(position)) { |
| 746 child.hitTest(result, position: new Point(position.x - child.parentData. position.x, | 861 child.hitTest(result, position: new Point(position.x - child.parentData. position.x, |
| 747 position.y - child.parentD ata.position.y)); | 862 position.y - child.parentD ata.position.y)); |
| 748 } | 863 } |
| 749 } | 864 } |
| 750 } | 865 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 padding.left + child.size.width + padding.right, | 928 padding.left + child.size.width + padding.right, |
| 814 padding.top + child.size.height + padding.bottom | 929 padding.top + child.size.height + padding.bottom |
| 815 )); | 930 )); |
| 816 } | 931 } |
| 817 | 932 |
| 818 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}padding: ${padding}\n'; | 933 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}padding: ${padding}\n'; |
| 819 } | 934 } |
| 820 | 935 |
| 821 class RenderPositionedBox extends RenderShiftedBox { | 936 class RenderPositionedBox extends RenderShiftedBox { |
| 822 | 937 |
| 938 // This box aligns a child box within itself. It's only useful for | |
| 939 // children that don't always size to fit their parent. For example, | |
| 940 // to align a box at the bottom right, you would pass this box a | |
| 941 // tight constraint that is bigger than the child's natural size, | |
| 942 // with horizontal and vertical set to 1.0. | |
| 943 | |
| 823 RenderPositionedBox({ | 944 RenderPositionedBox({ |
| 824 RenderBox child, | 945 RenderBox child, |
| 825 double horizontal: 0.5, | 946 double horizontal: 0.5, |
| 826 double vertical: 0.5 | 947 double vertical: 0.5 |
| 827 }) : _horizontal = horizontal, | 948 }) : _horizontal = horizontal, |
| 828 _vertical = vertical, | 949 _vertical = vertical, |
| 829 super(child) { | 950 super(child) { |
| 830 assert(horizontal != null); | 951 assert(horizontal != null); |
| 831 assert(vertical != null); | 952 assert(vertical != null); |
| 832 } | 953 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 844 double _vertical; | 965 double _vertical; |
| 845 double get vertical => _vertical; | 966 double get vertical => _vertical; |
| 846 void set vertical (double value) { | 967 void set vertical (double value) { |
| 847 assert(value != null); | 968 assert(value != null); |
| 848 if (_vertical == value) | 969 if (_vertical == value) |
| 849 return; | 970 return; |
| 850 _vertical = value; | 971 _vertical = value; |
| 851 markNeedsLayout(); | 972 markNeedsLayout(); |
| 852 } | 973 } |
| 853 | 974 |
| 854 double getMinIntrinsicWidth(BoxConstraints constraints) { | 975 void performLayout() { |
| 855 if (child != null) | 976 if (child != null) { |
| 856 return child.getMinIntrinsicWidth(constraints); | 977 child.layout(constraints.loosen(), parentUsesSize: true); |
| 857 return super.getMinIntrinsicWidth(constraints); | 978 size = constraints.constrain(child.size); |
| 979 assert(child.parentData is BoxParentData); | |
| 980 Offset delta = size - child.size; | |
| 981 child.parentData.position = (delta.scale(horizontal, vertical)).toPoint(); | |
| 982 } else { | |
| 983 performResize(); | |
| 984 } | |
| 858 } | 985 } |
| 859 | 986 |
| 860 double getMaxIntrinsicWidth(BoxConstraints constraints) { | 987 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}horizontal: ${horizontal}\n${prefix}vertical: ${vertical}\n'; |
| 861 if (child != null) | 988 } |
| 862 return child.getMaxIntrinsicWidth(constraints); | 989 |
| 863 return super.getMaxIntrinsicWidth(constraints); | 990 class RenderBaseline extends RenderShiftedBox { |
| 991 | |
| 992 RenderBaseline({ | |
| 993 RenderBox child, | |
| 994 double baseline, | |
| 995 TextBaseline baselineType | |
| 996 }) : _baseline = baseline, | |
| 997 _baselineType = baselineType, | |
| 998 super(child) { | |
| 999 assert(baseline != null); | |
| 1000 assert(baselineType != null); | |
| 864 } | 1001 } |
| 865 | 1002 |
| 866 double getMinIntrinsicHeight(BoxConstraints constraints) { | 1003 double _baseline; |
| 867 if (child != null) | 1004 double get baseline => _baseline; |
| 868 return child.getMinIntrinsicHeight(constraints); | 1005 void set baseline (double value) { |
| 869 return super.getMinIntrinsicHeight(constraints); | 1006 assert(value != null); |
| 1007 if (_baseline == value) | |
| 1008 return; | |
| 1009 _baseline = value; | |
| 1010 markNeedsLayout(); | |
| 870 } | 1011 } |
| 871 | 1012 |
| 872 double getMaxIntrinsicHeight(BoxConstraints constraints) { | 1013 TextBaseline _baselineType; |
| 873 if (child != null) | 1014 TextBaseline get baselineType => _baselineType; |
| 874 return child.getMaxIntrinsicHeight(constraints); | 1015 void set baselineType (TextBaseline value) { |
| 875 return super.getMaxIntrinsicHeight(constraints); | 1016 assert(value != null); |
| 1017 if (_baselineType == value) | |
| 1018 return; | |
| 1019 _baselineType = value; | |
| 1020 markNeedsLayout(); | |
| 876 } | 1021 } |
| 877 | 1022 |
| 878 void performLayout() { | 1023 void performLayout() { |
| 879 if (child != null) { | 1024 if (child != null) { |
| 880 child.layout(constraints.loosen(), parentUsesSize: true); | 1025 child.layout(constraints.loosen(), parentUsesSize: true); |
| 881 size = constraints.constrain(child.size); | 1026 size = constraints.constrain(child.size); |
| 882 assert(child.parentData is BoxParentData); | 1027 assert(child.parentData is BoxParentData); |
| 883 Offset delta = size - child.size; | 1028 double delta = baseline - child.getDistanceToBaseline(baselineType); |
| 884 child.parentData.position = (delta.scale(horizontal, vertical)).toPoint(); | 1029 child.parentData.position = new Point(0.0, delta); |
| 885 } else { | 1030 } else { |
| 886 performResize(); | 1031 performResize(); |
| 887 } | 1032 } |
| 888 } | 1033 } |
| 889 | 1034 |
| 890 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}horizontal: ${horizontal}\n${prefix}vertical: ${vertical}\n'; | 1035 String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings( prefix)}${prefix}baseline: ${baseline}\nbaselineType: ${baselineType}'; |
| 891 } | 1036 } |
| 892 | 1037 |
| 893 class RenderImage extends RenderBox { | 1038 class RenderImage extends RenderBox { |
| 894 | 1039 |
| 895 RenderImage(String url, Size dimensions) { | 1040 RenderImage(String url, Size dimensions) { |
| 896 requestedSize = dimensions; | 1041 requestedSize = dimensions; |
| 897 src = url; | 1042 src = url; |
| 898 } | 1043 } |
| 899 | 1044 |
| 900 sky.Image _image; | 1045 sky.Image _image; |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1248 } | 1393 } |
| 1249 | 1394 |
| 1250 } | 1395 } |
| 1251 | 1396 |
| 1252 // HELPER METHODS FOR RENDERBOX CONTAINERS | 1397 // HELPER METHODS FOR RENDERBOX CONTAINERS |
| 1253 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend erObjectMixin<ChildType, ParentDataType> { | 1398 abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare ntDataType extends ContainerParentDataMixin<ChildType>> implements ContainerRend erObjectMixin<ChildType, ParentDataType> { |
| 1254 | 1399 |
| 1255 // This class, by convention, doesn't override any members of the superclass. | 1400 // This class, by convention, doesn't override any members of the superclass. |
| 1256 // It only provides helper functions that subclasses can call. | 1401 // It only provides helper functions that subclasses can call. |
| 1257 | 1402 |
| 1258 double defaultGetDistanceToFirstActualBaseline(TextBaseline baseline) { | 1403 double defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) { |
| 1259 assert(!needsLayout); | 1404 assert(!needsLayout); |
| 1260 RenderBox child = firstChild; | 1405 RenderBox child = firstChild; |
| 1261 while (child != null) { | 1406 while (child != null) { |
| 1262 assert(child.parentData is ParentDataType); | 1407 assert(child.parentData is ParentDataType); |
| 1263 double result = child.getDistanceToActualBaseline(baseline); | 1408 double result = child.getDistanceToActualBaseline(baseline); |
| 1264 if (result != null) | 1409 if (result != null) |
| 1265 return result + child.parentData.position.y; | 1410 return result + child.parentData.position.y; |
| 1266 child = child.parentData.nextSibling; | 1411 child = child.parentData.nextSibling; |
| 1267 } | 1412 } |
| 1268 return null; | 1413 return null; |
| 1269 } | 1414 } |
| 1270 | 1415 |
| 1271 double defaultGetDistanceToHighestActualBaseline(TextBaseline baseline) { | 1416 double defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) { |
| 1272 assert(!needsLayout); | 1417 assert(!needsLayout); |
| 1273 double result; | 1418 double result; |
| 1274 RenderBox child = firstChild; | 1419 RenderBox child = firstChild; |
| 1275 while (child != null) { | 1420 while (child != null) { |
| 1276 assert(child.parentData is ParentDataType); | 1421 assert(child.parentData is ParentDataType); |
| 1277 double candidate = child.getDistanceToActualBaseline(baseline); | 1422 double candidate = child.getDistanceToActualBaseline(baseline); |
| 1278 if (candidate != null) { | 1423 if (candidate != null) { |
| 1279 candidate += child.parentData.position.x; | 1424 candidate += child.parentData.position.x; |
| 1280 if (result != null) | 1425 if (result != null) |
| 1281 result = math.min(result, candidate); | 1426 result = math.min(result, candidate); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1304 | 1449 |
| 1305 void defaultPaint(PaintingCanvas canvas, Offset offset) { | 1450 void defaultPaint(PaintingCanvas canvas, Offset offset) { |
| 1306 RenderBox child = firstChild; | 1451 RenderBox child = firstChild; |
| 1307 while (child != null) { | 1452 while (child != null) { |
| 1308 assert(child.parentData is ParentDataType); | 1453 assert(child.parentData is ParentDataType); |
| 1309 canvas.paintChild(child, child.parentData.position + offset); | 1454 canvas.paintChild(child, child.parentData.position + offset); |
| 1310 child = child.parentData.nextSibling; | 1455 child = child.parentData.nextSibling; |
| 1311 } | 1456 } |
| 1312 } | 1457 } |
| 1313 } | 1458 } |
| OLD | NEW |