diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 3d28ab3d49..bdf161eb84 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -734,18 +734,72 @@ class _ForkingSemanticsFragment extends _SemanticsFragment { } } +/// The pipeline owner manages the rendering pipeline. +/// +/// The pipeline owner provides an interface for driving the rendering pipeline +/// and stores the state about which render objects have requested to be visited +/// in each stage of the pipeline. To flush the pipeline, call the following +/// functions in order: +/// +/// 1. [flushLayout] updates any render objects that need to compute their +/// layout. During this phase, the size and position of each render +/// object is calculated. Render objects might dirty their painting or +/// compositing state during this phase. +/// 2. [flushCompositingBits] updates any render objects that have dirty +/// compositing bits. During this phase, each render object learns whether +/// any of its children require compositing. This information is used during +/// the painting phase when selecting how to implement visual effects such as +/// clipping. If a render object has a composited child, its needs to use a +/// [Layer] to create the clip in order for the clip to apply to the +/// composited child (which will be painted into its own [Layer]). +/// 3. [flushPaint] visites any render objects that need to paint. During this +/// phase, render objects get a chance to record painting commands into +/// [PictureLayer]s and construct other composited [Layer]s. +/// 4. Finally, if [SemanticsNode.hasListeners] is true, [flushSemantics] will +/// compile the semantics for the render objects. This semantic information +/// is used by assistive technology to improve the accessibility of the +/// render tree. +/// +/// The [RendererBinding] holds the pipeline owner for the render objects that +/// are visible on screen. You can create other pipeline owners to manage +/// off-screen objects, which can flush their pipelines independently of the +/// on-screen render objects. class PipelineOwner { + /// Creates a pipeline owner. + /// + /// Typically created by the binding (e.g., [RendererBinding]), but can be + /// created separately from the binding to drive off-screen render objects + /// through the rendering pipeline. PipelineOwner({ this.onNeedVisualUpdate }); + + /// Called when a render object associated with this pipeline owner wishes to + /// update its visual appearance. + /// + /// Typical implementations of this function will schedule a task to flush the + /// various stages of the pipeline. This function might be called multiple + /// times in quick succession. Implementations should take care to discard + /// duplicate calls quickly. final VoidCallback onNeedVisualUpdate; + /// Calls [onNeedVisualUpdate] if [onNeedVisualUpdate] is not null. + /// + /// Used to notify the pipeline owner that an associated render object wishes + /// to update its visual appearance. void requestVisualUpdate() { if (onNeedVisualUpdate != null) onNeedVisualUpdate(); } List _nodesNeedingLayout = []; - bool _debugDoingLayout = false; + + /// Whether this pipeline is currently in the layout phase. + /// + /// Specifically, whether [flushLayout] is currently running. + /// + /// Only valid when asserts are enabled. bool get debugDoingLayout => _debugDoingLayout; + bool _debugDoingLayout = false; + /// Update the layout information for all dirty render objects. /// /// This function is one of the core stages of the rendering pipeline. Layout @@ -789,8 +843,15 @@ class PipelineOwner { } List _nodesNeedingPaint = []; - bool _debugDoingPaint = false; + + /// Whether this pipeline is currently in the paint phase. + /// + /// Specifically, whether [flushPaint] is currently running. + /// + /// Only valid when asserts are enabled. bool get debugDoingPaint => _debugDoingPaint; + bool _debugDoingPaint = false; + /// Update the display lists for all render objects. /// /// This function is one of the core stages of the rendering pipeline. @@ -820,6 +881,13 @@ class PipelineOwner { bool _debugDoingSemantics = false; List _nodesNeedingSemantics = []; + /// Update the semantics for all render objects. + /// + /// This function is one of the core stages of the rendering pipeline. The + /// semantics are compiled after painting and only after + /// [RenderObject.scheduleInitialSemantics] has been called. + /// + /// See [FlutterBinding] for an example of how this function is used. void flushSemantics() { Timeline.startSync('Semantics'); assert(_semanticsEnabled); @@ -878,7 +946,7 @@ void _doNothing() { } /// The [RenderBox] subclass introduces the opinion that the layout /// system uses cartesian coordinates. abstract class RenderObject extends AbstractNode implements HitTestTarget { - + /// Initializes internal fields for subclasses. RenderObject() { _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing; _performLayout = performLayout; @@ -919,7 +987,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// You can call this function to set up the parent data for child before the /// child is added to the parent's child list. void setupParentData(RenderObject child) { - assert(debugCanPerformMutations); + assert(_debugCanPerformMutations); if (child.parentData is! ParentData) child.parentData = new ParentData(); } @@ -930,7 +998,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// in other cases will lead to an inconsistent tree and probably cause crashes. @override void adoptChild(RenderObject child) { - assert(debugCanPerformMutations); + assert(_debugCanPerformMutations); assert(child != null); setupParentData(child); super.adoptChild(child); @@ -944,7 +1012,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// in other cases will lead to an inconsistent tree and probably cause crashes. @override void dropChild(RenderObject child) { - assert(debugCanPerformMutations); + assert(_debugCanPerformMutations); assert(child != null); assert(child.parentData != null); child._cleanRelayoutSubtreeRoot(); @@ -1005,26 +1073,65 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { )); } - bool _debugDoingThisResize = false; + /// Whether [performResize] for this render object is currently running. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// false. bool get debugDoingThisResize => _debugDoingThisResize; - bool _debugDoingThisLayout = false; + bool _debugDoingThisResize = false; + + /// Whether [performLayout] for this render object is currently running. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// false. bool get debugDoingThisLayout => _debugDoingThisLayout; - static RenderObject _debugActiveLayout; + bool _debugDoingThisLayout = false; + + /// The render object that is actively computing layout. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// null. static RenderObject get debugActiveLayout => _debugActiveLayout; - bool _debugMutationsLocked = false; - bool _debugCanParentUseSize; + static RenderObject _debugActiveLayout; + + /// Whether the parent render object is permitted to use this render object's + /// size. + /// + /// Determined by the `parentUsesSize` parameter to [layout]. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// null. bool get debugCanParentUseSize => _debugCanParentUseSize; - bool get debugCanPerformMutations { - RenderObject node = this; - while (true) { - if (node._doingThisLayoutWithCallback) - return true; - if (node._debugMutationsLocked) - return false; - if (node.parent is! RenderObject) - return true; - node = node.parent; - } + bool _debugCanParentUseSize; + + bool _debugMutationsLocked = false; + + /// Whether tree mutations are currently permitted. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// null. + bool get _debugCanPerformMutations { + bool result; + assert(() { + RenderObject node = this; + while (true) { + if (node._doingThisLayoutWithCallback) { + result = true; + break; + } + if (node._debugMutationsLocked) { + result = false; + break; + } + if (node.parent is! RenderObject) { + result = true; + break; + } + node = node.parent; + } + return true; + }); + return result; } @override @@ -1085,7 +1192,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// debugAssertDoesMeetConstraints(), and should not be checked in /// release mode (where it will always be false). static bool debugCheckingIntrinsics = false; - bool debugAncestorsAlreadyMarkedNeedsLayout() { + bool _debugAncestorsAlreadyMarkedNeedsLayout() { if (_relayoutSubtreeRoot == null) return true; // we haven't yet done layout even once, so there's nothing for us to do RenderObject node = this; @@ -1115,9 +1222,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// computing its layout information, this function will also mark the parent /// as needing layout. void markNeedsLayout() { - assert(debugCanPerformMutations); + assert(_debugCanPerformMutations); if (_needsLayout) { - assert(debugAncestorsAlreadyMarkedNeedsLayout()); + assert(_debugAncestorsAlreadyMarkedNeedsLayout()); return; } _needsLayout = true; @@ -1414,10 +1521,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // PAINTING - bool _debugDoingThisPaint = false; + /// Whether [paint] for this render object is currently running. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// false. bool get debugDoingThisPaint => _debugDoingThisPaint; - static RenderObject _debugActivePaint; + bool _debugDoingThisPaint = false; + + /// The render object that is actively painting. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// null. static RenderObject get debugActivePaint => _debugActivePaint; + static RenderObject _debugActivePaint; /// Whether this render object repaints separately from its parent. /// @@ -1711,7 +1827,15 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { bool _needsSemanticsGeometryUpdate = true; SemanticsNode _semantics; - SemanticsNode get debugSemantics { // only exposed for testing and debugging + /// The semantics of this render object. + /// + /// Exposed only for testing and debugging. To learn about the semantics of + /// render objects in production, register as a listener using + /// [SemanticsNode.addListener]. + /// + /// Only valid when asserts are enabled. In release builds, always returns + /// null. + SemanticsNode get debugSemantics { SemanticsNode result; assert(() { result = _semantics; diff --git a/packages/flutter/lib/src/rendering/performance_overlay.dart b/packages/flutter/lib/src/rendering/performance_overlay.dart index bc7f2b859f..7466b1f5ac 100644 --- a/packages/flutter/lib/src/rendering/performance_overlay.dart +++ b/packages/flutter/lib/src/rendering/performance_overlay.dart @@ -41,9 +41,28 @@ enum PerformanceOverlayOption { visualizeEngineStatistics, } +/// Displays performance statistics. +/// +/// The overlay show two time series. The first shows how much time was required +/// on this thread to produce each frame. The second shows how much time was +/// required on the GPU thread to produce each frame. Ideally, both these values +/// would be less than the total frame budget for the hardware on which the app +/// is running. For example, if the hardware has a screen that updates at 60 Hz, +/// each thread should ideally spend less than 16ms producing each frame. This +/// ideal condition is indicated by a green vertical line for each thread. +/// Otherwise, the performance overlay shows a red vertical line. +/// +/// The simplest way to show the performance overlay is to set +/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] +/// to `true`. class RenderPerformanceOverlay extends RenderBox { - RenderPerformanceOverlay({ int optionsMask: 0, int rasterizerThreshold: 0 }) - : _optionsMask = optionsMask, + /// Creates a performance overlay render object. + /// + /// The [optionsMask] and [rasterizerThreshold] arguments must not be null. + RenderPerformanceOverlay({ + int optionsMask: 0, + int rasterizerThreshold: 0 + }) : _optionsMask = optionsMask, _rasterizerThreshold = rasterizerThreshold; /// The mask is created by shifting 1 by the index of the specific @@ -51,6 +70,7 @@ class RenderPerformanceOverlay extends RenderBox { int get optionsMask => _optionsMask; int _optionsMask; set optionsMask(int mask) { + assert(mask != null); if (mask == _optionsMask) return; _optionsMask = mask; @@ -63,6 +83,7 @@ class RenderPerformanceOverlay extends RenderBox { int get rasterizerThreshold => _rasterizerThreshold; int _rasterizerThreshold; set rasterizerThreshold (int threshold) { + assert(threshold != null); if (threshold == _rasterizerThreshold) return; _rasterizerThreshold = threshold; diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index b3b964cddf..097b8cca99 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -121,11 +121,15 @@ enum HitTestBehavior { /// A RenderProxyBox subclass that allows you to customize the /// hit-testing behavior. abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox { + /// Initializes member variables for subclasses. + /// + /// By default, the [behavior] is [HitTestBehavior.deferToChild]. RenderProxyBoxWithHitTestBehavior({ this.behavior: HitTestBehavior.deferToChild, RenderBox child }) : super(child); + /// How to behave during hit testing. HitTestBehavior behavior; @override @@ -171,6 +175,9 @@ abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox { /// pixels, you could use `const BoxConstraints(minHeight: 50.0)`` as the /// [additionalConstraints]. class RenderConstrainedBox extends RenderProxyBox { + /// Creates a render box that constrains its child. + /// + /// The [additionalConstraints] argument must not be null and must be valid. RenderConstrainedBox({ RenderBox child, BoxConstraints additionalConstraints @@ -257,6 +264,11 @@ class RenderConstrainedBox extends RenderProxyBox { /// Constrains the child's maxWidth and maxHeight if they're otherwise /// unconstrained. class RenderLimitedBox extends RenderProxyBox { + /// Creates a render box that imposes a maxWidth or maxHeight on its child if + /// the child is otherwise unconstrained. + /// + /// The [maxWidth] and [maxHeight] arguments not be null and must be + /// non-negative. RenderLimitedBox({ RenderBox child, double maxWidth: double.INFINITY, @@ -376,13 +388,16 @@ class RenderLimitedBox extends RenderProxyBox { /// will eventually select a size for the child that meets the layout /// constraints but fails to meet the aspect ratio constraints. class RenderAspectRatio extends RenderProxyBox { + /// Creates as render object with a specific aspect ratio. + /// + /// The [aspectRatio] argument must be a finite, positive value. RenderAspectRatio({ RenderBox child, double aspectRatio }) : _aspectRatio = aspectRatio, super(child) { - assert(_aspectRatio > 0.0); - assert(_aspectRatio.isFinite); - assert(_aspectRatio != null); + assert(aspectRatio != null); + assert(aspectRatio > 0.0); + assert(aspectRatio.isFinite); } /// The aspect ratio to attempt to use. @@ -511,7 +526,7 @@ class RenderAspectRatio extends RenderProxyBox { /// /// This class is relatively expensive. Avoid using it where possible. class RenderIntrinsicWidth extends RenderProxyBox { - + /// Creates a render object that sizes itself to its child's intrinsic width. RenderIntrinsicWidth({ double stepWidth, double stepHeight, @@ -618,7 +633,7 @@ class RenderIntrinsicWidth extends RenderProxyBox { /// /// This class is relatively expensive. Avoid using it where possible. class RenderIntrinsicHeight extends RenderProxyBox { - + /// Creates a render object that sizes itself to its child's intrinsic height. RenderIntrinsicHeight({ RenderBox child }) : super(child); @@ -686,7 +701,10 @@ int _getAlphaFromOpacity(double opacity) => (opacity * 255).round(); /// 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. class RenderOpacity extends RenderProxyBox { - RenderOpacity({ RenderBox child, double opacity: 1.0 }) + /// Creates a partially transparent render object. + /// + /// The [opacity] argument must be between 0.0 and 1.0, inclusive. + RenderOpacity({ double opacity: 1.0, RenderBox child }) : _opacity = opacity, _alpha = _getAlphaFromOpacity(opacity), super(child) { assert(opacity != null); assert(opacity >= 0.0 && opacity <= 1.0); @@ -748,12 +766,34 @@ class RenderOpacity extends RenderProxyBox { } } +/// Signature for a function that creates a [Shader] for a given [Rect]. +/// +/// Used by [RenderShaderMask]. typedef Shader ShaderCallback(Rect bounds); +/// Applies a mask generated by a [Shader] to its child. +/// +/// For example, [RenderShaderMask] can be used to gradually fade out the edge +/// of a child by using a [ui.Gradient.linear] mask. class RenderShaderMask extends RenderProxyBox { - RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, TransferMode transferMode }) - : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child); + /// Creates a render object that applies a mask generated by a [Shader] to its child. + /// + /// The [shaderCallback] and [transferMode] arguments must not be null. + RenderShaderMask({ + ShaderCallback shaderCallback, + TransferMode transferMode: TransferMode.modulate, + RenderBox child + }) : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child) { + assert(shaderCallback != null); + assert(transferMode != null); + } + /// 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. + // TODO(abarth): Use the delegate pattern here to avoid generating spurious + // repaints when the ShaderCallback changes identity. ShaderCallback get shaderCallback => _shaderCallback; ShaderCallback _shaderCallback; set shaderCallback (ShaderCallback newShaderCallback) { @@ -764,6 +804,10 @@ class RenderShaderMask extends RenderProxyBox { markNeedsPaint(); } + /// The [TransferMode] to use when applying the shader to the child. + /// + /// The default, [TransferMode.modulate], is useful for applying an alpha blend + /// to the child. Other transfer modes can be used to create other effects. TransferMode get transferMode => _transferMode; TransferMode _transferMode; set transferMode (TransferMode newTransferMode) { @@ -787,12 +831,20 @@ class RenderShaderMask extends RenderProxyBox { } } +/// Applies a filter to the existing painted content and then paints [child]. class RenderBackdropFilter extends RenderProxyBox { + /// Creates a backdrop filter. + /// + /// The [filter] argument must not be null. RenderBackdropFilter({ RenderBox child, ui.ImageFilter filter }) : _filter = filter, super(child) { assert(filter != null); } + /// 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 ui.ImageFilter get filter => _filter; ui.ImageFilter _filter; set filter (ui.ImageFilter newFilter) { @@ -877,8 +929,14 @@ abstract class _RenderCustomClip extends RenderProxyBox { /// Clips its child using a rectangle. /// -/// Prevents its child from painting outside its bounds. +/// By default, [RenderClipRect] prevents its child from painting outside its +/// bounds, but the size and location of the clip can be customized using a +/// custom [clipper]. class RenderClipRect extends _RenderCustomClip { + /// Creates a rectangular clip. + /// + /// If [clipper] is null, the clip will match the layout size and position of + /// the child. RenderClipRect({ RenderBox child, CustomClipper clipper @@ -910,6 +968,7 @@ class RenderClipRect extends _RenderCustomClip { /// y radius values and prevents its child from painting outside that rounded /// rectangle. class RenderClipRRect extends RenderProxyBox { + /// Creates a rounded-rectangular clip. RenderClipRRect({ RenderBox child, double xRadius, @@ -962,9 +1021,14 @@ class RenderClipRRect extends RenderProxyBox { /// Clips its child using an oval. /// -/// Inscribes an oval into its layout dimensions and prevents its child from -/// painting outside that oval. +/// By default, inscribes an oval into its layout dimensions and prevents its +/// child from painting outside that oval, but the size and location of the clip +/// can be customized using a custom [clipper]. class RenderClipOval extends _RenderCustomClip { + /// Creates an oval-shaped clip. + /// + /// If [clipper] is null, the oval will be inscribed into the layout size and + /// position of the child. RenderClipOval({ RenderBox child, CustomClipper clipper @@ -1018,6 +1082,12 @@ class RenderClipOval extends _RenderCustomClip { /// * To clip to an oval or circle, consider [RenderClipOval]. /// * To clip to a rounded rectangle, consider [RenderClipRRect]. class RenderClipPath extends _RenderCustomClip { + /// 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 [RenderClipRect], which can achieve the same effect more + /// efficiently. RenderClipPath({ RenderBox child, CustomClipper clipper @@ -1148,6 +1218,9 @@ class RenderDecoratedBox extends RenderProxyBox { /// Applies a transformation before painting its child. class RenderTransform extends RenderProxyBox { + /// Creates a render object that transforms its child. + /// + /// The [transform] argument must not be null. RenderTransform({ Matrix4 transform, Offset origin, @@ -1312,12 +1385,16 @@ class RenderTransform extends RenderProxyBox { } } -/// Applies a translation transformation before painting its child. The -/// translation is expressed as a [FractionalOffset] relative to the +/// Applies a translation transformation before painting its child. +/// +/// The translation is expressed as a [FractionalOffset] relative to the /// RenderFractionalTranslation box's size. Hit tests will only be detected /// inside the bounds of the RenderFractionalTranslation, even if the contents /// are offset such that they overflow. class RenderFractionalTranslation extends RenderProxyBox { + /// Creates a render object that translates its child's painting. + /// + /// The [translation] argument must not be null. RenderFractionalTranslation({ FractionalOffset translation, this.transformHitTests: true, @@ -1472,20 +1549,29 @@ abstract class CustomPainter { bool hitTest(Point position) => null; } -/// Delegates its painting +/// Provides a canvas on which to draw during the paint phase. /// -/// When asked to paint, custom paint first asks painter to paint with the -/// current canvas and then paints its children. After painting its children, -/// custom paint asks foregroundPainter to paint. The coodinate system of the -/// canvas matches the coordinate system of the custom paint object. The -/// painters are expected to paint within a rectangle starting at the origin -/// and encompassing a region of the given size. If the painters paints outside +/// When asked to paint, [CustomPaint] first ask its [painter] to paint on the +/// current canvas, then it paints its child, and then, after painting its +/// child, it ask its [foregroundPainter] to paint. The coodinate system of the +/// canvas matches the coordinate system of the [CustomPaint] object. The +/// painters are expected to paint within a rectangle starting at the origin and +/// encompassing a region of the given size. (If the painters paints outside /// those bounds, there might be insufficient memory allocated to rasterize the -/// painting commands and the resulting behavior is undefined. +/// painting commands and the resulting behavior is undefined.) /// -/// Because custom paint calls its painters during paint, you cannot dirty -/// layout or paint information during the callback. +/// Painters are implemented by subclassing [CustomPainter]. +/// +/// Because custom paint calls its painters during paint, you cannot mark the +/// tree as needing a new layout during the callback (the layout for this frame +/// has already happened). +/// +/// See also: +/// +/// * [CustomPainter], +/// * [Canvas] class RenderCustomPaint extends RenderProxyBox { + /// Creates a render object that delgates its painting. RenderCustomPaint({ CustomPainter painter, CustomPainter foregroundPainter, @@ -1633,13 +1719,31 @@ class RenderCustomPaint extends RenderProxyBox { } } +/// Signature for listening to [PointerDownEvent] events. +/// +/// Used by [Listener] and [RenderPointerListener]. typedef void PointerDownEventListener(PointerDownEvent event); + +/// Signature for listening to [PointerMoveEvent] events. +/// +/// Used by [Listener] and [RenderPointerListener]. typedef void PointerMoveEventListener(PointerMoveEvent event); + +/// Signature for listening to [PointerUpEvent] events. +/// +/// Used by [Listener] and [RenderPointerListener]. typedef void PointerUpEventListener(PointerUpEvent event); + +/// Signature for listening to [PointerCancelEvent] events. +/// +/// Used by [Listener] and [RenderPointerListener]. typedef void PointerCancelEventListener(PointerCancelEvent event); -/// Calls the callbacks in response to pointer events. +/// Calls callbacks in response to pointer events. class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { + /// Creates a render object that forwards point events to callbacks. + /// + /// The [behavior] argument defaults to [HitTestBehavior.deferToChild]. RenderPointerListener({ this.onPointerDown, this.onPointerMove, @@ -1649,9 +1753,16 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { RenderBox child }) : super(behavior: behavior, child: child); + /// Called when a pointer comes into contact with the screen at this object. PointerDownEventListener onPointerDown; + + /// Called when a pointer that triggered an [onPointerDown] changes position. PointerMoveEventListener onPointerMove; + + /// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen. PointerUpEventListener onPointerUp; + + /// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver. PointerCancelEventListener onPointerCancel; @override @@ -1710,6 +1821,7 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { /// was not. These counts can also be inspected programmatically using /// [debugAsymmetricPaintCount] and [debugSymmetricPaintCount] respectively. class RenderRepaintBoundary extends RenderProxyBox { + /// Creates a repaint boundary around [child]. RenderRepaintBoundary({ RenderBox child }) : super(child); @override @@ -1720,7 +1832,8 @@ class RenderRepaintBoundary extends RenderProxyBox { /// paint at different times. When both paint at the same time, the repaint /// boundary is redundant, and may be actually making performance worse. /// - /// Only valid in checked mode. In release builds, always returns zero. + /// Only valid when asserts are enabled. In release builds, always returns + /// zero. /// /// Can be reset using [debugResetMetrics]. See [debugAsymmetricPaintCount] /// for the corresponding count of times where only the parent or only the @@ -1735,7 +1848,8 @@ class RenderRepaintBoundary extends RenderProxyBox { /// child, it can improve performance by reducing the number of paint /// operations that have to be recorded each frame. /// - /// Only valid in checked mode. In release builds, always returns zero. + /// Only valid when asserts are enabled. In release builds, always returns + /// zero. /// /// Can be reset using [debugResetMetrics]. See [debugSymmetricPaintCount] for /// the corresponding count of times where both the parent and the child @@ -1746,7 +1860,7 @@ class RenderRepaintBoundary extends RenderProxyBox { /// Resets the [debugSymmetricPaintCount] and [debugAsymmetricPaintCount] /// counts to zero. /// - /// Only valid in checked mode. Does nothing in release builds. + /// Only valid when asserts are enabled. Does nothing in release builds. void debugResetMetrics() { assert(() { _debugSymmetricPaintCount = 0; @@ -1813,6 +1927,10 @@ class RenderRepaintBoundary extends RenderProxyBox { /// the semantics layer (and thus e.g. accessibility tools). If /// [ignoringSemantics] is null, it uses the value of [ignoring]. class RenderIgnorePointer extends RenderProxyBox { + /// Creates a render object that is invisivle to hit testing. + /// + /// The [ignoring] argument must not be null. If [ignoringSemantics], this + /// render object will be ignored for semantics if [ignoring] is true. RenderIgnorePointer({ RenderBox child, bool ignoring: true, @@ -1821,6 +1939,10 @@ class RenderIgnorePointer extends RenderProxyBox { assert(_ignoring != null); } + /// Whether this render object is ignored during hit testing. + /// + /// Regardless of whether this render object is ignored during hit testing, it + /// will still consume space during layout and be visible during painting. bool get ignoring => _ignoring; bool _ignoring; set ignoring(bool value) { @@ -1832,6 +1954,11 @@ class RenderIgnorePointer extends RenderProxyBox { markNeedsSemanticsUpdate(); } + /// Whether the semantics of this render object is ignored when compiling the semantics tree. + /// + /// If null, defaults to value of [ignoring]. + /// + /// See [SemanticsNode] for additional information about the semantics tree. bool get ignoringSemantics => _ignoringSemantics; bool _ignoringSemantics; set ignoringSemantics(bool value) { @@ -1869,6 +1996,9 @@ class RenderIgnorePointer extends RenderProxyBox { /// Holds opaque meta data in the render tree. class RenderMetaData extends RenderProxyBoxWithHitTestBehavior { + /// Creates a render object that hold opaque metadata. + /// + /// The [behavior] argument defaults to [HitTestBehavior.deferToChild]. RenderMetaData({ this.metaData, HitTestBehavior behavior: HitTestBehavior.deferToChild, diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart index ab8954d5a8..e210cd9778 100644 --- a/packages/flutter/lib/src/rendering/shifted_box.dart +++ b/packages/flutter/lib/src/rendering/shifted_box.dart @@ -91,6 +91,9 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi /// size. Padding then sizes itself to its child's size, inflated by the /// padding, effectively creating empty space around the child. class RenderPadding extends RenderShiftedBox { + /// Creates a render object that insets its child. + /// + /// The [padding] argument must not be null and must have non-negative insets. RenderPadding({ EdgeInsets padding, RenderBox child @@ -219,12 +222,16 @@ class RenderPadding extends RenderShiftedBox { } } +/// Abstract class for one-child-layout render boxes that use a +/// [FractionalOffset] to align their children. abstract class RenderAligningShiftedBox extends RenderShiftedBox { + /// Initializes member variables for subclasses. + /// + /// The [alignment] argument must not be null. RenderAligningShiftedBox({ - RenderBox child, - FractionalOffset alignment: FractionalOffset.center - }) : _alignment = alignment, - super(child) { + FractionalOffset alignment: FractionalOffset.center, + RenderBox child + }) : _alignment = alignment, super(child) { assert(alignment != null && alignment.dx != null && alignment.dy != null); } @@ -274,7 +281,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox { } } -/// Aligns its child box within itself. +/// Positions its child using a [FractionalOffset]. /// /// 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, @@ -285,6 +292,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox { /// dimensions. Using widthFactor and heightFactor you can force this latter /// behavior in all cases. class RenderPositionedBox extends RenderAligningShiftedBox { + /// Creates a render object that positions its child. RenderPositionedBox({ RenderBox child, double widthFactor, @@ -427,6 +435,7 @@ class RenderPositionedBox extends RenderAligningShiftedBox { /// child inside a larger parent, use [RenderPositionedBox] and /// [RenderConstrainedBox] rather than RenderOverflowBox. class RenderConstrainedOverflowBox extends RenderAligningShiftedBox { + /// Creates a render object that lets its child overflow itself. RenderConstrainedOverflowBox({ RenderBox child, double minWidth, @@ -543,9 +552,12 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox { } } -/// A render box that's a specific size but passes its original constraints +/// A render box that is a specific size but passes its original constraints /// through to its child, which will probably overflow. class RenderSizedOverflowBox extends RenderAligningShiftedBox { + /// Creates a render box of a given size that lets its child overflow. + /// + /// The [requestedSize] argument must not be null. RenderSizedOverflowBox({ RenderBox child, Size requestedSize, @@ -617,6 +629,10 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox { /// /// It then tries to size itself to the size of its child. class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox { + /// Creates a render box that sizes its child to a fraction of the total available space. + /// + /// If non-null, the [widthFactor] and [heightFactor] arguments must be + /// non-negative. RenderFractionallySizedOverflowBox({ RenderBox child, double widthFactor, @@ -755,6 +771,9 @@ class SingleChildLayoutDelegate { /// of the parent, but the size of the parent cannot depend on the size of the /// child. class RenderCustomSingleChildLayoutBox extends RenderShiftedBox { + /// Creates a render box that defers its layout to a delgate. + /// + /// The [delegate] argument must not be null. RenderCustomSingleChildLayoutBox({ RenderBox child, SingleChildLayoutDelegate delegate diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index 29cf3c7d00..743b912660 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -48,6 +48,9 @@ class ViewConfiguration { /// bootstrapping the rendering pipeline. The view has a unique child /// [RenderBox], which is required to fill the entire output surface. class RenderView extends RenderObject with RenderObjectWithChildMixin { + /// Creates the root of the render tree. + /// + /// Typically created by the binding (e.g., [RendererBinding]). RenderView({ RenderBox child, this.timeForRotation: const Duration(microseconds: 83333), @@ -115,6 +118,13 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin assert(false); // nobody tells the screen to rotate, the whole rotate() dance is started from our performResize() } + /// Determines the set of render objects located at the given position. + /// + /// Returns true if the given point is contained in this render object or one + /// of its descendants. Adds any render objects that contain the point to the + /// given hit test result. + /// + /// The [position] argument is in the coordinate system of the render view. bool hitTest(HitTestResult result, { Point position }) { if (child != null) child.hitTest(result, position: position); diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 244f065c6d..f0e1be48e8 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -95,7 +95,14 @@ class Opacity extends SingleChildRenderObjectWidget { } } +/// Applies a mask generated by a [Shader] to its child. +/// +/// For example, [ShaderMask] can be used to gradually fade out the edge +/// of a child by using a [ui.Gradient.linear] mask. class ShaderMask extends SingleChildRenderObjectWidget { + /// Creates a widget that applies a mask generated by a [Shader] to its child. + /// + /// The [shaderCallback] and [transferMode] arguments must not be null. ShaderMask({ Key key, this.shaderCallback, @@ -106,7 +113,16 @@ class ShaderMask extends SingleChildRenderObjectWidget { assert(transferMode != null); } + /// 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. final ShaderCallback shaderCallback; + + /// The [TransferMode] to use when applying the shader to the child. + /// + /// The default, [TransferMode.modulate], is useful for applying an alpha blend + /// to the child. Other transfer modes can be used to create other effects. final TransferMode transferMode; @override @@ -125,7 +141,11 @@ class ShaderMask extends SingleChildRenderObjectWidget { } } +/// Applies a filter to the existing painted content and then paints [child]. class BackdropFilter extends SingleChildRenderObjectWidget { + /// Creates a backdrop filter. + /// + /// The [filter] argument must not be null. BackdropFilter({ Key key, this.filter, @@ -134,6 +154,10 @@ class BackdropFilter extends SingleChildRenderObjectWidget { assert(filter != null); } + /// 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 final ui.ImageFilter filter; @override @@ -183,15 +207,14 @@ class DecoratedBox extends SingleChildRenderObjectWidget { /// Provides a canvas on which to draw during the paint phase. /// -/// When asked to paint, [CustomPaint] objects first ask their [painter] to -/// paint on the current canvas, then they paint their children, and then, after -/// painting their children, ask their [foregroundPainter] to paint. The -/// coodinate system of the canvas matches the coordinate system of the -/// [CustomPaint] object. The painters are expected to paint within a rectangle -/// starting at the origin and encompassing a region of the given size. (If the -/// painters paints outside those bounds, there might be insufficient memory -/// allocated to rasterize the painting commands and the resulting behavior is -/// undefined.) +/// When asked to paint, [CustomPaint] first ask its [painter] to paint on the +/// current canvas, then it paints its child, and then, after painting its +/// child, it ask its [foregroundPainter] to paint. The coodinate system of the +/// canvas matches the coordinate system of the [CustomPaint] object. The +/// painters are expected to paint within a rectangle starting at the origin and +/// encompassing a region of the given size. (If the painters paints outside +/// those bounds, there might be insufficient memory allocated to rasterize the +/// painting commands and the resulting behavior is undefined.) /// /// Painters are implemented by subclassing [CustomPainter]. /// @@ -199,8 +222,12 @@ class DecoratedBox extends SingleChildRenderObjectWidget { /// tree as needing a new layout during the callback (the layout for this frame /// has already happened). /// -/// See: [CustomPainter], [Canvas]. +/// See also: +/// +/// * [CustomPainter], +/// * [Canvas] class CustomPaint extends SingleChildRenderObjectWidget { + /// Creates a widget that delgates its painting. CustomPaint({ Key key, this.painter, this.foregroundPainter, Widget child }) : super(key: key, child: child); @@ -233,8 +260,14 @@ class CustomPaint extends SingleChildRenderObjectWidget { /// Clips its child using a rectangle. /// -/// Prevents its child from painting outside its bounds. +/// By default, [ClipRect] prevents its child from painting outside its +/// bounds, but the size and location of the clip can be customized using a +/// custome [clipper]. class ClipRect extends SingleChildRenderObjectWidget { + /// Creates a rectangular clip. + /// + /// If [clipper] is null, the clip will match the layout size and position of + /// the child. ClipRect({ Key key, this.clipper, Widget child }) : super(key: key, child: child); /// If non-null, determines which clip to use. @@ -260,6 +293,7 @@ class ClipRect extends SingleChildRenderObjectWidget { /// y radius values and prevents its child from painting outside that rounded /// rectangle. class ClipRRect extends SingleChildRenderObjectWidget { + /// Creates a rounded-rectangular clip. ClipRRect({ Key key, this.xRadius, this.yRadius, Widget child }) : super(key: key, child: child); @@ -288,9 +322,14 @@ class ClipRRect extends SingleChildRenderObjectWidget { /// Clips its child using an oval. /// -/// Inscribes an oval into its layout dimensions and prevents its child from -/// painting outside that oval. +/// By default, inscribes an oval into its layout dimensions and prevents its +/// child from painting outside that oval, but the size and location of the clip +/// can be customized using a custom [clipper]. class ClipOval extends SingleChildRenderObjectWidget { + /// Creates an oval-shaped clip. + /// + /// If [clipper] is null, the oval will be inscribed into the layout size and + /// position of the child. ClipOval({ Key key, this.clipper, Widget child }) : super(key: key, child: child); /// If non-null, determines which clip to use. @@ -331,6 +370,12 @@ class ClipOval extends SingleChildRenderObjectWidget { /// * To clip to an oval or circle, consider [ClipOval]. /// * To clip to a rounded rectangle, consider [ClipRRect]. class ClipPath extends SingleChildRenderObjectWidget { + /// 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. ClipPath({ Key key, this.clipper, Widget child }) : super(key: key, child: child); /// If non-null, determines which clip to use. @@ -359,8 +404,17 @@ class ClipPath extends SingleChildRenderObjectWidget { /// Applies a transformation before painting its child. class Transform extends SingleChildRenderObjectWidget { - Transform({ Key key, this.transform, this.origin, this.alignment, this.transformHitTests: true, Widget child }) - : super(key: key, child: child) { + /// Creates a widget that transforms its child. + /// + /// The [transform] argument must not be null. + Transform({ + Key key, + this.transform, + this.origin, + this.alignment, + this.transformHitTests: true, + Widget child + }) : super(key: key, child: child) { assert(transform != null); } @@ -404,8 +458,15 @@ class Transform extends SingleChildRenderObjectWidget { /// Applies a translation expressed as a fraction of the box's size before /// painting its child. class FractionalTranslation extends SingleChildRenderObjectWidget { - FractionalTranslation({ Key key, this.translation, this.transformHitTests: true, Widget child }) - : super(key: key, child: child) { + /// Creates a widget that translates its child's painting. + /// + /// The [translation] argument must not be null. + FractionalTranslation({ + Key key, + this.translation, + this.transformHitTests: true, + Widget child + }) : super(key: key, child: child) { assert(translation != null); } @@ -763,6 +824,10 @@ class ConstrainedBox extends SingleChildRenderObjectWidget { /// the child according to a [FractionalOffset] value) /// * [OverflowBox] class FractionallySizedBox extends SingleChildRenderObjectWidget { + /// 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. FractionallySizedBox({ Key key, this.alignment: FractionalOffset.center, @@ -771,6 +836,8 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget { Widget child }) : super(key: key, child: child) { assert(alignment != null && alignment.dx != null && alignment.dy != null); + assert(widthFactor == null || widthFactor >= 0.0); + assert(heightFactor == null || heightFactor >= 0.0); } /// If non-null, the fraction of the incoming width given to the child. @@ -863,11 +930,12 @@ class LimitedBox extends SingleChildRenderObjectWidget { } } -/// A render object that imposes different constraints on its child than it gets +/// A widget that imposes different constraints on its child than it gets /// from its parent, possibly allowing the child to overflow the parent. /// /// See [RenderOverflowBox] for details. class OverflowBox extends SingleChildRenderObjectWidget { + /// Creates a widget that lets its child overflow itself. OverflowBox({ Key key, this.alignment: FractionalOffset.center, @@ -939,7 +1007,12 @@ class OverflowBox extends SingleChildRenderObjectWidget { } } +/// A widget that is a specific size but passes its original constraints +/// through to its child, which will probably overflow. class SizedOverflowBox extends SingleChildRenderObjectWidget { + /// Creates a widget of a given size that lets its child overflow. + /// + /// The [requestedSize] argument must not be null. SizedOverflowBox({ Key key, this.alignment: FractionalOffset.center, @@ -960,6 +1033,7 @@ class SizedOverflowBox extends SingleChildRenderObjectWidget { /// with the center of the parent. final FractionalOffset alignment; + /// The size this render box should attempt to be. final Size size; @override @@ -2762,7 +2836,14 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { // EVENT HANDLING +/// Calls callbacks in response to pointer events. +/// +/// Rather than listening for raw pointer events, consider listening for +/// higher-level gestures using [GestureDetector]. class Listener extends SingleChildRenderObjectWidget { + /// Creates a widget that forwards point events to callbacks. + /// + /// The [behavior] argument defaults to [HitTestBehavior.deferToChild]. Listener({ Key key, Widget child, @@ -2775,10 +2856,19 @@ class Listener extends SingleChildRenderObjectWidget { assert(behavior != null); } + /// Called when a pointer comes into contact with the screen at this object. final PointerDownEventListener onPointerDown; + + /// Called when a pointer that triggered an [onPointerDown] changes position. final PointerMoveEventListener onPointerMove; + + /// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen. final PointerUpEventListener onPointerUp; + + /// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver. final PointerCancelEventListener onPointerCancel; + + /// How to behave during hit testing. final HitTestBehavior behavior; @override @@ -2857,12 +2947,42 @@ class RepaintBoundary extends SingleChildRenderObjectWidget { RenderRepaintBoundary createRenderObject(BuildContext context) => new RenderRepaintBoundary(); } +/// Is invisible during hit testing. +/// +/// When [ignoring] is `true`, this widget (and its subtree) is invisible +/// to hit testing. It still consumes space during layout and paints its child +/// as usual. It just cannot be the target of located events because it returns +/// `false` from [hitTest]. +/// +/// When [ignoringSemantics] is `true`, the subtree will be invisible to +/// the semantics layer (and thus e.g. accessibility tools). If +/// [ignoringSemantics] is null, it uses the value of [ignoring]. class IgnorePointer extends SingleChildRenderObjectWidget { - IgnorePointer({ Key key, Widget child, this.ignoring: true, this.ignoringSemantics }) - : super(key: key, child: child); + /// Creates a widget that is invisivle to hit testing. + /// + /// The [ignoring] argument must not be null. If [ignoringSemantics], this + /// render object will be ignored for semantics if [ignoring] is true. + IgnorePointer({ + Key key, + Widget child, + this.ignoring: true, + this.ignoringSemantics + }) : super(key: key, child: child) { + assert(ignoring != null); + } + /// 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. final bool ignoring; - final bool ignoringSemantics; // if null, defaults to value of ignoring + + /// 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; @override RenderIgnorePointer createRenderObject(BuildContext context) => new RenderIgnorePointer( @@ -2878,6 +2998,45 @@ class IgnorePointer extends SingleChildRenderObjectWidget { } } +/// Holds opaque meta data in the render tree. +class MetaData extends SingleChildRenderObjectWidget { + /// Creates a widget that hold opaque metadata. + /// + /// The [behavior] argument defaults to [HitTestBehavior.deferToChild]. + MetaData({ + Key key, + Widget child, + this.metaData, + this.behavior: HitTestBehavior.deferToChild + }) : 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 description) { + super.debugFillDescription(description); + description.add('behavior: $behavior'); + description.add('metaData: $metaData'); + } +} + // UTILITY NODES @@ -2979,38 +3138,6 @@ class ExcludeSemantics extends SingleChildRenderObjectWidget { RenderExcludeSemantics createRenderObject(BuildContext context) => new RenderExcludeSemantics(); } -class MetaData extends SingleChildRenderObjectWidget { - MetaData({ - Key key, - Widget child, - this.metaData, - this.behavior: HitTestBehavior.deferToChild - }) : super(key: key, child: child); - - final dynamic metaData; - 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 description) { - super.debugFillDescription(description); - description.add('behavior: $behavior'); - description.add('metaData: $metaData'); - } -} - /// Always builds the given child. /// /// Useful for attaching a key to an existing widget. diff --git a/packages/flutter/lib/src/widgets/performance_overlay.dart b/packages/flutter/lib/src/widgets/performance_overlay.dart index 028f5af5a4..f26cd2d02a 100644 --- a/packages/flutter/lib/src/widgets/performance_overlay.dart +++ b/packages/flutter/lib/src/widgets/performance_overlay.dart @@ -13,8 +13,9 @@ import 'framework.dart'; /// required on the GPU thread to produce each frame. Ideally, both these values /// would be less than the total frame budget for the hardware on which the app /// is running. For example, if the hardware has a screen that updates at 60 Hz, -/// each thread should ideally spend less than 16 ms producing each frame. This +/// each thread should ideally spend less than 16ms producing each frame. This /// ideal condition is indicated by a green vertical line for each thread. +/// Otherwise, the performance overlay shows a red vertical line. /// /// The simplest way to show the performance overlay is to set /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]