basic.dart 116 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:ui' as ui show Image, ImageFilter;
6

7
import 'package:flutter/foundation.dart';
8 9
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
10

11
import 'debug.dart';
12
import 'framework.dart';
13

14
export 'package:flutter/animation.dart';
15
export 'package:flutter/foundation.dart' show TargetPlatform;
16
export 'package:flutter/painting.dart';
17
export 'package:flutter/rendering.dart' show
18 19 20 21 22
  Axis,
  BoxConstraints,
  CrossAxisAlignment,
  CustomClipper,
  CustomPainter,
23
  DecorationPosition,
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
  FlexFit,
  FlowDelegate,
  FlowPaintingContext,
  FractionalOffsetTween,
  HitTestBehavior,
  MainAxisAlignment,
  MainAxisSize,
  MultiChildLayoutDelegate,
  Overflow,
  PaintingContext,
  PointerCancelEvent,
  PointerCancelEventListener,
  PointerDownEvent,
  PointerDownEventListener,
  PointerEvent,
  PointerMoveEvent,
  PointerMoveEventListener,
  PointerUpEvent,
  PointerUpEventListener,
  RelativeRect,
  ShaderCallback,
  SingleChildLayoutDelegate,
  TextOverflow,
  ValueChanged,
Adam Barth's avatar
Adam Barth committed
48 49 50
  ValueGetter,
  WrapAlignment,
  WrapCrossAlignment;
51 52 53

// PAINTING NODES

54
/// A widget that makes its child partially transparent.
55 56 57 58
///
/// This class paints its child into an intermediate buffer and then blends the
/// child back into the scene partially transparent.
///
Ian Hickson's avatar
Ian Hickson committed
59 60 61 62
/// For values of opacity other than 0.0 and 1.0, this class is relatively
/// expensive because it requires painting the child into an intermediate
/// buffer. For the value 0.0, the child is simply not painted at all. For the
/// value 1.0, the child is painted immediately without an intermediate buffer.
63
class Opacity extends SingleChildRenderObjectWidget {
64 65 66 67
  /// Creates a widget that makes its child partially transparent.
  ///
  /// The [opacity] argument must not be null and must be between 0.0 and 1.0
  /// (inclusive).
68
  const Opacity({
69 70 71
    Key key,
    @required this.opacity,
    Widget child
72 73
  }) : assert(opacity != null && opacity >= 0.0 && opacity <= 1.0),
       super(key: key, child: child);
74

75 76 77 78
  /// The fraction to scale the child's alpha value.
  ///
  /// An opacity of 1.0 is fully opaque. An opacity of 0.0 is fully transparent
  /// (i.e., invisible).
Ian Hickson's avatar
Ian Hickson committed
79 80 81 82 83 84
  ///
  /// The opacity must not be null.
  ///
  /// Values 1.0 and 0.0 are painted with a fast path. Other values
  /// require painting the child into an intermediate buffer, which is
  /// expensive.
85 86
  final double opacity;

87
  @override
88
  RenderOpacity createRenderObject(BuildContext context) => new RenderOpacity(opacity: opacity);
89

90
  @override
91
  void updateRenderObject(BuildContext context, RenderOpacity renderObject) {
92
    renderObject.opacity = opacity;
93
  }
94

95
  @override
96 97 98 99
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('opacity: $opacity');
  }
100 101
}

102
/// A widget that applies a mask generated by a [Shader] to its child.
103 104 105
///
/// For example, [ShaderMask] can be used to gradually fade out the edge
/// of a child by using a [ui.Gradient.linear] mask.
106
class ShaderMask extends SingleChildRenderObjectWidget {
107 108
  /// Creates a widget that applies a mask generated by a [Shader] to its child.
  ///
109
  /// The [shaderCallback] and [blendMode] arguments must not be null.
110
  const ShaderMask({
Hans Muller's avatar
Hans Muller committed
111
    Key key,
112
    @required this.shaderCallback,
113
    this.blendMode: BlendMode.modulate,
Hans Muller's avatar
Hans Muller committed
114
    Widget child
115 116 117
  }) : assert(shaderCallback != null),
       assert(blendMode != null),
       super(key: key, child: child);
Hans Muller's avatar
Hans Muller committed
118

119 120 121 122
  /// Called to creates the [Shader] that generates the mask.
  ///
  /// The shader callback is called with the current size of the child so that
  /// it can customize the shader to the size and location of the child.
Hans Muller's avatar
Hans Muller committed
123
  final ShaderCallback shaderCallback;
124

125
  /// The [BlendMode] to use when applying the shader to the child.
126
  ///
127 128 129
  /// The default, [BlendMode.modulate], is useful for applying an alpha blend
  /// to the child. Other blend modes can be used to create other effects.
  final BlendMode blendMode;
Hans Muller's avatar
Hans Muller committed
130

131
  @override
132
  RenderShaderMask createRenderObject(BuildContext context) {
Hans Muller's avatar
Hans Muller committed
133 134
    return new RenderShaderMask(
      shaderCallback: shaderCallback,
135
      blendMode: blendMode
Hans Muller's avatar
Hans Muller committed
136 137 138
    );
  }

139
  @override
140
  void updateRenderObject(BuildContext context, RenderShaderMask renderObject) {
141 142
    renderObject
      ..shaderCallback = shaderCallback
143
      ..blendMode = blendMode;
Hans Muller's avatar
Hans Muller committed
144 145 146
  }
}

147
/// A widget that applies a filter to the existing painted content and then paints [child].
148 149 150
///
/// This effect is relatively expensive, especially if the filter is non-local,
/// such as a blur.
151
class BackdropFilter extends SingleChildRenderObjectWidget {
152 153 154
  /// Creates a backdrop filter.
  ///
  /// The [filter] argument must not be null.
155
  const BackdropFilter({
156
    Key key,
157
    @required this.filter,
158
    Widget child
159 160
  }) : assert(filter != null),
       super(key: key, child: child);
161

162 163 164 165
  /// The image filter to apply to the existing painted content before painting the child.
  ///
  /// For example, consider using [ui.ImageFilter.blur] to create a backdrop
  /// blur effect
166 167 168 169 170 171 172 173 174 175 176 177 178
  final ui.ImageFilter filter;

  @override
  RenderBackdropFilter createRenderObject(BuildContext context) {
    return new RenderBackdropFilter(filter: filter);
  }

  @override
  void updateRenderObject(BuildContext context, RenderBackdropFilter renderObject) {
    renderObject.filter = filter;
  }
}

179
/// A widget that provides a canvas on which to draw during the paint phase.
180
///
181
/// When asked to paint, [CustomPaint] first asks its [painter] to paint on the
182
/// current canvas, then it paints its child, and then, after painting its
183
/// child, it asks its [foregroundPainter] to paint. The coodinate system of the
184 185
/// canvas matches the coordinate system of the [CustomPaint] object. The
/// painters are expected to paint within a rectangle starting at the origin and
186
/// encompassing a region of the given size. (If the painters paint outside
187 188
/// those bounds, there might be insufficient memory allocated to rasterize the
/// painting commands and the resulting behavior is undefined.)
189
///
190 191
/// Painters are implemented by subclassing [CustomPainter].
///
Ian Hickson's avatar
Ian Hickson committed
192 193 194 195 196 197 198
/// Because custom paint calls its painters during paint, you cannot call
/// `setState` or `markNeedsLayout` during the callback (the layout for this
/// frame has already happened).
///
/// Custom painters normally size themselves to their child. If they do not have
/// a child, they attempt to size themselves to the [size], which defaults to
/// [Size.zero].
199
///
200 201
/// See also:
///
202 203
///  * [CustomPainter].
///  * [Canvas].
204
class CustomPaint extends SingleChildRenderObjectWidget {
205
  /// Creates a widget that delegates its painting.
206 207 208
  const CustomPaint({ Key key, this.painter, this.foregroundPainter, this.size: Size.zero, Widget child })
    : assert(size != null),
      super(key: key, child: child);
209

210
  /// The painter that paints before the children.
211
  final CustomPainter painter;
212 213

  /// The painter that paints after the children.
214
  final CustomPainter foregroundPainter;
Adam Barth's avatar
Adam Barth committed
215

Ian Hickson's avatar
Ian Hickson committed
216 217 218 219 220 221 222 223 224
  /// The size that this [CustomPaint] should aim for, given the layout
  /// constraints, if there is no child.
  ///
  /// Defaults to [Size.zero].
  ///
  /// If there's a child, this is ignored, and the size of the child is used
  /// instead.
  final Size size;

225
  @override
226
  RenderCustomPaint createRenderObject(BuildContext context) => new RenderCustomPaint(
227
    painter: painter,
Ian Hickson's avatar
Ian Hickson committed
228 229
    foregroundPainter: foregroundPainter,
    preferredSize: size,
230
  );
231

232
  @override
233
  void updateRenderObject(BuildContext context, RenderCustomPaint renderObject) {
234 235
    renderObject
      ..painter = painter
Ian Hickson's avatar
Ian Hickson committed
236 237
      ..foregroundPainter = foregroundPainter
      ..preferredSize = size;
238 239
  }

240
  @override
241
  void didUnmountRenderObject(RenderCustomPaint renderObject) {
242 243 244
    renderObject
      ..painter = null
      ..foregroundPainter = null;
245 246 247
  }
}

248
/// A widget that clips its child using a rectangle.
249
///
250
/// By default, [ClipRect] prevents its child from painting outside its
251 252
/// bounds, but the size and location of the clip rect can be customized using a
/// custom [clipper].
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
///
/// [ClipRect] is commonly used with these widgets, which commonly paint outside
/// their bounds.
///
///  * [CustomPaint]
///  * [CustomSingleChildLayout]
///  * [CustomMultiChildLayout]
///  * [Align] and [Center] (e.g., if [Align.widthFactor] or
///    [Align.heightFactor] is less than 1.0).
///  * [OverflowBox]
///  * [SizedOverflowBox]
///
/// ## Example
///
/// For example, use a clip to show the top half of an [Image], you can use a
/// [ClipRect] combined with an [Align]:
///
/// ```dart
/// new ClipRect(
///   child: new Align(
///     alignment: FractionalOffset.topCenter,
///     heightFactor: 0.5,
///     child: new Image(...),
///   ),
/// ),
/// ```
///
/// See also:
///
///  * [CustomClipper], for information about creating custom clips.
///  * [ClipRRect], for a clip with rounded corners.
///  * [ClipOval], for an elliptical clip.
///  * [ClipPath], for an arbitrarily shaped clip.
286
class ClipRect extends SingleChildRenderObjectWidget {
287 288 289 290
  /// Creates a rectangular clip.
  ///
  /// If [clipper] is null, the clip will match the layout size and position of
  /// the child.
291
  const ClipRect({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
292

293
  /// If non-null, determines which clip to use.
294 295
  final CustomClipper<Rect> clipper;

296
  @override
297
  RenderClipRect createRenderObject(BuildContext context) => new RenderClipRect(clipper: clipper);
298

299
  @override
300
  void updateRenderObject(BuildContext context, RenderClipRect renderObject) {
301 302 303
    renderObject.clipper = clipper;
  }

304
  @override
305 306 307
  void didUnmountRenderObject(RenderClipRect renderObject) {
    renderObject.clipper = null;
  }
308 309
}

310
/// A widget that clips its child using a rounded rectangle.
311
///
312 313 314
/// By default, [ClipRRect] uses its own bounds as the base rectangle for the
/// clip, but the size and location of the clip can be customized using a custom
/// [clipper].
315 316 317 318 319 320 321
///
/// See also:
///
///  * [CustomClipper], for information about creating custom clips.
///  * [ClipRect], for more efficient clips without rounded corners.
///  * [ClipOval], for an elliptical clip.
///  * [ClipPath], for an arbitrarily shaped clip.
322
class ClipRRect extends SingleChildRenderObjectWidget {
323
  /// Creates a rounded-rectangular clip.
324 325 326 327 328
  ///
  /// The [borderRadius] defaults to [BorderRadius.zero], i.e. a rectangle with
  /// right-angled corners.
  ///
  /// If [clipper] is non-null, then [borderRadius] is ignored.
329
  const ClipRRect({
330
    Key key,
331 332 333
    this.borderRadius,
    this.clipper,
    Widget child,
334 335
  }) : assert(borderRadius != null || clipper != null),
       super(key: key, child: child);
336

337
  /// The border radius of the rounded corners.
338
  ///
339 340 341 342
  /// Values are clamped so that horizontal and vertical radii sums do not
  /// exceed width/height.
  ///
  /// This value is ignored if [clipper] is non-null.
343
  final BorderRadius borderRadius;
344

345 346 347
  /// If non-null, determines which clip to use.
  final CustomClipper<RRect> clipper;

348
  @override
349
  RenderClipRRect createRenderObject(BuildContext context) => new RenderClipRRect(borderRadius: borderRadius, clipper: clipper);
350

351
  @override
352
  void updateRenderObject(BuildContext context, RenderClipRRect renderObject) {
353
    renderObject
354 355
      ..borderRadius = borderRadius
      ..clipper = clipper;
356 357 358
  }
}

359
/// A widget that clips its child using an oval.
360
///
361 362 363
/// By default, inscribes an axis-aligned oval into its layout dimensions and
/// prevents its child from painting outside that oval, but the size and
/// location of the clip oval can be customized using a custom [clipper].
364 365 366 367 368 369 370 371
/// See also:
///
/// See also:
///
///  * [CustomClipper], for information about creating custom clips.
///  * [ClipRect], for more efficient clips without rounded corners.
///  * [ClipRRect], for a clip with rounded corners.
///  * [ClipPath], for an arbitrarily shaped clip.
372
class ClipOval extends SingleChildRenderObjectWidget {
373 374 375 376
  /// Creates an oval-shaped clip.
  ///
  /// If [clipper] is null, the oval will be inscribed into the layout size and
  /// position of the child.
377
  const ClipOval({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
378

379
  /// If non-null, determines which clip to use.
Ian Hickson's avatar
Ian Hickson committed
380 381 382 383 384 385 386 387
  ///
  /// The delegate returns a rectangle that describes the axis-aligned
  /// bounding box of the oval. The oval's axes will themselves also
  /// be axis-aligned.
  ///
  /// If the [clipper] delegate is null, then the oval uses the
  /// widget's bounding box (the layout dimensions of the render
  /// object) instead.
388 389
  final CustomClipper<Rect> clipper;

390
  @override
391
  RenderClipOval createRenderObject(BuildContext context) => new RenderClipOval(clipper: clipper);
392

393
  @override
394
  void updateRenderObject(BuildContext context, RenderClipOval renderObject) {
395 396 397
    renderObject.clipper = clipper;
  }

398
  @override
399 400 401
  void didUnmountRenderObject(RenderClipOval renderObject) {
    renderObject.clipper = null;
  }
402 403
}

404
/// A widget that clips its child using a path.
Ian Hickson's avatar
Ian Hickson committed
405
///
406
/// Calls a callback on a delegate whenever the widget is to be
Ian Hickson's avatar
Ian Hickson committed
407 408 409 410 411 412 413 414 415 416
/// painted. The callback returns a path and the widget prevents the
/// child from painting outside the path.
///
/// Clipping to a path is expensive. Certain shapes have more
/// optimized widgets:
///
///  * To clip to a rectangle, consider [ClipRect].
///  * To clip to an oval or circle, consider [ClipOval].
///  * To clip to a rounded rectangle, consider [ClipRRect].
class ClipPath extends SingleChildRenderObjectWidget {
417 418 419 420 421 422
  /// Creates a path clip.
  ///
  /// If [clipper] is null, the clip will be a rectangle that matches the layout
  /// size and location of the child. However, rather than use this default,
  /// consider using a [ClipRect], which can achieve the same effect more
  /// efficiently.
423
  const ClipPath({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
Ian Hickson's avatar
Ian Hickson committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445

  /// If non-null, determines which clip to use.
  ///
  /// The default clip, which is used if this property is null, is the
  /// bounding box rectangle of the widget. [ClipRect] is a more
  /// efficient way of obtaining that effect.
  final CustomClipper<Path> clipper;

  @override
  RenderClipPath createRenderObject(BuildContext context) => new RenderClipPath(clipper: clipper);

  @override
  void updateRenderObject(BuildContext context, RenderClipPath renderObject) {
    renderObject.clipper = clipper;
  }

  @override
  void didUnmountRenderObject(RenderClipPath renderObject) {
    renderObject.clipper = null;
  }
}

446 447 448
/// A widget representing a physical layer that clips its children to a shape.
class PhysicalModel extends SingleChildRenderObjectWidget {
  /// Creates a physical model with a rounded-rectangular clip.
449
  const PhysicalModel({
450 451 452 453 454 455
    Key key,
    @required this.shape,
    this.borderRadius: BorderRadius.zero,
    @required this.elevation,
    @required this.color,
    Widget child,
456 457 458 459 460
  }) : assert(shape != null),
       assert(borderRadius != null),
       assert(elevation != null),
       assert(color != null),
       super(key: key, child: child);
461 462 463 464 465 466 467 468

  /// The type of shape.
  final BoxShape shape;

  /// The border radius of the rounded corners.
  ///
  /// Values are clamped so that horizontal and vertical radii sums do not
  /// exceed width/height.
469 470
  ///
  /// This is ignored if the [shape] is not [BoxShape.rectangle].
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
  final BorderRadius borderRadius;

  /// The z-coordinate at which to place this physical object.
  final int elevation;

  /// The background color.
  final Color color;

  @override
  RenderPhysicalModel createRenderObject(BuildContext context) => new RenderPhysicalModel(shape: shape, borderRadius: borderRadius, elevation: elevation, color: color);

  @override
  void updateRenderObject(BuildContext context, RenderPhysicalModel renderObject) {
    renderObject
      ..shape = shape
      ..borderRadius = borderRadius
      ..elevation = elevation
      ..color = color;
  }
}
491 492 493

// POSITIONING AND SIZING NODES

494
/// A widget that applies a transformation before painting its child.
495
class Transform extends SingleChildRenderObjectWidget {
496 497 498
  /// Creates a widget that transforms its child.
  ///
  /// The [transform] argument must not be null.
499
  const Transform({
500
    Key key,
501
    @required this.transform,
502 503 504 505
    this.origin,
    this.alignment,
    this.transformHitTests: true,
    Widget child
506 507
  }) : assert(transform != null),
       super(key: key, child: child);
508

509
  /// The matrix to transform the child by during painting.
510
  final Matrix4 transform;
511 512 513 514 515 516

  /// The origin of the coordinate system (relative to the upper left corder of
  /// this render object) in which to apply the matrix.
  ///
  /// Setting an origin is equivalent to conjugating the transform matrix by a
  /// translation. This property is provided just for convenience.
517
  final Offset origin;
518 519 520 521

  /// The alignment of the origin, relative to the size of the box.
  ///
  /// This is equivalent to setting an origin based on the size of the box.
522
  /// If it is specified at the same time as an offset, both are applied.
Hixie's avatar
Hixie committed
523
  final FractionalOffset alignment;
524

525 526 527
  /// Whether to apply the translation when performing hit tests.
  final bool transformHitTests;

528
  @override
529
  RenderTransform createRenderObject(BuildContext context) => new RenderTransform(
530 531 532 533 534
    transform: transform,
    origin: origin,
    alignment: alignment,
    transformHitTests: transformHitTests
  );
535

536
  @override
537
  void updateRenderObject(BuildContext context, RenderTransform renderObject) {
538 539 540 541 542
    renderObject
      ..transform = transform
      ..origin = origin
      ..alignment = alignment
      ..transformHitTests = transformHitTests;
543 544 545
  }
}

Adam Barth's avatar
Adam Barth committed
546 547 548 549 550
/// Scales and positions its child within itself according to [fit].
class FittedBox extends SingleChildRenderObjectWidget {
  /// Creates a widget that scales and positions its child within itself according to [fit].
  ///
  /// The [fit] and [alignment] arguments must not be null.
551
  const FittedBox({
Adam Barth's avatar
Adam Barth committed
552
    Key key,
553
    this.fit: BoxFit.contain,
Adam Barth's avatar
Adam Barth committed
554 555
    this.alignment: FractionalOffset.center,
    Widget child
556 557 558
  }) : assert(fit != null),
       assert(alignment != null),
       super(key: key, child: child);
Adam Barth's avatar
Adam Barth committed
559 560

  /// How to inscribe the child into the space allocated during layout.
561
  final BoxFit fit;
Adam Barth's avatar
Adam Barth committed
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580

  /// How to align the child within its parent's bounds.
  ///
  /// An alignment of (0.0, 0.0) aligns the child to the top-left corner of its
  /// parent's bounds.  An alignment of (1.0, 0.5) aligns the child to the middle
  /// of the right edge of its parent's bounds.
  final FractionalOffset alignment;

  @override
  RenderFittedBox createRenderObject(BuildContext context) => new RenderFittedBox(fit: fit, alignment: alignment);

  @override
  void updateRenderObject(BuildContext context, RenderFittedBox renderObject) {
    renderObject
      ..fit = fit
      ..alignment = alignment;
  }
}

581 582
/// A widget that applies a translation expressed as a fraction of the box's
/// size before painting its child.
583
class FractionalTranslation extends SingleChildRenderObjectWidget {
584 585 586
  /// Creates a widget that translates its child's painting.
  ///
  /// The [translation] argument must not be null.
587
  const FractionalTranslation({
588
    Key key,
589
    @required this.translation,
590 591
    this.transformHitTests: true,
    Widget child
592 593
  }) : assert(translation != null),
       super(key: key, child: child);
594 595 596 597 598 599 600

  /// The offset by which to translate the child, as a multiple of its size.
  final FractionalOffset translation;

  /// Whether to apply the translation when performing hit tests.
  final bool transformHitTests;

601
  @override
602
  RenderFractionalTranslation createRenderObject(BuildContext context) => new RenderFractionalTranslation(translation: translation, transformHitTests: transformHitTests);
603

604
  @override
605
  void updateRenderObject(BuildContext context, RenderFractionalTranslation renderObject) {
606 607 608
    renderObject
      ..translation = translation
      ..transformHitTests = transformHitTests;
609 610 611
  }
}

612
/// A widget that rotates its child by a integral number of quarter turns.
613 614 615 616
///
/// Unlike [Transform], which applies a transform just prior to painting,
/// this object applies its rotation prior to layout, which means the entire
/// rotated box consumes only as much space as required by the rotated child.
617
class RotatedBox extends SingleChildRenderObjectWidget {
618 619 620
  /// A widget that rotates its child.
  ///
  /// The [quarterTurns] argument must not be null.
621
  const RotatedBox({
622 623 624
    Key key,
    @required this.quarterTurns,
    Widget child
625 626
  }) : assert(quarterTurns != null),
       super(key: key, child: child);
627 628 629 630

  /// The number of clockwise quarter turns the child should be rotated.
  final int quarterTurns;

631
  @override
632 633
  RenderRotatedBox createRenderObject(BuildContext context) => new RenderRotatedBox(quarterTurns: quarterTurns);

634
  @override
635 636 637 638 639
  void updateRenderObject(BuildContext context, RenderRotatedBox renderObject) {
    renderObject.quarterTurns = quarterTurns;
  }
}

640
/// A widget that insets its child by the given padding.
641 642 643 644 645
///
/// When passing layout constraints to its child, padding shrinks the
/// constraints by the given padding, causing the child to layout at a smaller
/// size. Padding then sizes itself to its child's size, inflated by the
/// padding, effectively creating empty space around the child.
646
class Padding extends SingleChildRenderObjectWidget {
647 648 649
  /// Creates a widget that insets its child.
  ///
  /// The [padding] argument must not be null.
650
  const Padding({
651 652 653
    Key key,
    @required this.padding,
    Widget child
654 655
  }) : assert(padding != null),
       super(key: key, child: child);
656

657
  /// The amount of space by which to inset the child.
658
  final EdgeInsets padding;
659

660
  @override
661
  RenderPadding createRenderObject(BuildContext context) => new RenderPadding(padding: padding);
662

663
  @override
664
  void updateRenderObject(BuildContext context, RenderPadding renderObject) {
665
    renderObject.padding = padding;
666 667 668
  }
}

669 670
/// A widget that aligns its child within itself and optionally sizes itself
/// based on the child's size.
671 672 673
///
/// For example, to align a box at the bottom right, you would pass this box a
/// tight constraint that is bigger than the child's natural size,
Adam Barth's avatar
Adam Barth committed
674
/// with an alignment of [FractionalOffset.bottomRight].
Adam Barth's avatar
Adam Barth committed
675
///
676 677 678 679 680
/// This widget will be as big as possible if its dimensions are constrained and
/// [widthFactor] and [heightFactor] are null. If a dimension is unconstrained
/// and the corresponding size factor is null then the widget will match its
/// child's size in that dimension. If a size factor is non-null then the
/// corresponding dimension of this widget will be the product of the child's
Hans Muller's avatar
Hans Muller committed
681 682
/// dimension and the size factor. For example if widthFactor is 2.0 then
/// the width of this widget will always be twice its child's width.
Adam Barth's avatar
Adam Barth committed
683 684 685
///
/// See also:
///
686 687
///  * [CustomSingleChildLayout], which uses a delegate to control the layout of
///    a single child.
688 689 690 691
///  * [Center], which is the same as [Align] but with the [alignment] always
///    set to [FractionalOffset.center].
///  * [FractionallySizedBox], which sizes its child based on a fraction of its own
///    size and positions the child according to a [FractionalOffset] value.
692
class Align extends SingleChildRenderObjectWidget {
Adam Barth's avatar
Adam Barth committed
693 694 695
  /// Creates an alignment widget.
  ///
  /// The alignment defaults to [FractionalOffset.center].
696
  const Align({
697
    Key key,
Adam Barth's avatar
Adam Barth committed
698
    this.alignment: FractionalOffset.center,
699 700
    this.widthFactor,
    this.heightFactor,
701
    Widget child
702 703 704 705
  }) : assert(alignment != null),
       assert(widthFactor == null || widthFactor >= 0.0),
       assert(heightFactor == null || heightFactor >= 0.0),
       super(key: key, child: child);
706

707 708 709 710 711 712 713 714 715
  /// How to align the child.
  ///
  /// The x and y values of the alignment control the horizontal and vertical
  /// alignment, respectively.  An x value of 0.0 means that the left edge of
  /// the child is aligned with the left edge of the parent whereas an x value
  /// of 1.0 means that the right edge of the child is aligned with the right
  /// edge of the parent. Other values interpolate (and extrapolate) linearly.
  /// For example, a value of 0.5 means that the center of the child is aligned
  /// with the center of the parent.
716
  final FractionalOffset alignment;
717 718 719 720

  /// If non-null, sets its width to the child's width multipled by this factor.
  ///
  /// Can be both greater and less than 1.0 but must be positive.
721
  final double widthFactor;
722 723 724 725

  /// If non-null, sets its height to the child's height multipled by this factor.
  ///
  /// Can be both greater and less than 1.0 but must be positive.
726
  final double heightFactor;
727

728
  @override
729
  RenderPositionedBox createRenderObject(BuildContext context) => new RenderPositionedBox(alignment: alignment, widthFactor: widthFactor, heightFactor: heightFactor);
730

731
  @override
732
  void updateRenderObject(BuildContext context, RenderPositionedBox renderObject) {
733 734 735 736
    renderObject
      ..alignment = alignment
      ..widthFactor = widthFactor
      ..heightFactor = heightFactor;
737
  }
738 739 740 741 742 743 744 745 746 747

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('alignment: $alignment');
    if (widthFactor != null)
      description.add('widthFactor: $widthFactor');
    if (heightFactor != null)
      description.add('heightFactor: $heightFactor');
  }
748 749
}

750
/// A widget that centers its child within itself.
Adam Barth's avatar
Adam Barth committed
751
///
752 753 754 755 756 757 758 759
/// This widget will be as big as possible if its dimensions are constrained and
/// [widthFactor] and [heightFactor] are null. If a dimension is unconstrained
/// and the corresponding size factor is null then the widget will match its
/// child's size in that dimension. If a size factor is non-null then the
/// corresponding dimension of this widget will be the product of the child's
/// dimension and the size factor. For example if widthFactor is 2.0 then
/// the width of this widget will always be twice its child's width.
///
Adam Barth's avatar
Adam Barth committed
760 761
/// See also:
///
762 763
///  * [Align], which lets you arbitrarily position a child within itself,
///    rather than just centering it.
764
class Center extends Align {
765
  /// Creates a widget that centers its child.
766
  const Center({ Key key, double widthFactor, double heightFactor, Widget child })
767
    : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
768 769
}

770
/// A widget that defers the layout of its single child to a delegate.
771 772 773 774 775
///
/// The delegate can determine the layout constraints for the child and can
/// decide where to position the child. The delegate can also determine the size
/// of the parent, but the size of the parent cannot depend on the size of the
/// child.
Adam Barth's avatar
Adam Barth committed
776 777 778
///
/// See also:
///
779 780 781 782 783 784 785
///  * [SingleChildLayoutDelegate], which controls the layout of the child.
///  * [Align], which sizes itself based on its child's size and positions
///    the child according to a [FractionalOffset] value.
///  * [FractionallySizedBox], which sizes its child based on a fraction of its own
///    size and positions the child according to a [FractionalOffset] value.
///  * [CustomMultiChildLayout], which uses a delegate to position multiple
///    children.
786
class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
Adam Barth's avatar
Adam Barth committed
787 788
  /// Creates a custom single child layout.
  ///
789
  /// The [delegate] argument must not be null.
790
  const CustomSingleChildLayout({
Adam Barth's avatar
Adam Barth committed
791
    Key key,
792
    @required this.delegate,
Adam Barth's avatar
Adam Barth committed
793
    Widget child
794 795
  }) : assert(delegate != null),
       super(key: key, child: child);
Adam Barth's avatar
Adam Barth committed
796

Adam Barth's avatar
Adam Barth committed
797
  /// The delegate that controls the layout of the child.
798
  final SingleChildLayoutDelegate delegate;
Adam Barth's avatar
Adam Barth committed
799

800
  @override
801
  RenderCustomSingleChildLayoutBox createRenderObject(BuildContext context) => new RenderCustomSingleChildLayoutBox(delegate: delegate);
Adam Barth's avatar
Adam Barth committed
802

803
  @override
804
  void updateRenderObject(BuildContext context, RenderCustomSingleChildLayoutBox renderObject) {
805 806 807 808
    renderObject.delegate = delegate;
  }
}

809
/// Meta data for identifying children in a [CustomMultiChildLayout].
810
///
Hans Muller's avatar
Hans Muller committed
811 812
/// The [MultiChildLayoutDelegate] hasChild, layoutChild, and positionChild
/// methods use these identifiers.
813
class LayoutId extends ParentDataWidget<CustomMultiChildLayout> {
Adam Barth's avatar
Adam Barth committed
814 815 816
  /// Marks a child with a layout identifier.
  ///
  /// Both the child and the id arguments must not be null.
817 818
  LayoutId({
    Key key,
819
    @required this.id,
820
    @required Widget child
821 822 823
  }) : assert(child != null),
       assert(id != null),
       super(key: key ?? new ValueKey<Object>(id), child: child);
824

825
  /// An object representing the identity of this child.
826 827
  final Object id;

828
  @override
829 830 831 832 833
  void applyParentData(RenderObject renderObject) {
    assert(renderObject.parentData is MultiChildLayoutParentData);
    final MultiChildLayoutParentData parentData = renderObject.parentData;
    if (parentData.id != id) {
      parentData.id = id;
834
      final AbstractNode targetParent = renderObject.parent;
835 836 837 838 839
      if (targetParent is RenderObject)
        targetParent.markNeedsLayout();
    }
  }

840
  @override
841 842 843 844 845 846
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('id: $id');
  }
}

847
/// A widget that uses a delegate to size and position multiple children.
848 849 850 851 852
///
/// The delegate can determine the layout constraints for each child and can
/// decide where to position each child. The delegate can also determine the
/// size of the parent, but the size of the parent cannot depend on the sizes of
/// the children.
Adam Barth's avatar
Adam Barth committed
853
///
854 855 856 857 858 859 860 861 862
/// [CustomMultiChildLayout] is appropriate when there are complex relationships
/// between the size and positioning of a multiple widgets. To control the
/// layout of a single child, [CustomSingleChildLayout] is more appropriate. For
/// simple cases, such as aligning a widget to one or another edge, the [Stack]
/// widget is more appropriate.
///
/// Each child must be wrapped in a [LayoutId] widget to identify the widget for
/// the delegate.
///
Adam Barth's avatar
Adam Barth committed
863 864
/// See also:
///
865 866 867 868 869 870 871
/// * [MultiChildLayoutDelegate], for details about how to control the layout of
///   the children.
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
///   a single child.
/// * [Stack], which arranges children relative to the edges of the container.
/// * [Flow], which provides paint-time control of its children using transform
///   matrices.
872
class CustomMultiChildLayout extends MultiChildRenderObjectWidget {
Adam Barth's avatar
Adam Barth committed
873 874
  /// Creates a custom multi-child layout.
  ///
875
  /// The [delegate] argument must not be null.
876
  CustomMultiChildLayout({
877
    Key key,
878
    @required this.delegate,
879
    List<Widget> children: const <Widget>[],
880 881
  }) : assert(delegate != null),
       super(key: key, children: children);
882

883
  /// The delegate that controls the layout of the children.
884 885
  final MultiChildLayoutDelegate delegate;

886
  @override
887
  RenderCustomMultiChildLayoutBox createRenderObject(BuildContext context) {
888 889 890
    return new RenderCustomMultiChildLayoutBox(delegate: delegate);
  }

891
  @override
892
  void updateRenderObject(BuildContext context, RenderCustomMultiChildLayoutBox renderObject) {
Adam Barth's avatar
Adam Barth committed
893 894 895 896
    renderObject.delegate = delegate;
  }
}

897 898
/// A box with a specified size.
///
Adam Barth's avatar
Adam Barth committed
899 900 901 902 903 904 905
/// If given a child, this widget forces its child to have a specific width
/// and/or height (assuming values are permitted by this widget's parent). If
/// either the width or height is null, this widget will size itself to match
/// the child's size in that dimension.
///
/// If not given a child, this widget will size itself to the given width and
/// height, treating nulls as zero.
Ian Hickson's avatar
Ian Hickson committed
906 907 908 909
///
/// The [new SizedBox.expand] constructor can be used to make a [SizedBox] that
/// sizes itself to fit the parent. It is equivalent to setting [width] and
/// [height] to [double.INFINITY].
910
class SizedBox extends SingleChildRenderObjectWidget {
911 912 913
  /// Creates a fixed size box. The [width] and [height] parameters can be null
  /// to indicate that the size of the box should not be constrained in
  /// the corresponding dimension.
914
  const SizedBox({ Key key, this.width, this.height, Widget child })
915 916
    : super(key: key, child: child);

917
  /// Creates a box that will become as large as its parent allows.
Ian Hickson's avatar
Ian Hickson committed
918 919 920 921 922
  const SizedBox.expand({ Key key, Widget child })
    : width = double.INFINITY,
      height = double.INFINITY,
      super(key: key, child: child);

923 924 925 926 927 928
  /// Creates a box with the specified size.
  SizedBox.fromSize({ Key key, Widget child, Size size })
    : width = size?.width,
      height = size?.height,
      super(key: key, child: child);

929
  /// If non-null, requires the child to have exactly this width.
930
  final double width;
931 932

  /// If non-null, requires the child to have exactly this height.
933 934
  final double height;

935
  @override
936
  RenderConstrainedBox createRenderObject(BuildContext context) => new RenderConstrainedBox(
937 938
    additionalConstraints: _additionalConstraints
  );
939

940
  BoxConstraints get _additionalConstraints {
941
    return new BoxConstraints.tightFor(width: width, height: height);
942 943
  }

944
  @override
945
  void updateRenderObject(BuildContext context, RenderConstrainedBox renderObject) {
946
    renderObject.additionalConstraints = _additionalConstraints;
947
  }
948

Ian Hickson's avatar
Ian Hickson committed
949 950
  @override
  String toStringShort() {
951
    final String type = (width == double.INFINITY && height == double.INFINITY) ?
Ian Hickson's avatar
Ian Hickson committed
952 953 954 955
                  '$runtimeType.expand' : '$runtimeType';
    return key == null ? '$type' : '$type-$key';
  }

956
  @override
957 958
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
Ian Hickson's avatar
Ian Hickson committed
959 960 961 962 963 964
    if (width != double.INFINITY || height != double.INFINITY) {
      if (width != null)
        description.add('width: $width');
      if (height != null)
        description.add('height: $height');
    }
965
  }
966 967
}

968
/// A widget that imposes additional constraints on its child.
969 970 971
///
/// For example, if you wanted [child] to have a minimum height of 50.0 logical
/// pixels, you could use `const BoxConstraints(minHeight: 50.0)`` as the
972
/// [constraints].
973
class ConstrainedBox extends SingleChildRenderObjectWidget {
974 975 976 977 978 979 980
  /// Creates a widget that imposes additional constraints on its child.
  ///
  /// The [constraints] argument must not be null.
  ConstrainedBox({
    Key key,
    @required this.constraints,
    Widget child
981 982
  }) : assert(constraints != null),
       super(key: key, child: child) {
983
    assert(constraints.debugAssertIsValid());
984
  }
985

986
  /// The additional constraints to impose on the child.
987 988
  final BoxConstraints constraints;

989
  @override
990
  RenderConstrainedBox createRenderObject(BuildContext context) => new RenderConstrainedBox(additionalConstraints: constraints);
991

992
  @override
993
  void updateRenderObject(BuildContext context, RenderConstrainedBox renderObject) {
994
    renderObject.additionalConstraints = constraints;
995
  }
996

997
  @override
998 999
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
Hixie's avatar
Hixie committed
1000
    description.add('$constraints');
1001
  }
1002 1003
}

1004
/// A widget that sizes its child to a fraction of the total available space.
1005
/// For more details about the layout algorithm, see [RenderFractionallySizedOverflowBox].
1006
///
1007
/// See also:
1008
///
Hans Muller's avatar
Hans Muller committed
1009 1010
/// * [Align] (which sizes itself based on its child's size and positions
///   the child according to a [FractionalOffset] value)
1011
/// * [OverflowBox]
1012
class FractionallySizedBox extends SingleChildRenderObjectWidget {
1013 1014 1015 1016
  /// Creates a widget that sizes its child to a fraction of the total available space.
  ///
  /// If non-null, the [widthFactor] and [heightFactor] arguments must be
  /// non-negative.
1017
  const FractionallySizedBox({
1018
    Key key,
Adam Barth's avatar
Adam Barth committed
1019
    this.alignment: FractionalOffset.center,
1020 1021
    this.widthFactor,
    this.heightFactor,
1022
    Widget child
1023 1024 1025 1026
  }) : assert(alignment != null),
       assert(widthFactor == null || widthFactor >= 0.0),
       assert(heightFactor == null || heightFactor >= 0.0),
       super(key: key, child: child);
Hixie's avatar
Hixie committed
1027

1028
  /// If non-null, the fraction of the incoming width given to the child.
1029 1030 1031
  ///
  /// If non-null, the child is given a tight width constraint that is the max
  /// incoming width constraint multipled by this factor.
1032 1033 1034
  ///
  /// If null, the incoming width constraints are passed to the child
  /// unmodified.
1035
  final double widthFactor;
1036

Hans Muller's avatar
Hans Muller committed
1037
  /// If non-null, the fraction of the incoming height given to the child.
1038 1039 1040
  ///
  /// If non-null, the child is given a tight height constraint that is the max
  /// incoming height constraint multipled by this factor.
1041 1042 1043
  ///
  /// If null, the incoming height constraints are passed to the child
  /// unmodified.
1044
  final double heightFactor;
Hixie's avatar
Hixie committed
1045

1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
  /// How to align the child.
  ///
  /// The x and y values of the alignment control the horizontal and vertical
  /// alignment, respectively.  An x value of 0.0 means that the left edge of
  /// the child is aligned with the left edge of the parent whereas an x value
  /// of 1.0 means that the right edge of the child is aligned with the right
  /// edge of the parent. Other values interpolate (and extrapolate) linearly.
  /// For example, a value of 0.5 means that the center of the child is aligned
  /// with the center of the parent.
  final FractionalOffset alignment;

1057
  @override
1058 1059
  RenderFractionallySizedOverflowBox createRenderObject(BuildContext context) => new RenderFractionallySizedOverflowBox(
    alignment: alignment,
1060 1061
    widthFactor: widthFactor,
    heightFactor: heightFactor
Hixie's avatar
Hixie committed
1062 1063
  );

1064
  @override
1065
  void updateRenderObject(BuildContext context, RenderFractionallySizedOverflowBox renderObject) {
1066
    renderObject
1067
      ..alignment = alignment
1068 1069
      ..widthFactor = widthFactor
      ..heightFactor = heightFactor;
Hixie's avatar
Hixie committed
1070
  }
1071

1072
  @override
1073 1074
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
1075
    description.add('alignment: $alignment');
1076 1077 1078 1079
    if (widthFactor != null)
      description.add('widthFactor: $widthFactor');
    if (heightFactor != null)
      description.add('heightFactor: $heightFactor');
1080
  }
Hixie's avatar
Hixie committed
1081 1082
}

1083 1084 1085 1086 1087 1088
/// A box that limits its size only when it's unconstrained.
///
/// If this widget's maximum width is unconstrained then its child's width is
/// limited to maxWidth. Similarly, if this widget's maximum height is unconstrained
/// then its child's height is limited to to maxHeight.
class LimitedBox extends SingleChildRenderObjectWidget {
1089 1090 1091 1092
  /// Creates a box that limits its size only when it's unconstrained.
  ///
  /// The [maxWidth] and [maxHeight] arguments must not be null and must not be
  /// negative.
1093
  const LimitedBox({
1094 1095 1096 1097
    Key key,
    this.maxWidth: double.INFINITY,
    this.maxHeight: double.INFINITY,
    Widget child
1098 1099 1100
  }) : assert(maxWidth != null && maxWidth >= 0.0),
       assert(maxHeight != null && maxHeight >= 0.0),
       super(key: key, child: child);
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130

  /// The maximum width limit to apply in the absence of a maxWidth constraint.
  final double maxWidth;

  /// The maximum height limit to apply in the absence of a maxHeight constraint.
  final double maxHeight;

  @override
  RenderLimitedBox createRenderObject(BuildContext context) => new RenderLimitedBox(
    maxWidth: maxWidth,
    maxHeight: maxHeight
  );

  @override
  void updateRenderObject(BuildContext context, RenderLimitedBox renderObject) {
    renderObject
      ..maxWidth = maxWidth
      ..maxHeight = maxHeight;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    if (maxWidth != double.INFINITY)
      description.add('maxWidth: $maxWidth');
    if (maxHeight != double.INFINITY)
      description.add('maxHeight: $maxHeight');
  }
}

1131
/// A widget that imposes different constraints on its child than it gets
1132 1133 1134
/// from its parent, possibly allowing the child to overflow the parent.
///
/// See [RenderOverflowBox] for details.
1135
class OverflowBox extends SingleChildRenderObjectWidget {
1136
  /// Creates a widget that lets its child overflow itself.
1137
  const OverflowBox({
1138
    Key key,
Adam Barth's avatar
Adam Barth committed
1139
    this.alignment: FractionalOffset.center,
1140 1141 1142 1143 1144 1145
    this.minWidth,
    this.maxWidth,
    this.minHeight,
    this.maxHeight,
    Widget child
  }) : super(key: key, child: child);
1146

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
  /// How to align the child.
  ///
  /// The x and y values of the alignment control the horizontal and vertical
  /// alignment, respectively.  An x value of 0.0 means that the left edge of
  /// the child is aligned with the left edge of the parent whereas an x value
  /// of 1.0 means that the right edge of the child is aligned with the right
  /// edge of the parent. Other values interpolate (and extrapolate) linearly.
  /// For example, a value of 0.5 means that the center of the child is aligned
  /// with the center of the parent.
  final FractionalOffset alignment;

1158 1159
  /// The minimum width constraint to give the child. Set this to null (the
  /// default) to use the constraint from the parent instead.
1160
  final double minWidth;
1161 1162 1163

  /// The maximum width constraint to give the child. Set this to null (the
  /// default) to use the constraint from the parent instead.
1164
  final double maxWidth;
1165 1166 1167

  /// The minimum height constraint to give the child. Set this to null (the
  /// default) to use the constraint from the parent instead.
1168
  final double minHeight;
1169 1170 1171

  /// The maximum height constraint to give the child. Set this to null (the
  /// default) to use the constraint from the parent instead.
1172 1173
  final double maxHeight;

1174
  @override
1175 1176
  RenderConstrainedOverflowBox createRenderObject(BuildContext context) => new RenderConstrainedOverflowBox(
    alignment: alignment,
1177 1178 1179
    minWidth: minWidth,
    maxWidth: maxWidth,
    minHeight: minHeight,
1180
    maxHeight: maxHeight
1181 1182
  );

1183
  @override
1184
  void updateRenderObject(BuildContext context, RenderConstrainedOverflowBox renderObject) {
1185
    renderObject
1186
      ..alignment = alignment
1187 1188 1189
      ..minWidth = minWidth
      ..maxWidth = maxWidth
      ..minHeight = minHeight
1190
      ..maxHeight = maxHeight;
1191
  }
1192

1193
  @override
1194 1195
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
1196
    description.add('alignment: $alignment');
1197 1198 1199 1200 1201 1202 1203 1204 1205
    if (minWidth != null)
      description.add('minWidth: $minWidth');
    if (maxWidth != null)
      description.add('maxWidth: $maxWidth');
    if (minHeight != null)
      description.add('minHeight: $minHeight');
    if (maxHeight != null)
      description.add('maxHeight: $maxHeight');
  }
1206 1207
}

1208 1209
/// A widget that is a specific size but passes its original constraints
/// through to its child, which will probably overflow.
1210
class SizedOverflowBox extends SingleChildRenderObjectWidget {
1211 1212
  /// Creates a widget of a given size that lets its child overflow.
  ///
1213
  /// The [size] argument must not be null.
1214
  const SizedOverflowBox({
1215
    Key key,
1216
    @required this.size,
Adam Barth's avatar
Adam Barth committed
1217
    this.alignment: FractionalOffset.center,
1218
    Widget child
1219 1220 1221
  }) : assert(size != null),
       assert(alignment != null),
       super(key: key, child: child);
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232

  /// How to align the child.
  ///
  /// The x and y values of the alignment control the horizontal and vertical
  /// alignment, respectively.  An x value of 0.0 means that the left edge of
  /// the child is aligned with the left edge of the parent whereas an x value
  /// of 1.0 means that the right edge of the child is aligned with the right
  /// edge of the parent. Other values interpolate (and extrapolate) linearly.
  /// For example, a value of 0.5 means that the center of the child is aligned
  /// with the center of the parent.
  final FractionalOffset alignment;
1233

1234
  /// The size this widget should attempt to be.
1235 1236
  final Size size;

1237
  @override
1238 1239 1240 1241 1242 1243
  RenderSizedOverflowBox createRenderObject(BuildContext context) {
    return new RenderSizedOverflowBox(
      alignment: alignment,
      requestedSize: size
    );
  }
1244

1245
  @override
1246
  void updateRenderObject(BuildContext context, RenderSizedOverflowBox renderObject) {
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
    renderObject
      ..alignment = alignment
      ..requestedSize = size;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('alignment: $alignment');
    if (size != null)
      description.add('size: $size');
1258 1259 1260
  }
}

1261
/// A widget that lays the child out as if it was in the tree, but without painting anything,
1262 1263
/// without making the child available for hit testing, and without taking any
/// room in the parent.
1264
class Offstage extends SingleChildRenderObjectWidget {
1265
  /// Creates a widget that visually hides its child.
1266 1267 1268
  const Offstage({ Key key, this.offstage: true, Widget child })
    : assert(offstage != null),
      super(key: key, child: child);
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279

  /// Whether the child is hidden from the rest of the tree.
  ///
  /// If true, the child is laid out as if it was in the tree, but without
  /// painting anything, without making the child available for hit testing, and
  /// without taking any room in the parent.
  ///
  /// If false, the child is included in the tree as normal.
  final bool offstage;

  @override
1280
  RenderOffstage createRenderObject(BuildContext context) => new RenderOffstage(offstage: offstage);
Hixie's avatar
Hixie committed
1281

1282
  @override
1283
  void updateRenderObject(BuildContext context, RenderOffstage renderObject) {
1284 1285 1286 1287 1288 1289 1290 1291
    renderObject.offstage = offstage;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('offstage: $offstage');
  }
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307

  @override
  _OffstageElement createElement() => new _OffstageElement(this);
}

class _OffstageElement extends SingleChildRenderObjectElement {
  _OffstageElement(Offstage widget) : super(widget);

  @override
  Offstage get widget => super.widget;

  @override
  void visitChildrenForSemantics(ElementVisitor visitor) {
    if (!widget.offstage)
      super.visitChildrenForSemantics(visitor);
  }
Hixie's avatar
Hixie committed
1308 1309
}

1310
/// A widget that attempts to size the child to a specific aspect ratio.
1311
///
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
/// The widget first tries the largest width permited by the layout
/// constraints. The height of the widget is determined by applying the
/// given aspect ratio to the width, expressed as a ratio of width to height.
///
/// For example, a 16:9 width:height aspect ratio would have a value of
/// 16.0/9.0. If the maximum width is infinite, the initial width is determined
/// by applying the aspect ratio to the maximum height.
///
/// Now consider a second example, this time with an aspect ratio of 2.0 and
/// layout constraints that require the width to be between 0.0 and 100.0 and
/// the height to be between 0.0 and 100.0. We'll select a width of 100.0 (the
/// biggest allowed) and a height of 50.0 (to match the aspect ratio).
///
/// In that same situation, if the aspect ratio is 0.5, we'll also select a
/// width of 100.0 (still the biggest allowed) and we'll attempt to use a height
/// of 200.0. Unfortunately, that violates the constraints because the child can
/// be at most 100.0 pixels tall. The widget will then take that value
/// and apply the aspect ratio again to obtain a width of 50.0. That width is
/// permitted by the constraints and the child receives a width of 50.0 and a
/// height of 100.0. If the width were not permitted, the widget would
/// continue iterating through the constraints. If the widget does not
/// find a feasible size after consulting each constraint, the widget
/// will eventually select a size for the child that meets the layout
/// constraints but fails to meet the aspect ratio constraints.
1336
class AspectRatio extends SingleChildRenderObjectWidget {
1337 1338 1339
  /// Creates a widget with a specific aspect ratio.
  ///
  /// The [aspectRatio] argument must not be null.
1340
  const AspectRatio({
1341 1342 1343
    Key key,
    @required this.aspectRatio,
    Widget child
1344 1345
  }) : assert(aspectRatio != null),
       super(key: key, child: child);
1346

1347
  /// The aspect ratio to attempt to use.
1348 1349 1350
  ///
  /// The aspect ratio is expressed as a ratio of width to height. For example,
  /// a 16:9 width:height aspect ratio would have a value of 16.0/9.0.
1351 1352
  final double aspectRatio;

1353
  @override
1354
  RenderAspectRatio createRenderObject(BuildContext context) => new RenderAspectRatio(aspectRatio: aspectRatio);
1355

1356
  @override
1357
  void updateRenderObject(BuildContext context, RenderAspectRatio renderObject) {
1358
    renderObject.aspectRatio = aspectRatio;
1359
  }
1360

1361
  @override
1362 1363 1364 1365
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('aspectRatio: $aspectRatio');
  }
1366 1367
}

1368
/// A widget that sizes its child to the child's intrinsic width.
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
///
/// Sizes its child's width to the child's maximum intrinsic width. If
/// [stepWidth] is non-null, the child's width will be snapped to a multiple of
/// the [stepWidth]. Similarly, if [stepHeight] is non-null, the child's height
/// will be snapped to a multiple of the [stepHeight].
///
/// This class is useful, for example, when unlimited width is available and
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable width.
///
/// This class is relatively expensive. Avoid using it where possible.
1380
class IntrinsicWidth extends SingleChildRenderObjectWidget {
1381 1382 1383
  /// Creates a widget that sizes its child to the child's intrinsic width.
  ///
  /// This class is relatively expensive. Avoid using it where possible.
1384
  const IntrinsicWidth({ Key key, this.stepWidth, this.stepHeight, Widget child })
1385 1386
    : super(key: key, child: child);

1387
  /// If non-null, force the child's width to be a multiple of this value.
1388
  final double stepWidth;
1389 1390

  /// If non-null, force the child's height to be a multiple of this value.
1391 1392
  final double stepHeight;

1393
  @override
1394
  RenderIntrinsicWidth createRenderObject(BuildContext context) => new RenderIntrinsicWidth(stepWidth: stepWidth, stepHeight: stepHeight);
1395

1396
  @override
1397
  void updateRenderObject(BuildContext context, RenderIntrinsicWidth renderObject) {
1398 1399 1400
    renderObject
      ..stepWidth = stepWidth
      ..stepHeight = stepHeight;
1401 1402 1403
  }
}

1404
/// A widget that sizes its child to the child's intrinsic height.
1405 1406 1407 1408 1409 1410
///
/// This class is useful, for example, when unlimited height is available and
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable height.
///
/// This class is relatively expensive. Avoid using it where possible.
1411
class IntrinsicHeight extends SingleChildRenderObjectWidget {
1412 1413 1414
  /// Creates a widget that sizes its child to the child's intrinsic height.
  ///
  /// This class is relatively expensive. Avoid using it where possible.
1415
  const IntrinsicHeight({ Key key, Widget child }) : super(key: key, child: child);
1416 1417

  @override
1418
  RenderIntrinsicHeight createRenderObject(BuildContext context) => new RenderIntrinsicHeight();
Hixie's avatar
Hixie committed
1419 1420
}

1421 1422 1423
/// A widget that positions its child according to the child's baseline.
///
/// This widget shifts the child down such that the child's baseline (or the
1424 1425 1426 1427 1428
/// bottom of the child, if the child has no baseline) is [baseline]
/// logical pixels below the top of this box, then sizes this box to
/// contain the child. If [baseline] is less than the distance from
/// the top of the child to the baseline of the child, then the child
/// is top-aligned instead.
1429
class Baseline extends SingleChildRenderObjectWidget {
1430
  /// Creates a widget that positions its child according to the child's baseline.
1431
  ///
1432
  /// The [baseline] and [baselineType] arguments must not be null.
1433
  const Baseline({
1434 1435 1436 1437
    Key key,
    @required this.baseline,
    @required this.baselineType,
    Widget child
1438 1439 1440
  }) : assert(baseline != null),
       assert(baselineType != null),
       super(key: key, child: child);
1441

1442 1443 1444 1445 1446
  /// The number of logical pixels from the top of this box at which to position
  /// the child's baseline.
  final double baseline;

  /// The type of baseline to use for positioning the child.
1447 1448
  final TextBaseline baselineType;

1449
  @override
1450
  RenderBaseline createRenderObject(BuildContext context) => new RenderBaseline(baseline: baseline, baselineType: baselineType);
1451

1452
  @override
1453
  void updateRenderObject(BuildContext context, RenderBaseline renderObject) {
1454 1455 1456
    renderObject
      ..baseline = baseline
      ..baselineType = baselineType;
1457 1458 1459 1460
  }
}


Ian Hickson's avatar
Ian Hickson committed
1461 1462
// SLIVERS

1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482
/// A sliver that contains a single box widget.
///
/// Slivers are special-purpose widgets that can be combined using a
/// [CustomScrollView] to create custom scroll effects. A [SliverToBoxAdapter]
/// is a basic sliver that creates a bridge back to one of the usual box-based
/// widgets.
///
/// Rather than using multiple [SliverToBoxAdapter] widgets to display multiple
/// box widgets in a [CustomScrollView], consider using [SliverList],
/// [SliverFixedExtentList], or [SliverGrid], which are more efficient because
/// they instantiate only those children that are actually visible through the
/// scroll view's viewport.
///
/// See also:
///
///  * [CustomScrollView], which displays a scrollable list of slivers.
///  * [SliverList], which displays multiple box widgets in a linear array.
///  * [SliverFixedExtentList], which displays multiple box widgets with the
///    same main-axis extent in a linear array.
///  * [SliverGrid], which displays multiple box widgets in arbitrary positions.
Ian Hickson's avatar
Ian Hickson committed
1483
class SliverToBoxAdapter extends SingleChildRenderObjectWidget {
1484
  /// Creates a sliver that contains a single box widget.
1485
  const SliverToBoxAdapter({
Ian Hickson's avatar
Ian Hickson committed
1486 1487 1488 1489 1490 1491 1492 1493
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderSliverToBoxAdapter createRenderObject(BuildContext context) => new RenderSliverToBoxAdapter();
}

1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
/// A sliver that applies padding on each side of another sliver.
///
/// Slivers are special-purpose widgets that can be combined using a
/// [CustomScrollView] to create custom scroll effects. A [SliverPadding]
/// is a basic sliver that insets another sliver by applying padding on each
/// side.
///
/// Applying padding to anything but the most mundane sliver is likely to have
/// undesired effects. For example, wrapping a
/// [SliverPinnedPersistentHeader] will cause the app bar to overlap
/// earlier slivers (contrary to the normal behavior of pinned app bars), and
/// while the app bar is pinned, the padding will scroll away.
///
/// See also:
///
///  * [CustomScrollView], which displays a scrollable list of slivers.
Ian Hickson's avatar
Ian Hickson committed
1510
class SliverPadding extends SingleChildRenderObjectWidget {
1511 1512 1513
  /// Creates a sliver that applies padding on each side of another sliver.
  ///
  /// The [padding] argument must not be null.
1514
  const SliverPadding({
Ian Hickson's avatar
Ian Hickson committed
1515 1516
    Key key,
    @required this.padding,
1517
    Widget sliver,
1518 1519
  }) : assert(padding != null),
       super(key: key, child: sliver);
Ian Hickson's avatar
Ian Hickson committed
1520

1521
  /// The amount of space by which to inset the child sliver.
Ian Hickson's avatar
Ian Hickson committed
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
  final EdgeInsets padding;

  @override
  RenderSliverPadding createRenderObject(BuildContext context) => new RenderSliverPadding(padding: padding);

  @override
  void updateRenderObject(BuildContext context, RenderSliverPadding renderObject) {
    renderObject.padding = padding;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('padding: $padding');
  }
}


1540 1541
// LAYOUT NODES

1542 1543
/// A widget that arranges its children sequentially along a given axis, forcing
/// them to the dimension of the parent in the other axis.
1544
///
1545
/// This widget is rarely used directly. Instead, consider using [ListView],
1546 1547 1548
/// which combines a similar layout algorithm with scrolling behavior, or
/// [Column], which gives you more flexible control over the layout of a
/// vertical set of boxes.
1549
///
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
/// See also:
///
///  * [RenderListBody], which implements this layout algorithm and the
///    documentation for which describes some of its subtleties.
///  * [SingleChildScrollView], which is sometimes used with [ListBody] to
///    make the contents scrollable.
///  * [Column] and [Row], which implement a more elaborate version of
///    this layout algorithm (at the cost of being slightly less efficient).
///  * [ListView], which implements an efficient scrolling version of this
///    layout algorithm.
class ListBody extends MultiChildRenderObjectWidget {
  /// Creates a layout widget that arranges its children sequentially along a
  /// given axis.
1563 1564
  ///
  /// By default, the [mainAxis] is [Axis.vertical].
1565
  ListBody({
1566
    Key key,
1567
    this.mainAxis: Axis.vertical,
1568
    List<Widget> children: const <Widget>[],
1569 1570
  }) : assert(mainAxis != null),
       super(key: key, children: children);
1571

1572
  /// The direction to use as the main axis.
1573
  final Axis mainAxis;
1574

1575
  @override
1576
  RenderListBody createRenderObject(BuildContext context) => new RenderListBody(mainAxis: mainAxis);
1577

1578
  @override
1579
  void updateRenderObject(BuildContext context, RenderListBody renderObject) {
1580
    renderObject.mainAxis = mainAxis;
1581
  }
1582 1583
}

1584
/// A widget that uses the stack layout algorithm for its children.
Adam Barth's avatar
Adam Barth committed
1585
///
1586 1587 1588
/// This class is useful if you want to overlap several children in a simple
/// way, for example having some text and an image, overlaid with a gradient and
/// a button attached to the bottom.
1589
///
1590 1591 1592 1593 1594 1595 1596
/// Each child of a [Stack] widget is either _positioned_ or _non-positioned_.
/// Positioned children are those wrapped in a [Positioned] widget that has at
/// least one non-null property. The stack sizes itself to contain all the
/// non-positioned children, which are positioned according to [alignment]
/// (which defaults to the top-left corner). The positioned children are then
/// placed relative to the stack according to their top, right, bottom, and left
/// properties.
1597
///
1598 1599 1600 1601 1602 1603 1604
/// The stack paints its children in order. If you want to change the order in
/// which the children paint, you can rebuild the stack with the children in
/// the new order. If you reorder the children in this way, consider giving the
/// children non-null keys. These keys will cause the framework to move the
/// underlying objects for the children to their new locations rather than
/// recreate them at their new location.
///
1605 1606 1607 1608 1609 1610
/// For more details about the stack layout algorithm, see [RenderStack].
///
/// If you want to lay a number of children out in a particular pattern, or if
/// you want to make a custom layout manager, you probably want to use
/// [CustomMultiChildLayout] instead. In particular, when using a [Stack] you
/// can't position children relative to their size or the stack's own size.
Adam Barth's avatar
Adam Barth committed
1611 1612 1613
///
/// See also:
///
1614 1615
///  * [Align], which sizes itself based on its child's size and positions
///    the child according to a [FractionalOffset] value.
1616 1617 1618 1619 1620 1621
///  * [CustomSingleChildLayout], which uses a delegate to control the layout of
///    a single child.
///  * [CustomMultiChildLayout], which uses a delegate to position multiple
///    children.
///  * [Flow], which provides paint-time control of its children using transform
///    matrices.
1622
class Stack extends MultiChildRenderObjectWidget {
1623
  /// Creates a stack layout widget.
1624 1625 1626
  ///
  /// By default, the non-positioned children of the stack are aligned by their
  /// top left corners.
1627
  Stack({
Hans Muller's avatar
Hans Muller committed
1628
    Key key,
1629
    this.alignment: FractionalOffset.topLeft,
1630
    this.overflow: Overflow.clip,
1631
    List<Widget> children: const <Widget>[],
1632
  }) : super(key: key, children: children);
Hans Muller's avatar
Hans Muller committed
1633

Adam Barth's avatar
Adam Barth committed
1634
  /// How to align the non-positioned children in the stack.
1635 1636 1637 1638 1639
  ///
  /// The non-positioned children are placed relative to each other such that
  /// the points determined by [alignment] are co-located. For example, if the
  /// [alignment] is [FractionalOffset.topLeft], then the top left corner of
  /// each non-positioned child will be located at the same global coordinate.
1640
  final FractionalOffset alignment;
Hans Muller's avatar
Hans Muller committed
1641

1642 1643 1644 1645 1646 1647
  /// Whether overflowing children should be clipped. See [Overflow].
  ///
  /// Some children in a stack might overflow its box. When this flag is set to
  /// [Overflow.clipped], children cannot paint outside of the stack's box.
  final Overflow overflow;

1648
  @override
1649 1650 1651 1652 1653 1654
  RenderStack createRenderObject(BuildContext context) {
    return new RenderStack(
      alignment: alignment,
      overflow: overflow
    );
  }
Hans Muller's avatar
Hans Muller committed
1655

1656
  @override
1657
  void updateRenderObject(BuildContext context, RenderStack renderObject) {
1658 1659 1660
    renderObject
      ..alignment = alignment
      ..overflow = overflow;
Hans Muller's avatar
Hans Muller committed
1661 1662 1663
  }
}

1664
/// A [Stack] that shows a single child from a list of children.
1665
///
1666 1667 1668 1669
/// The displayed child is the one with the given [index]. The stack is
/// always as big as the largest child.
///
/// If value is null, then nothing is displayed.
1670 1671
///
/// For more details, see [Stack].
1672
class IndexedStack extends Stack {
1673
  /// Creates a [Stack] widget that paints a single child.
1674 1675
  ///
  /// The [index] argument must not be null.
1676
  IndexedStack({
Hans Muller's avatar
Hans Muller committed
1677
    Key key,
1678
    FractionalOffset alignment: FractionalOffset.topLeft,
1679
    this.index: 0,
1680
    List<Widget> children: const <Widget>[],
1681
  }) : super(key: key, alignment: alignment, children: children);
Hans Muller's avatar
Hans Muller committed
1682

Adam Barth's avatar
Adam Barth committed
1683
  /// The index of the child to show.
Hans Muller's avatar
Hans Muller committed
1684
  final int index;
Adam Barth's avatar
Adam Barth committed
1685

1686
  @override
1687
  RenderIndexedStack createRenderObject(BuildContext context) => new RenderIndexedStack(index: index, alignment: alignment);
Hans Muller's avatar
Hans Muller committed
1688

1689
  @override
1690
  void updateRenderObject(BuildContext context, RenderIndexedStack renderObject) {
1691 1692 1693
    renderObject
      ..index = index
      ..alignment = alignment;
Hans Muller's avatar
Hans Muller committed
1694
  }
1695 1696
}

1697
/// A widget that controls where a child of a [Stack] is positioned.
Adam Barth's avatar
Adam Barth committed
1698
///
1699 1700 1701 1702
/// A [Positioned] widget must be a descendant of a [Stack], and the path from
/// the [Positioned] widget to its enclosing [Stack] must contain only
/// [StatelessWidget]s or [StatefulWidget]s (not other kinds of widgets, like
/// [RenderObjectWidget]s).
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
///
/// If a widget is wrapped in a [Positioned], then it is a _positioned_ widget
/// in its [Stack]. If the [top] property is non-null, the top edge of this child
/// will be positioned [top] layout units from the top of the stack widget. The
/// [right], [bottom], and [left] properties work analogously.
///
/// If both the [top] and [bottom] properties are non-null, then the child will
/// be forced to have exactly the height required to satisfy both constraints.
/// Similarly, setting the [right] and [left] properties to non-null values will
/// force the child to have a particular width. Alternatively the [width] and
/// [height] properties can be used to give the dimensions, with one
/// corresponding position property (e.g. [top] and [height]).
1715
class Positioned extends ParentDataWidget<Stack> {
1716
  /// Creates a widget that controls where a child of a [Stack] is positioned.
Hixie's avatar
Hixie committed
1717 1718 1719 1720 1721
  ///
  /// Only two out of the three horizontal values ([left], [right],
  /// [width]), and only two out of the three vertical values ([top],
  /// [bottom], [height]), can be set. In each case, at least one of
  /// the three must be null.
1722
  const Positioned({
1723
    Key key,
1724
    this.left,
1725 1726 1727
    this.top,
    this.right,
    this.bottom,
1728
    this.width,
1729 1730
    this.height,
    @required Widget child
1731 1732 1733
  }) : assert(left == null || right == null || width == null),
       assert(top == null || bottom == null || height == null),
       super(key: key, child: child);
1734

Hixie's avatar
Hixie committed
1735 1736 1737 1738 1739
  /// Creates a Positioned object with the values from the given [Rect].
  ///
  /// This sets the [left], [top], [width], and [height] properties
  /// from the given [Rect]. The [right] and [bottom] properties are
  /// set to null.
1740 1741
  Positioned.fromRect({
    Key key,
1742 1743
    Rect rect,
    @required Widget child,
1744 1745 1746 1747
  }) : left = rect.left,
       top = rect.top,
       width = rect.width,
       height = rect.height,
1748 1749
       right = null,
       bottom = null,
1750
       super(key: key, child: child);
1751

1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767
  /// Creates a Positioned object with the values from the given [RelativeRect].
  ///
  /// This sets the [left], [top], [right], and [bottom] properties from the
  /// given [RelativeRect]. The [height] and [width] properties are set to null.
  Positioned.fromRelativeRect({
    Key key,
    RelativeRect rect,
    @required Widget child,
  }) : left = rect.left,
       top = rect.top,
       right = rect.right,
       bottom = rect.bottom,
       width = null,
       height = null,
       super(key: key, child: child);

1768 1769
  /// Creates a Positioned object with [left], [top], [right], and [bottom] set
  /// to 0.0 unless a value for them is passed.
1770
  Positioned.fill({
1771 1772 1773 1774
    Key key,
    this.left: 0.0,
    this.top: 0.0,
    this.right: 0.0,
1775 1776
    this.bottom: 0.0,
    @required Widget child,
1777 1778 1779 1780
  }) : width = null,
       height = null,
       super(key: key, child: child);

Hixie's avatar
Hixie committed
1781 1782 1783 1784
  /// The distance that the child's left edge is inset from the left of the stack.
  ///
  /// Only two out of the three horizontal values ([left], [right], [width]) can be
  /// set. The third must be null.
1785 1786
  final double left;

Hixie's avatar
Hixie committed
1787 1788 1789 1790
  /// The distance that the child's top edge is inset from the top of the stack.
  ///
  /// Only two out of the three vertical values ([top], [bottom], [height]) can be
  /// set. The third must be null.
1791
  final double top;
Adam Barth's avatar
Adam Barth committed
1792

Hixie's avatar
Hixie committed
1793 1794 1795 1796
  /// The distance that the child's right edge is inset from the right of the stack.
  ///
  /// Only two out of the three horizontal values ([left], [right], [width]) can be
  /// set. The third must be null.
1797
  final double right;
Adam Barth's avatar
Adam Barth committed
1798

Hixie's avatar
Hixie committed
1799 1800 1801 1802
  /// The distance that the child's bottom edge is inset from the bottom of the stack.
  ///
  /// Only two out of the three vertical values ([top], [bottom], [height]) can be
  /// set. The third must be null.
1803
  final double bottom;
Adam Barth's avatar
Adam Barth committed
1804 1805 1806

  /// The child's width.
  ///
Hixie's avatar
Hixie committed
1807
  /// Only two out of the three horizontal values ([left], [right], [width]) can be
1808
  /// set. The third must be null.
1809
  final double width;
Adam Barth's avatar
Adam Barth committed
1810 1811 1812

  /// The child's height.
  ///
Hixie's avatar
Hixie committed
1813
  /// Only two out of the three vertical values ([top], [bottom], [height]) can be
1814
  /// set. The third must be null.
1815 1816
  final double height;

1817
  @override
1818 1819 1820
  void applyParentData(RenderObject renderObject) {
    assert(renderObject.parentData is StackParentData);
    final StackParentData parentData = renderObject.parentData;
1821
    bool needsLayout = false;
1822

1823 1824 1825 1826 1827
    if (parentData.left != left) {
      parentData.left = left;
      needsLayout = true;
    }

1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
    if (parentData.top != top) {
      parentData.top = top;
      needsLayout = true;
    }

    if (parentData.right != right) {
      parentData.right = right;
      needsLayout = true;
    }

    if (parentData.bottom != bottom) {
      parentData.bottom = bottom;
      needsLayout = true;
    }

1843 1844 1845 1846 1847 1848 1849 1850 1851 1852
    if (parentData.width != width) {
      parentData.width = width;
      needsLayout = true;
    }

    if (parentData.height != height) {
      parentData.height = height;
      needsLayout = true;
    }

1853
    if (needsLayout) {
1854
      final AbstractNode targetParent = renderObject.parent;
1855 1856 1857
      if (targetParent is RenderObject)
        targetParent.markNeedsLayout();
    }
1858
  }
1859

1860
  @override
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    if (left != null)
      description.add('left: $left');
    if (top != null)
      description.add('top: $top');
    if (right != null)
      description.add('right: $right');
    if (bottom != null)
      description.add('bottom: $bottom');
1871 1872 1873 1874
    if (width != null)
      description.add('width: $width');
    if (height != null)
      description.add('height: $height');
1875
  }
1876 1877
}

1878
/// A widget that displays its children in a one-dimensional array.
Adam Barth's avatar
Adam Barth committed
1879
///
1880 1881 1882
/// The [Flex] widget allows you to control the axis along which the children are
/// placed (horizontal or vertical). This is referred to as the _main axis_. If
/// you know the main axis in advance, then consider using a [Row] (if it's
1883
/// horizontal) or [Column] (if it's vertical) instead, because that will be less
1884 1885
/// verbose.
///
1886 1887
/// To cause a child to expand to fill the available vertical space, wrap the
/// child in an [Expanded] widget.
1888 1889 1890 1891
///
/// The [Flex] widget does not scroll (and in general it is considered an error
/// to have more children in a [Flex] than will fit in the available room). If
/// you have some widgets and want them to be able to scroll if there is
1892
/// insufficient room, consider using a [ScrollList].
1893 1894 1895
///
/// If you only have one child, then rather than using [Flex], [Row], or
/// [Column], consider using [Align] or [Center] to position the child.
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
///
/// ## Layout algorithm
///
/// Layout for a [Flex] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
///    [Expanded]) with unbounded main axis constraints and the incoming
///    cross axis constraints. If the [crossAxisAlignment] is
///    [CrossAxisAlignment.stretch], instead use tight cross axis constraints
///    that match the incoming max extent in the cross axis.
/// 2. Divide the remaining main axis space among the children with non-zero
///    flex factors (e.g., those that are [Expanded]) according to their flex
///    factor. For example, a child with a flex factor of 2.0 will receive twice
///    the amount of main axis space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same cross axis
///    constraints as in step 1, but instead of using unbounded main axis
///    constraints, use max axis constraints based on the amount of space
///    allocated in step 2. Children with [Flexible.fit] properties that are
///    [FlexFit.tight] are given tight constraints (i.e., forced to fill the
///    allocated space), and children with [Flexible.fit] properties that are
///    [FlexFit.loose] are given loose constraints (i.e., not forced to fill the
///    allocated space).
/// 4. The cross axis extent of the [Flex] is the maximum cross axis extent of
///    the children (which will always satisfy the incoming constraints).
/// 5. The main axis extent of the [Flex] is determined by the [mainAxisSize]
///    property. If the [mainAxisSize] property is [MainAxisSize.max], then the
///    main axis extent of the [Flex] is the max extent of the incoming main
///    axis constraints. If the [mainAxisSize] property is [MainAxisSize.min],
///    then the main axis extent of the [Flex] is the sum of the main axis
///    extents of the children (subject to the incoming constraints).
/// 6. Determine the position for each child according to the
///    [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
///    [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any main axis
///    space that has not been allocated to children is divided evenly and
///    placed between the children.
1931
class Flex extends MultiChildRenderObjectWidget {
1932 1933
  /// Creates a flex layout.
  ///
1934 1935
  /// The [direction] is required.
  ///
1936 1937 1938
  /// The [direction], [mainAxisAlignment], and [crossAxisAlignment] arguments
  /// must not be null. If [crossAxisAlignment] is
  /// [CrossAxisAlignment.baseline], then [textBaseline] must not be null.
1939
  Flex({
1940
    Key key,
1941
    @required this.direction,
1942
    this.mainAxisAlignment: MainAxisAlignment.start,
1943
    this.mainAxisSize: MainAxisSize.max,
1944
    this.crossAxisAlignment: CrossAxisAlignment.center,
1945
    this.textBaseline,
1946
    List<Widget> children: const <Widget>[],
1947 1948 1949 1950 1951 1952
  }) : assert(direction != null),
       assert(mainAxisAlignment != null),
       assert(mainAxisSize != null),
       assert(crossAxisAlignment != null),
       super(key: key, children: children) {
    assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null); // https://github.com/dart-lang/sdk/issues/29278
1953
  }
1954

1955
  /// The direction to use as the main axis.
1956 1957 1958 1959 1960
  ///
  /// If you know the axis in advance, then consider using a [Row] (if it's
  /// horizontal) or [Column] (if it's vertical) instead of a [Flex], since that
  /// will be less verbose. (For [Row] and [Column] this property is fixed to
  /// the appropriate axis.)
1961
  final Axis direction;
1962 1963

  /// How the children should be placed along the main axis.
1964 1965 1966 1967
  ///
  /// For example, [MainAxisAlignment.start], the default, places the children
  /// at the start (i.e., the left for a [Row] or the top for a [Column]) of the
  /// main axis.
1968
  final MainAxisAlignment mainAxisAlignment;
1969

1970 1971 1972 1973
  /// How much space space should be occupied in the main axis.
  ///
  /// After allocating space to children, there might be some remaining free
  /// space. This value controls whether to maximize or minimize the amount of
1974
  /// free space, subject to the incoming layout constraints.
1975 1976 1977 1978 1979
  ///
  /// If some children have a non-zero flex factors (and none have a fit of
  /// [FlexFit.loose]), they will expand to consume all the available space and
  /// there will be no remaining free space to maximize or minimize, making this
  /// value irrelevant to the final layout.
1980 1981
  final MainAxisSize mainAxisSize;

1982
  /// How the children should be placed along the cross axis.
1983 1984 1985
  ///
  /// For example, [CrossAxisAlignment.center], the default, centers the
  /// children in the cross axis (e.g., horizontally for a [Column]).
1986
  final CrossAxisAlignment crossAxisAlignment;
1987 1988

  /// If aligning items according to their baseline, which baseline to use.
1989
  final TextBaseline textBaseline;
1990

1991
  @override
1992 1993 1994 1995 1996 1997 1998 1999 2000
  RenderFlex createRenderObject(BuildContext context) {
    return new RenderFlex(
      direction: direction,
      mainAxisAlignment: mainAxisAlignment,
      mainAxisSize: mainAxisSize,
      crossAxisAlignment: crossAxisAlignment,
      textBaseline: textBaseline
    );
  }
2001

2002
  @override
2003
  void updateRenderObject(BuildContext context, covariant RenderFlex renderObject) {
2004 2005
    renderObject
      ..direction = direction
2006
      ..mainAxisAlignment = mainAxisAlignment
2007
      ..mainAxisSize = mainAxisSize
2008
      ..crossAxisAlignment = crossAxisAlignment
2009
      ..textBaseline = textBaseline;
2010 2011 2012
  }
}

2013
/// A widget that displays its children in a horizontal array.
2014
///
2015 2016
/// To cause a child to expand to fill the available horizontal space, wrap the
/// child in an [Expanded] widget.
2017 2018 2019 2020
///
/// The [Row] widget does not scroll (and in general it is considered an error
/// to have more children in a [Row] than will fit in the available room). If
/// you have a line of widgets and want them to be able to scroll if there is
2021
/// insufficient room, consider using a [ScrollList].
2022 2023
///
/// For a vertical variant, see [Column].
2024 2025 2026
///
/// If you only have one child, then consider using [Align] or [Center] to
/// position the child.
2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059
///
/// ## Layout algorithm
///
/// Layout for a [Row] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
///    [Expanded]) with unbounded horizontal constraints and the incoming
///    vertical constraints. If the [crossAxisAlignment] is
///    [CrossAxisAlignment.stretch], instead use tight vertical constraints that
///    match the incoming max height.
/// 2. Divide the remaining horizontal space among the children with non-zero
///    flex factors (e.g., those that are [Expanded]) according to their flex
///    factor. For example, a child with a flex factor of 2.0 will receive twice
///    the amount of horizontal space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same vertical constraints
///    as in step 1, but instead of using unbounded horizontal constraints, use
///    horizontal constraints based on the amount of space allocated in step 2.
///    Children with [Flexible.fit] properties that are [FlexFit.tight] are
///    given tight constraints (i.e., forced to fill the allocated space), and
///    children with [Flexible.fit] properties that are [FlexFit.loose] are
///    given loose constraints (i.e., not forced to fill the allocated space).
/// 4. The height of the [Row] is the maximum height of the children (which will
///    always satisfy the incoming vertical constraints).
/// 5. The width of the [Row] is determined by the [mainAxisSize] property. If
///    the [mainAxisSize] property is [MainAxisSize.max], then the width of the
///    [Row] is the max width of the incoming constraints. If the [mainAxisSize]
///    property is [MainAxisSize.min], then the width of the [Row] is the sum
///    of widths of the children (subject to the incoming constraints).
/// 6. Determine the position for each child according to the
///    [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
///    [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any horizontal
///    space that has not been allocated to children is divided evenly and
///    placed between the children.
2060
class Row extends Flex {
2061 2062
  /// Creates a horizontal array of children.
  ///
2063 2064 2065
  /// The [direction], [mainAxisAlignment], [mainAxisSize], and
  /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment]
  /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null.
2066
  Row({
2067
    Key key,
2068
    MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
2069
    MainAxisSize mainAxisSize: MainAxisSize.max,
2070
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
2071
    TextBaseline textBaseline,
2072
    List<Widget> children: const <Widget>[],
2073 2074 2075
  }) : super(
    children: children,
    key: key,
2076
    direction: Axis.horizontal,
2077
    mainAxisAlignment: mainAxisAlignment,
2078
    mainAxisSize: mainAxisSize,
2079
    crossAxisAlignment: crossAxisAlignment,
2080 2081
    textBaseline: textBaseline
  );
2082 2083
}

2084
/// A widget that displays its children in a vertical array.
2085
///
2086 2087
/// To cause a child to expand to fill the available vertical space, wrap the
/// child in an [Expanded] widget.
2088
///
2089 2090 2091
/// The [Column] widget does not scroll (and in general it is considered an error
/// to have more children in a [Column] than will fit in the available room). If
/// you have a line of widgets and want them to be able to scroll if there is
2092
/// insufficient room, consider using a [ScrollList].
2093 2094
///
/// For a horizontal variant, see [Row].
2095 2096 2097
///
/// If you only have one child, then consider using [Align] or [Center] to
/// position the child.
2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
///
/// ## Layout algorithm
///
/// Layout for a [Column] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
///    [Expanded]) with unbounded vertical constraints and the incoming
///    horizontal constraints. If the [crossAxisAlignment] is
///    [CrossAxisAlignment.stretch], instead use tight horizontal constraints
///    that match the incoming max width.
/// 2. Divide the remaining vertical space among the children with non-zero
///    flex factors (e.g., those that are [Expanded]) according to their flex
///    factor. For example, a child with a flex factor of 2.0 will receive twice
///    the amount of vertical space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same horizontal
///    constraints as in step 1, but instead of using unbounded vertical
///    constraints, use vertical constraints based on the amount of space
///    allocated in step 2. Children with [Flexible.fit] properties that are
///    [FlexFit.tight] are given tight constraints (i.e., forced to fill the
///    allocated space), and children with [Flexible.fit] properties that are
///    [FlexFit.loose] are given loose constraints (i.e., not forced to fill the
///    allocated space).
/// 4. The width of the [Column] is the maximum width of the children (which
///    will always satisfy the incoming horizontal constraints).
/// 5. The height of the [Column] is determined by the [mainAxisSize] property.
///    If the [mainAxisSize] property is [MainAxisSize.max], then the height of
///    the [Column] is the max height of the incoming constraints. If the
///    [mainAxisSize] property is [MainAxisSize.min], then the height of the
///    [Column] is the sum of heights of the children (subject to the incoming
///    constraints).
/// 6. Determine the position for each child according to the
///    [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
///    [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any vertical
///    space that has not been allocated to children is divided evenly and
///    placed between the children.
2133
class Column extends Flex {
2134 2135
  /// Creates a vertical array of children.
  ///
2136 2137 2138
  /// The [direction], [mainAxisAlignment], [mainAxisSize], and
  /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment]
  /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null.
2139
  Column({
2140
    Key key,
2141
    MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
2142
    MainAxisSize mainAxisSize: MainAxisSize.max,
2143
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
2144
    TextBaseline textBaseline,
2145
    List<Widget> children: const <Widget>[],
2146 2147 2148
  }) : super(
    children: children,
    key: key,
2149
    direction: Axis.vertical,
2150
    mainAxisAlignment: mainAxisAlignment,
2151
    mainAxisSize: mainAxisSize,
2152
    crossAxisAlignment: crossAxisAlignment,
2153 2154
    textBaseline: textBaseline
  );
2155 2156
}

2157
/// A widget that controls how a child of a [Row], [Column], or [Flex] flexes.
Adam Barth's avatar
Adam Barth committed
2158
///
2159 2160 2161 2162 2163 2164
/// Using a [Flexible] widget gives a child of a [Row], [Column], or [Flex]
/// the flexibility to expand to fill the available space in the main axis
/// (e.g., horizontally for a [Row] or vertically for a [Column]), but, unlike
/// [Expanded], [Flexible] does not require the child to fill the available
/// space.
///
2165 2166 2167 2168
/// A [Flexible] widget must be a descendant of a [Row], [Column], or [Flex],
/// and the path from the [Flexible] widget to its enclosing [Row], [Column], or
/// [Flex] must contain only [StatelessWidget]s or [StatefulWidget]s (not other
/// kinds of widgets, like [RenderObjectWidget]s).
2169 2170 2171 2172
///
/// See also:
///
///  * [Expanded], which forces the child to expand to fill the available space.
2173
class Flexible extends ParentDataWidget<Flex> {
2174 2175
  /// Creates a widget that controls how a child of a [Row], [Column], or [Flex]
  /// flexes.
2176
  const Flexible({
2177 2178
    Key key,
    this.flex: 1,
2179
    this.fit: FlexFit.loose,
2180
    @required Widget child,
2181
  }) : super(key: key, child: child);
2182

Adam Barth's avatar
Adam Barth committed
2183 2184
  /// The flex factor to use for this child
  ///
Adam Barth's avatar
Adam Barth committed
2185 2186 2187 2188
  /// If null or zero, the child is inflexible and determines its own size. If
  /// non-zero, the amount of space the child's can occupy in the main axis is
  /// determined by dividing the free space (after placing the inflexible
  /// children) according to the flex factors of the flexible children.
2189 2190
  final int flex;

Adam Barth's avatar
Adam Barth committed
2191 2192 2193 2194 2195 2196 2197 2198 2199
  /// How a flexible child is inscribed into the available space.
  ///
  /// If [flex] is non-zero, the [fit] determines whether the child fills the
  /// space the parent makes available during layout. If the fit is
  /// [FlexFit.tight], the child is required to fill the available space. If the
  /// fit is [FlexFit.loose], the child can be at most as large as the available
  /// space (but is allowed to be smaller).
  final FlexFit fit;

2200
  @override
2201 2202 2203
  void applyParentData(RenderObject renderObject) {
    assert(renderObject.parentData is FlexParentData);
    final FlexParentData parentData = renderObject.parentData;
Adam Barth's avatar
Adam Barth committed
2204 2205
    bool needsLayout = false;

2206 2207
    if (parentData.flex != flex) {
      parentData.flex = flex;
Adam Barth's avatar
Adam Barth committed
2208 2209 2210 2211 2212 2213 2214 2215 2216
      needsLayout = true;
    }

    if (parentData.fit != fit) {
      parentData.fit = fit;
      needsLayout = true;
    }

    if (needsLayout) {
2217
      final AbstractNode targetParent = renderObject.parent;
2218 2219
      if (targetParent is RenderObject)
        targetParent.markNeedsLayout();
2220 2221
    }
  }
2222

2223
  @override
2224 2225 2226 2227
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('flex: $flex');
  }
2228 2229
}

2230 2231
/// A widget that expands a child of a [Row], [Column], or [Flex].
///
2232
/// Using an [Expanded] widget makes a child of a [Row], [Column], or [Flex]
2233 2234 2235 2236 2237
/// expand to fill the available space in the main axis (e.g., horizontally for
/// a [Row] or vertically for a [Column]). If multiple children are expanded,
/// the available space is divided amoung them according to the [flex] factor.
///
/// An [Expanded] widget must be a descendant of a [Row], [Column], or [Flex],
2238
/// and the path from the [Expanded] widget to its enclosing [Row], [Column], or
2239 2240
/// [Flex] must contain only [StatelessWidget]s or [StatefulWidget]s (not other
/// kinds of widgets, like [RenderObjectWidget]s).
2241 2242 2243 2244
///
/// See also:
///
///  * [Flexible], which does not force the child to fill the available space.
2245 2246 2247
class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// expand to fill the available space in the main axis.
2248
  const Expanded({
2249 2250 2251
    Key key,
    int flex: 1,
    @required Widget child,
2252
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
2253 2254
}

Adam Barth's avatar
Adam Barth committed
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370
class Wrap extends MultiChildRenderObjectWidget {
  Wrap({
    Key key,
    this.direction: Axis.horizontal,
    this.alignment: WrapAlignment.start,
    this.spacing: 0.0,
    this.runAlignment: WrapAlignment.start,
    this.runSpacing: 0.0,
    this.crossAxisAlignment: WrapCrossAlignment.start,
    List<Widget> children: const <Widget>[],
  }) : super(key: key, children: children);

  /// The direction to use as the main axis.
  ///
  /// For example, if [direction] is [Axis.horizontal], the default, the
  /// children are placed adjacent to one another in a horizontal run until the
  /// available horizontal space is consumed, at which point a subsequent
  /// children are placed in a new run vertically adjacent to the previous run.
  final Axis direction;

  /// How the children within a run should be places in the main axis.
  ///
  /// For example, if [alignment] is [WrapAlignment.center], the children in
  /// each run are grouped togeter in the center of their run in the main axis.
  ///
  /// Defaults to [WrapAlignment.start].
  ///
  /// See also:
  ///
  ///  * [runAlignment], which controls how the runs are placed relative to each
  ///    other in the cross axis.
  ///  * [crossAxisAlignment], which controls how the children within each run
  ///    are placed relative to each other in the cross axis.
  final WrapAlignment alignment;

  /// How much space to place between children in a run in the main axis.
  ///
  /// For example, if [spacing] is 10.0, the children will be spaced at least
  /// 10.0 logical pixels apart in the main axis.
  ///
  /// If there is additional free space in a run (e.g., because the wrap has a
  /// minimum size that is not filled or because some runs are longer than
  /// others), the additional free space will be allocated according to the
  /// [alignment].
  ///
  /// Defaults to 0.0.
  final double spacing;

  /// How the runs themselves should be placed in the cross axis.
  ///
  /// For example, if [runAlignment] is [WrapAlignment.center], the runs are
  /// grouped togeter in the center of the overall [Wrap] in the cross axis.
  ///
  /// Defaults to [WrapAlignment.start].
  ///
  /// See also:
  ///
  ///  * [alignment], which controls how the children within each run are placed
  ///    relative to each other in the main axis.
  ///  * [crossAxisAlignment], which controls how the children within each run
  ///    are placed relative to each other in the cross axis.
  final WrapAlignment runAlignment;

  /// How much space to place between the runs themselves in the cross axis.
  ///
  /// For example, if [runSpacing] is 10.0, the runs will be spaced at least
  /// 10.0 logical pixels apart in the cross axis.
  ///
  /// If there is additional free space in the overall [Wrap] (e.g., because
  /// the wrap has a minimum size that is not filled), the additional free space
  /// will be allocated according to the [runAlignment].
  ///
  /// Defaults to 0.0.
  final double runSpacing;

  /// How the children within a run should be aligned relative to each other in
  /// the cross axis.
  ///
  /// For example, if this is set to [WrapCrossAlignment.end], and the
  /// [direction] is [WrapDirection.horizontal], then the children within each
  /// run will have their bottom edges aligned to the bottom edge of the run.
  ///
  /// Defaults to [WrapCrossAlignment.start].
  ///
  /// See also:
  ///
  ///  * [alignment], which controls how the children within each run are placed
  ///    relative to each other in the main axis.
  ///  * [runAlignment], which controls how the runs are placed relative to each
  ///    other in the cross axis.
  final WrapCrossAlignment crossAxisAlignment;

  @override
  RenderWrap createRenderObject(BuildContext context) {
    return new RenderWrap(
      direction: direction,
      alignment: alignment,
      spacing: spacing,
      runAlignment: runAlignment,
      runSpacing: runSpacing,
      crossAxisAlignment: crossAxisAlignment,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderWrap renderObject) {
    renderObject
      ..direction = direction
      ..alignment = alignment
      ..spacing = spacing
      ..runAlignment = runAlignment
      ..runSpacing = runSpacing
      ..crossAxisAlignment = crossAxisAlignment;
  }
}

2371
/// A widget that implements the flow layout algorithm.
Adam Barth's avatar
Adam Barth committed
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392
///
/// Flow layouts are optimized for repositioning children using transformation
/// matrices.
///
/// The flow container is sized independently from the children by the
/// [FlowDelegate.getSize] function of the delegate. The children are then sized
/// independently given the constraints from the
/// [FlowDelegate.getConstraintsForChild] function.
///
/// Rather than positioning the children during layout, the children are
/// positioned using transformation matrices during the paint phase using the
/// matrices from the [FlowDelegate.paintChildren] function. The children can be
/// repositioned efficiently by simply repainting the flow.
///
/// The most efficient way to trigger a repaint of the flow is to supply a
/// repaint argument to the constructor of the [FlowDelegate]. The flow will
/// listen to this animation and repaint whenever the animation ticks, avoiding
/// both the build and layout phases of the pipeline.
///
/// See also:
///
2393 2394 2395 2396 2397 2398
///  * [FlowDelegate], which controls the visual presentation of the children.
///  * [Stack], which arranges children relative to the edges of the container.
///  * [CustomSingleChildLayout], which uses a delegate to control the layout of
///    a single child.
///  * [CustomMultiChildLayout], which uses a delegate to position multiple
///    children.
Adam Barth's avatar
Adam Barth committed
2399 2400 2401 2402 2403
class Flow extends MultiChildRenderObjectWidget {
  /// Creates a flow layout.
  ///
  /// Wraps each of the given children in a [RepaintBoundary] to avoid
  /// repainting the children when the flow repaints.
2404 2405
  ///
  /// The [delegate] argument must not be null.
Adam Barth's avatar
Adam Barth committed
2406 2407
  Flow({
    Key key,
2408
    @required this.delegate,
2409
    List<Widget> children: const <Widget>[],
2410 2411 2412
  }) : assert(delegate != null),
       super(key: key, children: RepaintBoundary.wrapAll(children));
       // https://github.com/dart-lang/sdk/issues/29277
Adam Barth's avatar
Adam Barth committed
2413 2414 2415 2416 2417 2418

  /// Creates a flow layout.
  ///
  /// Does not wrap the given children in repaint boundaries, unlike the default
  /// constructor. Useful when the child is trivial to paint or already contains
  /// a repaint boundary.
2419 2420
  ///
  /// The [delegate] argument must not be null.
Adam Barth's avatar
Adam Barth committed
2421 2422
  Flow.unwrapped({
    Key key,
2423
    @required this.delegate,
2424
    List<Widget> children: const <Widget>[],
Adam Barth's avatar
Adam Barth committed
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
  }) : super(key: key, children: children) {
    assert(delegate != null);
  }

  /// The delegate that controls the transformation matrices of the children.
  final FlowDelegate delegate;

  @override
  RenderFlow createRenderObject(BuildContext context) => new RenderFlow(delegate: delegate);

  @override
  void updateRenderObject(BuildContext context, RenderFlow renderObject) {
    renderObject
      ..delegate = delegate;
  }
}

Adam Barth's avatar
Adam Barth committed
2442
/// A paragraph of rich text.
2443
///
2444
/// The [RichText] widget displays text that uses multiple different styles. The
2445
/// text to display is described using a tree of [TextSpan] objects, each of
2446 2447 2448
/// which has an associated style that is used for that subtree. The text might
/// break across multiple lines or might all be displayed on the same line
/// depending on the layout constraints.
2449 2450
///
/// Text displayed in a [RichText] widget must be explicitly styled. When
2451 2452
/// picking which style to use, consider using [DefaultTextStyle.of] the current
/// [BuildContext] to provide defaults.
2453
///
2454 2455 2456
/// When all the text uses the same style, consider using the [Text] widget,
/// which is less verbose and integrates with [DefaultTextStyle] for default
/// styling.
2457
///
2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472
/// Example:
///
/// ```dart
/// new RichText(
///   text: new TextSpan(
///     text: 'Hello ',
///     style: DefaultTextStyle.of(context).style,
///     children: <TextSpan>[
///       new TextSpan(text: 'bold', style: new TextStyle(fontWeight: FontWeight.bold)),
///       new TextSpan(text: ' world!'),
///     ],
///   ),
/// ),
/// ```
///
2473 2474 2475 2476 2477
/// See also:
///
///  * [Text]
///  * [TextSpan]
///  * [DefaultTextStyle]
Adam Barth's avatar
Adam Barth committed
2478
class RichText extends LeafRenderObjectWidget {
2479 2480
  /// Creates a paragraph of rich text.
  ///
2481
  /// The [text], [softWrap], and [overflow] arguments must not be null.
2482
  const RichText({
2483
    Key key,
2484
    @required this.text,
2485 2486
    this.textAlign,
    this.softWrap: true,
2487
    this.overflow: TextOverflow.clip,
2488 2489
    this.textScaleFactor: 1.0,
    this.maxLines,
2490 2491 2492 2493 2494
  }) : assert(text != null),
       assert(softWrap != null),
       assert(overflow != null),
       assert(textScaleFactor != null),
       super(key: key);
2495

2496
  /// The text to display in this widget.
2497
  final TextSpan text;
2498

2499 2500 2501
  /// How the text should be aligned horizontally.
  final TextAlign textAlign;

2502 2503 2504 2505 2506 2507 2508 2509
  /// Whether the text should break at soft line breaks.
  ///
  /// If false, the glyphs in the text will be positioned as if there was unlimited horizontal space.
  final bool softWrap;

  /// How visual overflow should be handled.
  final TextOverflow overflow;

2510 2511 2512 2513 2514 2515
  /// The number of font pixels for each logical pixel.
  ///
  /// For example, if the text scale factor is 1.5, text will be 50% larger than
  /// the specified font size.
  final double textScaleFactor;

2516 2517 2518 2519 2520
  /// An optional maximum number of lines for the text to span, wrapping if necessary.
  /// If the text exceeds the given number of lines, it will be truncated according
  /// to [overflow].
  final int maxLines;

2521
  @override
2522
  RenderParagraph createRenderObject(BuildContext context) {
2523 2524 2525
    return new RenderParagraph(text,
      textAlign: textAlign,
      softWrap: softWrap,
2526
      overflow: overflow,
2527 2528
      textScaleFactor: textScaleFactor,
      maxLines: maxLines,
2529
    );
2530
  }
2531

2532
  @override
2533
  void updateRenderObject(BuildContext context, RenderParagraph renderObject) {
2534 2535
    renderObject
      ..text = text
2536 2537
      ..textAlign = textAlign
      ..softWrap = softWrap
2538
      ..overflow = overflow
2539 2540
      ..textScaleFactor = textScaleFactor
      ..maxLines = maxLines;
2541
  }
2542 2543
}

2544
/// A widget that displays a [ui.Image] directly.
2545
///
2546 2547
/// The image is painted using [paintImage], which describes the meanings of the
/// various fields on this class in more detail.
2548
///
2549
/// This widget is rarely used directly. Instead, consider using [Image].
2550
class RawImage extends LeafRenderObjectWidget {
2551 2552 2553
  /// Creates a widget that displays an image.
  ///
  /// The [scale] and [repeat] arguments must not be null.
2554
  const RawImage({
2555 2556 2557 2558
    Key key,
    this.image,
    this.width,
    this.height,
2559
    this.scale: 1.0,
Adam Barth's avatar
Adam Barth committed
2560
    this.color,
2561
    this.fit,
2562
    this.alignment,
2563 2564
    this.repeat: ImageRepeat.noRepeat,
    this.centerSlice
2565 2566 2567
  }) : assert(scale != null),
       assert(repeat != null),
       super(key: key);
2568

2569
  /// The image to display.
2570
  final ui.Image image;
2571 2572 2573 2574 2575

  /// If non-null, require the image to have this width.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio.
2576
  final double width;
2577 2578 2579 2580 2581

  /// If non-null, require the image to have this height.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio.
2582
  final double height;
2583

2584
  /// Specifies the image's scale.
2585 2586 2587 2588
  ///
  /// Used when determining the best display size for the image.
  final double scale;

Adam Barth's avatar
Adam Barth committed
2589 2590
  /// If non-null, apply this color filter to the image before painting.
  final Color color;
2591

Adam Barth's avatar
Adam Barth committed
2592
  /// How to inscribe the image into the space allocated during layout.
2593 2594 2595
  ///
  /// The default varies based on the other fields. See the discussion at
  /// [paintImage].
2596
  final BoxFit fit;
2597 2598 2599 2600 2601 2602

  /// How to align the image within its bounds.
  ///
  /// An alignment of (0.0, 0.0) aligns the image to the top-left corner of its
  /// layout bounds.  An alignment of (1.0, 0.5) aligns the image to the middle
  /// of the right edge of its layout bounds.
2603
  final FractionalOffset alignment;
2604 2605

  /// How to paint any portions of the layout bounds not covered by the image.
2606
  final ImageRepeat repeat;
2607 2608 2609 2610 2611 2612 2613 2614

  /// The center slice for a nine-patch image.
  ///
  /// The region of the image inside the center slice will be stretched both
  /// horizontally and vertically to fit the image into its destination. The
  /// region of the image above and below the center slice will be stretched
  /// only horizontally and the region of the image to the left and right of
  /// the center slice will be stretched only vertically.
2615
  final Rect centerSlice;
2616

2617
  @override
2618
  RenderImage createRenderObject(BuildContext context) => new RenderImage(
2619 2620 2621
    image: image,
    width: width,
    height: height,
2622
    scale: scale,
Adam Barth's avatar
Adam Barth committed
2623
    color: color,
2624
    fit: fit,
2625
    alignment: alignment,
2626
    repeat: repeat,
2627 2628
    centerSlice: centerSlice
  );
2629

2630
  @override
2631
  void updateRenderObject(BuildContext context, RenderImage renderObject) {
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641
    renderObject
      ..image = image
      ..width = width
      ..height = height
      ..scale = scale
      ..color = color
      ..alignment = alignment
      ..fit = fit
      ..repeat = repeat
      ..centerSlice = centerSlice;
2642
  }
2643

2644
  @override
2645 2646
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
2647
    description.add('image: $image');
2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664
    if (width != null)
      description.add('width: $width');
    if (height != null)
      description.add('height: $height');
    if (scale != 1.0)
      description.add('scale: $scale');
    if (color != null)
      description.add('color: $color');
    if (fit != null)
      description.add('fit: $fit');
    if (alignment != null)
      description.add('alignment: $alignment');
    if (repeat != ImageRepeat.noRepeat)
      description.add('repeat: $repeat');
    if (centerSlice != null)
      description.add('centerSlice: $centerSlice');
  }
2665 2666
}

2667
/// A widget that determines the default asset bundle for its descendants.
2668
///
2669 2670
/// For example, used by [Image] to determine which bundle to use for
/// [AssetImage]s if no bundle is specified explicitly.
Adam Barth's avatar
Adam Barth committed
2671
class DefaultAssetBundle extends InheritedWidget {
2672 2673 2674
  /// Creates a widget that determines the default asset bundle for its descendants.
  ///
  /// The [bundle] and [child] arguments must not be null.
2675
  const DefaultAssetBundle({
Adam Barth's avatar
Adam Barth committed
2676
    Key key,
2677 2678
    @required this.bundle,
    @required Widget child
2679 2680 2681
  }) : assert(bundle != null),
       assert(child != null),
       super(key: key, child: child);
Adam Barth's avatar
Adam Barth committed
2682

2683
  /// The bundle to use as a default.
Adam Barth's avatar
Adam Barth committed
2684 2685
  final AssetBundle bundle;

2686 2687 2688 2689 2690
  /// The bundle from the closest instance of this class that encloses
  /// the given context.
  ///
  /// If there is no [DefaultAssetBundle] ancestor widget in the tree
  /// at the given context, then this will return the [rootBundle].
2691 2692 2693 2694 2695 2696
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// AssetBundle bundle = DefaultAssetBundle.of(context);
  /// ```
Adam Barth's avatar
Adam Barth committed
2697
  static AssetBundle of(BuildContext context) {
2698
    final DefaultAssetBundle result = context.inheritFromWidgetOfExactType(DefaultAssetBundle);
2699
    return result?.bundle ?? rootBundle;
Adam Barth's avatar
Adam Barth committed
2700 2701
  }

2702
  @override
Adam Barth's avatar
Adam Barth committed
2703 2704 2705
  bool updateShouldNotify(DefaultAssetBundle old) => bundle != old.bundle;
}

2706 2707 2708 2709 2710
/// An adapter for placing a specific [RenderBox] in the widget tree.
///
/// A given render object can be placed at most once in the widget tree. This
/// widget enforces that restriction by keying itself using a [GlobalObjectKey]
/// for the given render object.
Hixie's avatar
Hixie committed
2711
class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
2712 2713 2714 2715
  /// Creates an adapter for placing a specific [RenderBox] in the widget tree.
  ///
  /// The [renderBox] argument must not be null.
  WidgetToRenderBoxAdapter({
2716
    @required this.renderBox,
2717 2718
    this.onBuild,
  }) : assert(renderBox != null),
2719 2720 2721 2722
       // WidgetToRenderBoxAdapter objects are keyed to their render box. This
       // prevents the widget being used in the widget hierarchy in two different
       // places, which would cause the RenderBox to get inserted in multiple
       // places in the RenderObject tree.
2723
       super(key: new GlobalObjectKey(renderBox));
Hixie's avatar
Hixie committed
2724

2725
  /// The render box to place in the widget tree.
Hixie's avatar
Hixie committed
2726 2727
  final RenderBox renderBox;

2728 2729 2730 2731 2732 2733
  /// Called when it is safe to update the render box and its descendants. If
  /// you update the RenderObject subtree under this widget outside of
  /// invocations of this callback, features like hit-testing will fail as the
  /// tree will be dirty.
  final VoidCallback onBuild;

2734
  @override
2735
  RenderBox createRenderObject(BuildContext context) => renderBox;
2736

2737
  @override
2738
  void updateRenderObject(BuildContext context, RenderBox renderObject) {
2739 2740 2741
    if (onBuild != null)
      onBuild();
  }
Hixie's avatar
Hixie committed
2742 2743
}

2744

2745
// EVENT HANDLING
2746

2747
/// A widget that calls callbacks in response to pointer events.
2748 2749 2750
///
/// Rather than listening for raw pointer events, consider listening for
/// higher-level gestures using [GestureDetector].
2751 2752 2753
///
/// If it has a child, this widget defers to the child for sizing behavior. If
/// it does not have a child, it grows to fit the parent instead.
2754
class Listener extends SingleChildRenderObjectWidget {
2755 2756 2757
  /// Creates a widget that forwards point events to callbacks.
  ///
  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
2758
  const Listener({
2759 2760 2761 2762
    Key key,
    this.onPointerDown,
    this.onPointerMove,
    this.onPointerUp,
2763
    this.onPointerCancel,
2764 2765
    this.behavior: HitTestBehavior.deferToChild,
    Widget child
2766 2767
  }) : assert(behavior != null),
       super(key: key, child: child);
2768

2769
  /// Called when a pointer comes into contact with the screen at this object.
Ian Hickson's avatar
Ian Hickson committed
2770
  final PointerDownEventListener onPointerDown;
2771 2772

  /// Called when a pointer that triggered an [onPointerDown] changes position.
Ian Hickson's avatar
Ian Hickson committed
2773
  final PointerMoveEventListener onPointerMove;
2774 2775

  /// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen.
Ian Hickson's avatar
Ian Hickson committed
2776
  final PointerUpEventListener onPointerUp;
2777 2778

  /// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver.
Ian Hickson's avatar
Ian Hickson committed
2779
  final PointerCancelEventListener onPointerCancel;
2780 2781

  /// How to behave during hit testing.
2782
  final HitTestBehavior behavior;
2783

2784
  @override
2785
  RenderPointerListener createRenderObject(BuildContext context) => new RenderPointerListener(
2786 2787 2788
    onPointerDown: onPointerDown,
    onPointerMove: onPointerMove,
    onPointerUp: onPointerUp,
2789 2790
    onPointerCancel: onPointerCancel,
    behavior: behavior
2791
  );
2792

2793
  @override
2794
  void updateRenderObject(BuildContext context, RenderPointerListener renderObject) {
2795 2796 2797 2798 2799 2800
    renderObject
      ..onPointerDown = onPointerDown
      ..onPointerMove = onPointerMove
      ..onPointerUp = onPointerUp
      ..onPointerCancel = onPointerCancel
      ..behavior = behavior;
2801
  }
2802

2803
  @override
2804 2805
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
2806
    final List<String> listeners = <String>[];
2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829
    if (onPointerDown != null)
      listeners.add('down');
    if (onPointerMove != null)
      listeners.add('move');
    if (onPointerUp != null)
      listeners.add('up');
    if (onPointerCancel != null)
      listeners.add('cancel');
    if (listeners.isEmpty)
      listeners.add('<none>');
    description.add('listeners: ${listeners.join(", ")}');
    switch (behavior) {
      case HitTestBehavior.translucent:
        description.add('behavior: translucent');
        break;
      case HitTestBehavior.opaque:
        description.add('behavior: opaque');
        break;
      case HitTestBehavior.deferToChild:
        description.add('behavior: defer-to-child');
        break;
    }
  }
2830
}
2831

2832
/// A widget that creates a separate display list for its child.
2833 2834 2835 2836 2837 2838 2839 2840
///
/// This widget creates a separate display list for its child, which
/// can improve performance if the subtree repaints at different times than
/// the surrounding parts of the tree. Specifically, when the child does not
/// repaint but its parent does, we can re-use the display list we recorded
/// previously. Similarly, when the child repaints but the surround tree does
/// not, we can re-record its display list without re-recording the display list
/// for the surround tree.
2841
class RepaintBoundary extends SingleChildRenderObjectWidget {
2842
  /// Creates a widget that isolates repaints.
2843
  const RepaintBoundary({ Key key, Widget child }) : super(key: key, child: child);
2844

2845 2846 2847 2848
  /// Wraps the given child in a [RepaintBoundary].
  ///
  /// The key for the [RepaintBoundary] is derived either from the child's key
  /// (if the child has a non-null key) or from the given `childIndex`.
2849
  factory RepaintBoundary.wrap(Widget child, int childIndex) {
2850
    assert(child != null);
2851
    final Key key = child.key != null ? new ValueKey<Key>(child.key) : new ValueKey<int>(childIndex);
2852 2853 2854
    return new RepaintBoundary(key: key, child: child);
  }

2855 2856 2857 2858 2859
  /// Wraps each of the given children in [RepaintBoundary]s.
  ///
  /// The key for each [RepaintBoundary] is derived either from the wrapped
  /// child's key (if the wrapped child has a non-null key) or from the wrapped
  /// child's index in the list.
Adam Barth's avatar
Adam Barth committed
2860
  static List<RepaintBoundary> wrapAll(List<Widget> widgets) {
2861
    final List<RepaintBoundary> result = new List<RepaintBoundary>(widgets.length);
Adam Barth's avatar
Adam Barth committed
2862 2863 2864 2865 2866
    for (int i = 0; i < result.length; ++i)
      result[i] = new RepaintBoundary.wrap(widgets[i], i);
    return result;
  }

2867
  @override
2868
  RenderRepaintBoundary createRenderObject(BuildContext context) => new RenderRepaintBoundary();
2869 2870
}

2871
/// A widget that is invisible during hit testing.
2872
///
2873
/// When [ignoring] is true, this widget (and its subtree) is invisible
2874
/// to hit testing. It still consumes space during layout and paints its child
2875
/// as usual. It just cannot be the target of located events, because it returns
2876
/// false from [hitTest].
2877
///
2878
/// When [ignoringSemantics] is true, the subtree will be invisible to
2879 2880
/// the semantics layer (and thus e.g. accessibility tools). If
/// [ignoringSemantics] is null, it uses the value of [ignoring].
2881 2882 2883 2884 2885
///
/// See also:
///
///  * [AbsorbPointer], which also prevents its children from receiving pointer
///    events but is itself visible to hit testing.
2886
class IgnorePointer extends SingleChildRenderObjectWidget {
2887
  /// Creates a widget that is invisible to hit testing.
2888 2889 2890
  ///
  /// The [ignoring] argument must not be null. If [ignoringSemantics], this
  /// render object will be ignored for semantics if [ignoring] is true.
2891
  const IgnorePointer({
2892 2893
    Key key,
    this.ignoring: true,
2894 2895
    this.ignoringSemantics,
    Widget child
2896 2897
  }) : assert(ignoring != null),
       super(key: key, child: child);
2898

2899 2900 2901 2902
  /// Whether this widget is ignored during hit testing.
  ///
  /// Regardless of whether this widget is ignored during hit testing, it will
  /// still consume space during layout and be visible during painting.
2903
  final bool ignoring;
2904 2905 2906 2907 2908 2909 2910

  /// Whether the semantics of this widget is ignored when compiling the semantics tree.
  ///
  /// If null, defaults to value of [ignoring].
  ///
  /// See [SemanticsNode] for additional information about the semantics tree.
  final bool ignoringSemantics;
2911

2912
  @override
2913
  RenderIgnorePointer createRenderObject(BuildContext context) => new RenderIgnorePointer(
Hixie's avatar
Hixie committed
2914 2915 2916
    ignoring: ignoring,
    ignoringSemantics: ignoringSemantics
  );
2917

2918
  @override
2919
  void updateRenderObject(BuildContext context, RenderIgnorePointer renderObject) {
2920 2921 2922
    renderObject
      ..ignoring = ignoring
      ..ignoringSemantics = ignoringSemantics;
2923
  }
2924 2925 2926 2927 2928 2929 2930 2931

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('ignoring: $ignoring');
    if (ignoringSemantics != null)
      description.add('ignoringSemantics: $ignoringSemantics');
  }
2932
}
2933

2934 2935
/// A widget that absorbs pointers during hit testing.
///
2936
/// When [absorbing] is true, this widget prevents its subtree from receiving
2937 2938
/// pointer events by terminating hit testing at itself. It still consumes space
/// during layout and paints its child as usual. It just prevents its children
2939
/// from being the target of located events, because it returns true from
2940
/// [hitTest].
2941 2942 2943 2944 2945
///
/// See also:
///
///  * [IgnorePointer], which also prevents its children from receiving pointer
///    events but is itself invisible to hit testing.
2946 2947 2948 2949
class AbsorbPointer extends SingleChildRenderObjectWidget {
  /// Creates a widget that absorbs pointers during hit testing.
  ///
  /// The [absorbing] argument must not be null
2950
  const AbsorbPointer({
2951 2952 2953
    Key key,
    this.absorbing: true,
    Widget child
2954 2955
  }) : assert(absorbing != null),
       super(key: key, child: child);
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972

  /// Whether this widget absorbs pointers during hit testing.
  ///
  /// Regardless of whether this render object absorbs pointers during hit
  /// testing, it will still consume space during layout and be visible during
  /// painting.
  final bool absorbing;

  @override
  RenderAbsorbPointer createRenderObject(BuildContext context) => new RenderAbsorbPointer(absorbing: absorbing);

  @override
  void updateRenderObject(BuildContext context, RenderAbsorbPointer renderObject) {
    renderObject.absorbing = absorbing;
  }
}

2973
/// Holds opaque meta data in the render tree.
2974 2975 2976 2977 2978
///
/// Useful for decorating the render tree with information that will be consumed
/// later. For example, you could store information in the render tree that will
/// be used when the user interacts with the render tree but has no visual
/// impact prior to the interaction.
2979
class MetaData extends SingleChildRenderObjectWidget {
2980
  /// Creates a widget that hold opaque meta data.
2981 2982
  ///
  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
2983
  const MetaData({
2984 2985
    Key key,
    this.metaData,
2986 2987
    this.behavior: HitTestBehavior.deferToChild,
    Widget child
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016
  }) : super(key: key, child: child);

  /// Opaque meta data ignored by the render tree
  final dynamic metaData;

  /// How to behave during hit testing.
  final HitTestBehavior behavior;

  @override
  RenderMetaData createRenderObject(BuildContext context) => new RenderMetaData(
    metaData: metaData,
    behavior: behavior
  );

  @override
  void updateRenderObject(BuildContext context, RenderMetaData renderObject) {
    renderObject
      ..metaData = metaData
      ..behavior = behavior;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('behavior: $behavior');
    description.add('metaData: $metaData');
  }
}

3017 3018 3019

// UTILITY NODES

3020 3021
/// A widget that annotates the widget tree with a description of the meaning of
/// the widgets.
3022 3023 3024
///
/// Used by accessibility tools, search engines, and other semantic analysis
/// software to determine the meaning of the application.
3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039
///
/// See also:
///
/// * [MergeSemantics], which marks a subtree as being a single node for
///   accessibility purposes.
/// * [ExcludeSemantics], which excludes a subtree from the semantics tree
///   (which might be useful if it is, e.g., totally decorative and not
///   important to the user).
/// * [RenderObject.semanticsAnnotator], the rendering library API through which
///   the [Semantics] widget is actually implemented.
/// * [SemanticsNode], the object used by the rendering library to represent
///   semantics in the semantics tree.
/// * [SemanticsDebugger], an overlay to help visualize the semantics tree. Can
///   be enabled using [WidgetsApp.showSemanticsDebugger] or
///   [MaterialApp.showSemanticsDebugger].
3040
class Semantics extends SingleChildRenderObjectWidget {
3041 3042 3043
  /// Creates a semantic annotation.
  ///
  /// The [container] argument must not be null.
3044
  const Semantics({
Hixie's avatar
Hixie committed
3045 3046 3047 3048 3049
    Key key,
    Widget child,
    this.container: false,
    this.checked,
    this.label
3050 3051
  }) : assert(container != null),
       super(key: key, child: child);
Hixie's avatar
Hixie committed
3052 3053 3054 3055

  /// If 'container' is true, this Widget will introduce a new node in
  /// the semantics tree. Otherwise, the semantics will be merged with
  /// the semantics of any ancestors.
3056
  ///
Hixie's avatar
Hixie committed
3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072
  /// The 'container' flag is implicitly set to true on the immediate
  /// semantics-providing descendants of a node where multiple
  /// children have semantics or have descendants providing semantics.
  /// In other words, the semantics of siblings are not merged. To
  /// merge the semantics of an entire subtree, including siblings,
  /// you can use a [MergeSemantics] widget.
  final bool container;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "checked" state, and what its current
  /// state is.
  final bool checked;

  /// Provides a textual description of the widget.
  final String label;

3073
  @override
3074
  RenderSemanticsAnnotations createRenderObject(BuildContext context) => new RenderSemanticsAnnotations(
Hixie's avatar
Hixie committed
3075 3076 3077 3078 3079
    container: container,
    checked: checked,
    label: label
  );

3080
  @override
3081
  void updateRenderObject(BuildContext context, RenderSemanticsAnnotations renderObject) {
3082 3083 3084 3085
    renderObject
      ..container = container
      ..checked = checked
      ..label = label;
Hixie's avatar
Hixie committed
3086 3087
  }

3088
  @override
Hixie's avatar
Hixie committed
3089 3090 3091
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('container: $container');
pq's avatar
pq committed
3092
    if (checked != null)
3093
      description.add('checked: $checked');
pq's avatar
pq committed
3094
    if (label != null)
Hixie's avatar
Hixie committed
3095 3096 3097 3098
      description.add('label: "$label"');
  }
}

3099 3100
/// A widget that merges the semantics of its descendants.
///
Hixie's avatar
Hixie committed
3101 3102
/// Causes all the semantics of the subtree rooted at this node to be
/// merged into one node in the semantics tree. For example, if you
3103
/// have a widget with a Text node next to a checkbox widget, this
Hixie's avatar
Hixie committed
3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117
/// could be used to merge the label from the Text node with the
/// "checked" semantic state of the checkbox into a single node that
/// had both the label and the checked state. Otherwise, the label
/// would be presented as a separate feature than the checkbox, and
/// the user would not be able to be sure that they were related.
///
/// Be aware that if two nodes in the subtree have conflicting
/// semantics, the result may be nonsensical. For example, a subtree
/// with a checked checkbox and an unchecked checkbox will be
/// presented as checked. All the labels will be merged into a single
/// string (with newlines separating each label from the other). If
/// multiple nodes in the merged subtree can handle semantic gestures,
/// the first one in tree order will be the one to receive the
/// callbacks.
3118
class MergeSemantics extends SingleChildRenderObjectWidget {
3119
  /// Creates a widget that merges the semantics of its descendants.
3120
  const MergeSemantics({ Key key, Widget child }) : super(key: key, child: child);
3121 3122

  @override
3123
  RenderMergeSemantics createRenderObject(BuildContext context) => new RenderMergeSemantics();
Hixie's avatar
Hixie committed
3124 3125
}

3126
/// A widget that drops all the semantics of its descendants.
Hixie's avatar
Hixie committed
3127 3128 3129 3130 3131
///
/// This can be used to hide subwidgets that would otherwise be
/// reported but that would only be confusing. For example, the
/// material library's [Chip] widget hides the avatar since it is
/// redundant with the chip label.
3132
class ExcludeSemantics extends SingleChildRenderObjectWidget {
3133
  /// Creates a widget that drops all the semantics of its descendants.
3134
  const ExcludeSemantics({ Key key, Widget child }) : super(key: key, child: child);
3135 3136

  @override
3137
  RenderExcludeSemantics createRenderObject(BuildContext context) => new RenderExcludeSemantics();
Hixie's avatar
Hixie committed
3138 3139
}

3140
/// A widget that builds its child.
Adam Barth's avatar
Adam Barth committed
3141 3142
///
/// Useful for attaching a key to an existing widget.
3143
class KeyedSubtree extends StatelessWidget {
3144
  /// Creates a widget that builds its child.
3145
  const KeyedSubtree({
3146 3147
    Key key,
    @required this.child
3148 3149
  }) : assert(child != null),
       super(key: key);
3150

3151
  /// The widget below this widget in the tree.
3152 3153
  final Widget child;

Adam Barth's avatar
Adam Barth committed
3154 3155
  /// Creates a KeyedSubtree for child with a key that's based on the child's existing key or childIndex.
  factory KeyedSubtree.wrap(Widget child, int childIndex) {
3156
    final Key key = child.key != null ? new ValueKey<Key>(child.key) : new ValueKey<int>(childIndex);
Adam Barth's avatar
Adam Barth committed
3157 3158 3159
    return new KeyedSubtree(key: key, child: child);
  }

3160
  /// Wrap each item in a KeyedSubtree whose key is based on the item's existing key or
3161
  /// the sum of its list index and `baseIndex`.
3162 3163 3164 3165
  static List<Widget> ensureUniqueKeysForList(Iterable<Widget> items, { int baseIndex: 0 }) {
    if (items == null || items.isEmpty)
      return items;

3166
    final List<Widget> itemsWithUniqueKeys = <Widget>[];
3167
    int itemIndex = baseIndex;
Adam Barth's avatar
Adam Barth committed
3168 3169
    for (Widget item in items) {
      itemsWithUniqueKeys.add(new KeyedSubtree.wrap(item, itemIndex));
3170 3171 3172 3173
      itemIndex += 1;
    }

    assert(!debugItemsHaveDuplicateKeys(itemsWithUniqueKeys));
Hans Muller's avatar
Hans Muller committed
3174
    return itemsWithUniqueKeys;
3175 3176
  }

3177
  @override
3178
  Widget build(BuildContext context) => child;
Adam Barth's avatar
Adam Barth committed
3179
}
3180

3181
/// A platonic widget that calls a closure to obtain its child widget.
3182 3183 3184
///
/// See also:
///
3185
///  * [StatefulBuilder], a platonic widget which also has state.
3186
class Builder extends StatelessWidget {
3187 3188 3189
  /// Creates a widget that delegates its build to a callback.
  ///
  /// The [builder] argument must not be null.
3190
  const Builder({
3191 3192
    Key key,
    @required this.builder
3193 3194
  }) : assert(builder != null),
       super(key: key);
3195 3196 3197

  /// Called to obtain the child widget.
  ///
3198
  /// This function is called whenever this widget is included in its parent's
3199
  /// build and the old widget (if any) that it synchronizes with has a distinct
3200 3201 3202
  /// object identity. Typically the parent's build method will construct
  /// a new tree of widgets and so a new Builder child will not be [identical]
  /// to the corresponding old one.
3203
  final WidgetBuilder builder;
3204

3205
  @override
3206 3207 3208
  Widget build(BuildContext context) => builder(context);
}

3209 3210 3211
/// Signature for the builder callback used by [StatefulBuilder].
///
/// Call [setState] to schedule the [StatefulBuilder] to rebuild.
3212
typedef Widget StatefulWidgetBuilder(BuildContext context, StateSetter setState);
3213 3214 3215 3216 3217

/// A platonic widget that both has state and calls a closure to obtain its child widget.
///
/// See also:
///
3218
///  * [Builder], the platonic stateless widget.
3219
class StatefulBuilder extends StatefulWidget {
3220 3221 3222
  /// Creates a widget that both has state and delegates its build to a callback.
  ///
  /// The [builder] argument must not be null.
3223
  const StatefulBuilder({
3224 3225
    Key key,
    @required this.builder
3226 3227
  }) : assert(builder != null),
       super(key: key);
3228

3229 3230 3231 3232 3233 3234 3235
  /// Called to obtain the child widget.
  ///
  /// This function is called whenever this widget is included in its parent's
  /// build and the old widget (if any) that it synchronizes with has a distinct
  /// object identity. Typically the parent's build method will construct
  /// a new tree of widgets and so a new Builder child will not be [identical]
  /// to the corresponding old one.
3236
  final StatefulWidgetBuilder builder;
3237 3238

  @override
3239 3240
  _StatefulBuilderState createState() => new _StatefulBuilderState();
}
3241

3242
class _StatefulBuilderState extends State<StatefulBuilder> {
3243
  @override
3244
  Widget build(BuildContext context) => config.builder(context, setState);
3245
}