Commit 7cf4c694 authored by Adam Barth's avatar Adam Barth

Complete docs for RenderObject (#4266)

parent 76772608
......@@ -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<RenderObject> _nodesNeedingLayout = <RenderObject>[];
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<RenderObject> _nodesNeedingPaint = <RenderObject>[];
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<RenderObject> _nodesNeedingSemantics = <RenderObject>[];
/// 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 {
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)
return true;
if (node._debugMutationsLocked)
return false;
if (node.parent is! RenderObject)
return 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;
......
......@@ -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;
......
......@@ -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<T> 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<Rect> {
/// Creates a rectangular clip.
///
/// If [clipper] is null, the clip will match the layout size and position of
/// the child.
RenderClipRect({
RenderBox child,
CustomClipper<Rect> clipper
......@@ -910,6 +968,7 @@ class RenderClipRect extends _RenderCustomClip<Rect> {
/// 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<Rect> {
/// 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<Rect> clipper
......@@ -1018,6 +1082,12 @@ class RenderClipOval extends _RenderCustomClip<Rect> {
/// * To clip to an oval or circle, consider [RenderClipOval].
/// * To clip to a rounded rectangle, consider [RenderClipRRect].
class RenderClipPath extends _RenderCustomClip<Path> {
/// 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<Path> 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.)
///
/// 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).
///
/// Because custom paint calls its painters during paint, you cannot dirty
/// layout or paint information during the callback.
/// 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,
......
......@@ -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
......
......@@ -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<RenderBox> {
/// 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<RenderBox>
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);
......
......@@ -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<String> 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<String> 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.
......
......@@ -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]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment