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 { ...@@ -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 { 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 }); 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; 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() { void requestVisualUpdate() {
if (onNeedVisualUpdate != null) if (onNeedVisualUpdate != null)
onNeedVisualUpdate(); onNeedVisualUpdate();
} }
List<RenderObject> _nodesNeedingLayout = <RenderObject>[]; 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 get debugDoingLayout => _debugDoingLayout;
bool _debugDoingLayout = false;
/// Update the layout information for all dirty render objects. /// Update the layout information for all dirty render objects.
/// ///
/// This function is one of the core stages of the rendering pipeline. Layout /// This function is one of the core stages of the rendering pipeline. Layout
...@@ -789,8 +843,15 @@ class PipelineOwner { ...@@ -789,8 +843,15 @@ class PipelineOwner {
} }
List<RenderObject> _nodesNeedingPaint = <RenderObject>[]; 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 get debugDoingPaint => _debugDoingPaint;
bool _debugDoingPaint = false;
/// Update the display lists for all render objects. /// Update the display lists for all render objects.
/// ///
/// This function is one of the core stages of the rendering pipeline. /// This function is one of the core stages of the rendering pipeline.
...@@ -820,6 +881,13 @@ class PipelineOwner { ...@@ -820,6 +881,13 @@ class PipelineOwner {
bool _debugDoingSemantics = false; bool _debugDoingSemantics = false;
List<RenderObject> _nodesNeedingSemantics = <RenderObject>[]; 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() { void flushSemantics() {
Timeline.startSync('Semantics'); Timeline.startSync('Semantics');
assert(_semanticsEnabled); assert(_semanticsEnabled);
...@@ -878,7 +946,7 @@ void _doNothing() { } ...@@ -878,7 +946,7 @@ void _doNothing() { }
/// The [RenderBox] subclass introduces the opinion that the layout /// The [RenderBox] subclass introduces the opinion that the layout
/// system uses cartesian coordinates. /// system uses cartesian coordinates.
abstract class RenderObject extends AbstractNode implements HitTestTarget { abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// Initializes internal fields for subclasses.
RenderObject() { RenderObject() {
_needsCompositing = isRepaintBoundary || alwaysNeedsCompositing; _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
_performLayout = performLayout; _performLayout = performLayout;
...@@ -919,7 +987,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -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 /// You can call this function to set up the parent data for child before the
/// child is added to the parent's child list. /// child is added to the parent's child list.
void setupParentData(RenderObject child) { void setupParentData(RenderObject child) {
assert(debugCanPerformMutations); assert(_debugCanPerformMutations);
if (child.parentData is! ParentData) if (child.parentData is! ParentData)
child.parentData = new ParentData(); child.parentData = new ParentData();
} }
...@@ -930,7 +998,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -930,7 +998,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// in other cases will lead to an inconsistent tree and probably cause crashes. /// in other cases will lead to an inconsistent tree and probably cause crashes.
@override @override
void adoptChild(RenderObject child) { void adoptChild(RenderObject child) {
assert(debugCanPerformMutations); assert(_debugCanPerformMutations);
assert(child != null); assert(child != null);
setupParentData(child); setupParentData(child);
super.adoptChild(child); super.adoptChild(child);
...@@ -944,7 +1012,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -944,7 +1012,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// in other cases will lead to an inconsistent tree and probably cause crashes. /// in other cases will lead to an inconsistent tree and probably cause crashes.
@override @override
void dropChild(RenderObject child) { void dropChild(RenderObject child) {
assert(debugCanPerformMutations); assert(_debugCanPerformMutations);
assert(child != null); assert(child != null);
assert(child.parentData != null); assert(child.parentData != null);
child._cleanRelayoutSubtreeRoot(); child._cleanRelayoutSubtreeRoot();
...@@ -1005,26 +1073,65 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -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 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; 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; static RenderObject get debugActiveLayout => _debugActiveLayout;
bool _debugMutationsLocked = false; static RenderObject _debugActiveLayout;
bool _debugCanParentUseSize;
/// 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 debugCanParentUseSize => _debugCanParentUseSize;
bool get debugCanPerformMutations { bool _debugCanParentUseSize;
RenderObject node = this;
while (true) { bool _debugMutationsLocked = false;
if (node._doingThisLayoutWithCallback)
return true; /// Whether tree mutations are currently permitted.
if (node._debugMutationsLocked) ///
return false; /// Only valid when asserts are enabled. In release builds, always returns
if (node.parent is! RenderObject) /// null.
return true; bool get _debugCanPerformMutations {
node = node.parent; 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 @override
...@@ -1085,7 +1192,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1085,7 +1192,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// debugAssertDoesMeetConstraints(), and should not be checked in /// debugAssertDoesMeetConstraints(), and should not be checked in
/// release mode (where it will always be false). /// release mode (where it will always be false).
static bool debugCheckingIntrinsics = false; static bool debugCheckingIntrinsics = false;
bool debugAncestorsAlreadyMarkedNeedsLayout() { bool _debugAncestorsAlreadyMarkedNeedsLayout() {
if (_relayoutSubtreeRoot == null) if (_relayoutSubtreeRoot == null)
return true; // we haven't yet done layout even once, so there's nothing for us to do return true; // we haven't yet done layout even once, so there's nothing for us to do
RenderObject node = this; RenderObject node = this;
...@@ -1115,9 +1222,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1115,9 +1222,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// computing its layout information, this function will also mark the parent /// computing its layout information, this function will also mark the parent
/// as needing layout. /// as needing layout.
void markNeedsLayout() { void markNeedsLayout() {
assert(debugCanPerformMutations); assert(_debugCanPerformMutations);
if (_needsLayout) { if (_needsLayout) {
assert(debugAncestorsAlreadyMarkedNeedsLayout()); assert(_debugAncestorsAlreadyMarkedNeedsLayout());
return; return;
} }
_needsLayout = true; _needsLayout = true;
...@@ -1414,10 +1521,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1414,10 +1521,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
// PAINTING // 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; 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 get debugActivePaint => _debugActivePaint;
static RenderObject _debugActivePaint;
/// Whether this render object repaints separately from its parent. /// Whether this render object repaints separately from its parent.
/// ///
...@@ -1711,7 +1827,15 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1711,7 +1827,15 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
bool _needsSemanticsGeometryUpdate = true; bool _needsSemanticsGeometryUpdate = true;
SemanticsNode _semantics; 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; SemanticsNode result;
assert(() { assert(() {
result = _semantics; result = _semantics;
......
...@@ -41,9 +41,28 @@ enum PerformanceOverlayOption { ...@@ -41,9 +41,28 @@ enum PerformanceOverlayOption {
visualizeEngineStatistics, 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 { class RenderPerformanceOverlay extends RenderBox {
RenderPerformanceOverlay({ int optionsMask: 0, int rasterizerThreshold: 0 }) /// Creates a performance overlay render object.
: _optionsMask = optionsMask, ///
/// The [optionsMask] and [rasterizerThreshold] arguments must not be null.
RenderPerformanceOverlay({
int optionsMask: 0,
int rasterizerThreshold: 0
}) : _optionsMask = optionsMask,
_rasterizerThreshold = rasterizerThreshold; _rasterizerThreshold = rasterizerThreshold;
/// The mask is created by shifting 1 by the index of the specific /// The mask is created by shifting 1 by the index of the specific
...@@ -51,6 +70,7 @@ class RenderPerformanceOverlay extends RenderBox { ...@@ -51,6 +70,7 @@ class RenderPerformanceOverlay extends RenderBox {
int get optionsMask => _optionsMask; int get optionsMask => _optionsMask;
int _optionsMask; int _optionsMask;
set optionsMask(int mask) { set optionsMask(int mask) {
assert(mask != null);
if (mask == _optionsMask) if (mask == _optionsMask)
return; return;
_optionsMask = mask; _optionsMask = mask;
...@@ -63,6 +83,7 @@ class RenderPerformanceOverlay extends RenderBox { ...@@ -63,6 +83,7 @@ class RenderPerformanceOverlay extends RenderBox {
int get rasterizerThreshold => _rasterizerThreshold; int get rasterizerThreshold => _rasterizerThreshold;
int _rasterizerThreshold; int _rasterizerThreshold;
set rasterizerThreshold (int threshold) { set rasterizerThreshold (int threshold) {
assert(threshold != null);
if (threshold == _rasterizerThreshold) if (threshold == _rasterizerThreshold)
return; return;
_rasterizerThreshold = threshold; _rasterizerThreshold = threshold;
......
...@@ -121,11 +121,15 @@ enum HitTestBehavior { ...@@ -121,11 +121,15 @@ enum HitTestBehavior {
/// A RenderProxyBox subclass that allows you to customize the /// A RenderProxyBox subclass that allows you to customize the
/// hit-testing behavior. /// hit-testing behavior.
abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox { abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox {
/// Initializes member variables for subclasses.
///
/// By default, the [behavior] is [HitTestBehavior.deferToChild].
RenderProxyBoxWithHitTestBehavior({ RenderProxyBoxWithHitTestBehavior({
this.behavior: HitTestBehavior.deferToChild, this.behavior: HitTestBehavior.deferToChild,
RenderBox child RenderBox child
}) : super(child); }) : super(child);
/// How to behave during hit testing.
HitTestBehavior behavior; HitTestBehavior behavior;
@override @override
...@@ -171,6 +175,9 @@ abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox { ...@@ -171,6 +175,9 @@ abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox {
/// pixels, you could use `const BoxConstraints(minHeight: 50.0)`` as the /// pixels, you could use `const BoxConstraints(minHeight: 50.0)`` as the
/// [additionalConstraints]. /// [additionalConstraints].
class RenderConstrainedBox extends RenderProxyBox { class RenderConstrainedBox extends RenderProxyBox {
/// Creates a render box that constrains its child.
///
/// The [additionalConstraints] argument must not be null and must be valid.
RenderConstrainedBox({ RenderConstrainedBox({
RenderBox child, RenderBox child,
BoxConstraints additionalConstraints BoxConstraints additionalConstraints
...@@ -257,6 +264,11 @@ class RenderConstrainedBox extends RenderProxyBox { ...@@ -257,6 +264,11 @@ class RenderConstrainedBox extends RenderProxyBox {
/// Constrains the child's maxWidth and maxHeight if they're otherwise /// Constrains the child's maxWidth and maxHeight if they're otherwise
/// unconstrained. /// unconstrained.
class RenderLimitedBox extends RenderProxyBox { 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({ RenderLimitedBox({
RenderBox child, RenderBox child,
double maxWidth: double.INFINITY, double maxWidth: double.INFINITY,
...@@ -376,13 +388,16 @@ class RenderLimitedBox extends RenderProxyBox { ...@@ -376,13 +388,16 @@ class RenderLimitedBox extends RenderProxyBox {
/// will eventually select a size for the child that meets the layout /// will eventually select a size for the child that meets the layout
/// constraints but fails to meet the aspect ratio constraints. /// constraints but fails to meet the aspect ratio constraints.
class RenderAspectRatio extends RenderProxyBox { class RenderAspectRatio extends RenderProxyBox {
/// Creates as render object with a specific aspect ratio.
///
/// The [aspectRatio] argument must be a finite, positive value.
RenderAspectRatio({ RenderAspectRatio({
RenderBox child, RenderBox child,
double aspectRatio double aspectRatio
}) : _aspectRatio = aspectRatio, super(child) { }) : _aspectRatio = aspectRatio, super(child) {
assert(_aspectRatio > 0.0); assert(aspectRatio != null);
assert(_aspectRatio.isFinite); assert(aspectRatio > 0.0);
assert(_aspectRatio != null); assert(aspectRatio.isFinite);
} }
/// The aspect ratio to attempt to use. /// The aspect ratio to attempt to use.
...@@ -511,7 +526,7 @@ class RenderAspectRatio extends RenderProxyBox { ...@@ -511,7 +526,7 @@ class RenderAspectRatio extends RenderProxyBox {
/// ///
/// This class is relatively expensive. Avoid using it where possible. /// This class is relatively expensive. Avoid using it where possible.
class RenderIntrinsicWidth extends RenderProxyBox { class RenderIntrinsicWidth extends RenderProxyBox {
/// Creates a render object that sizes itself to its child's intrinsic width.
RenderIntrinsicWidth({ RenderIntrinsicWidth({
double stepWidth, double stepWidth,
double stepHeight, double stepHeight,
...@@ -618,7 +633,7 @@ class RenderIntrinsicWidth extends RenderProxyBox { ...@@ -618,7 +633,7 @@ class RenderIntrinsicWidth extends RenderProxyBox {
/// ///
/// This class is relatively expensive. Avoid using it where possible. /// This class is relatively expensive. Avoid using it where possible.
class RenderIntrinsicHeight extends RenderProxyBox { class RenderIntrinsicHeight extends RenderProxyBox {
/// Creates a render object that sizes itself to its child's intrinsic height.
RenderIntrinsicHeight({ RenderIntrinsicHeight({
RenderBox child RenderBox child
}) : super(child); }) : super(child);
...@@ -686,7 +701,10 @@ int _getAlphaFromOpacity(double opacity) => (opacity * 255).round(); ...@@ -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 /// 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. /// value 1.0, the child is painted immediately without an intermediate buffer.
class RenderOpacity extends RenderProxyBox { 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) { : _opacity = opacity, _alpha = _getAlphaFromOpacity(opacity), super(child) {
assert(opacity != null); assert(opacity != null);
assert(opacity >= 0.0 && opacity <= 1.0); assert(opacity >= 0.0 && opacity <= 1.0);
...@@ -748,12 +766,34 @@ class RenderOpacity extends RenderProxyBox { ...@@ -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); 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 { class RenderShaderMask extends RenderProxyBox {
RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, TransferMode transferMode }) /// Creates a render object that applies a mask generated by a [Shader] to its child.
: _shaderCallback = shaderCallback, _transferMode = transferMode, super(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 get shaderCallback => _shaderCallback;
ShaderCallback _shaderCallback; ShaderCallback _shaderCallback;
set shaderCallback (ShaderCallback newShaderCallback) { set shaderCallback (ShaderCallback newShaderCallback) {
...@@ -764,6 +804,10 @@ class RenderShaderMask extends RenderProxyBox { ...@@ -764,6 +804,10 @@ class RenderShaderMask extends RenderProxyBox {
markNeedsPaint(); 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 get transferMode => _transferMode;
TransferMode _transferMode; TransferMode _transferMode;
set transferMode (TransferMode newTransferMode) { set transferMode (TransferMode newTransferMode) {
...@@ -787,12 +831,20 @@ class RenderShaderMask extends RenderProxyBox { ...@@ -787,12 +831,20 @@ class RenderShaderMask extends RenderProxyBox {
} }
} }
/// Applies a filter to the existing painted content and then paints [child].
class RenderBackdropFilter extends RenderProxyBox { class RenderBackdropFilter extends RenderProxyBox {
/// Creates a backdrop filter.
///
/// The [filter] argument must not be null.
RenderBackdropFilter({ RenderBox child, ui.ImageFilter filter }) RenderBackdropFilter({ RenderBox child, ui.ImageFilter filter })
: _filter = filter, super(child) { : _filter = filter, super(child) {
assert(filter != null); 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 get filter => _filter;
ui.ImageFilter _filter; ui.ImageFilter _filter;
set filter (ui.ImageFilter newFilter) { set filter (ui.ImageFilter newFilter) {
...@@ -877,8 +929,14 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox { ...@@ -877,8 +929,14 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
/// Clips its child using a rectangle. /// 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> { 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({ RenderClipRect({
RenderBox child, RenderBox child,
CustomClipper<Rect> clipper CustomClipper<Rect> clipper
...@@ -910,6 +968,7 @@ class RenderClipRect extends _RenderCustomClip<Rect> { ...@@ -910,6 +968,7 @@ class RenderClipRect extends _RenderCustomClip<Rect> {
/// y radius values and prevents its child from painting outside that rounded /// y radius values and prevents its child from painting outside that rounded
/// rectangle. /// rectangle.
class RenderClipRRect extends RenderProxyBox { class RenderClipRRect extends RenderProxyBox {
/// Creates a rounded-rectangular clip.
RenderClipRRect({ RenderClipRRect({
RenderBox child, RenderBox child,
double xRadius, double xRadius,
...@@ -962,9 +1021,14 @@ class RenderClipRRect extends RenderProxyBox { ...@@ -962,9 +1021,14 @@ class RenderClipRRect extends RenderProxyBox {
/// Clips its child using an oval. /// Clips its child using an oval.
/// ///
/// Inscribes an oval into its layout dimensions and prevents its child from /// By default, inscribes an oval into its layout dimensions and prevents its
/// painting outside that oval. /// 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> { 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({ RenderClipOval({
RenderBox child, RenderBox child,
CustomClipper<Rect> clipper CustomClipper<Rect> clipper
...@@ -1018,6 +1082,12 @@ class RenderClipOval extends _RenderCustomClip<Rect> { ...@@ -1018,6 +1082,12 @@ class RenderClipOval extends _RenderCustomClip<Rect> {
/// * To clip to an oval or circle, consider [RenderClipOval]. /// * To clip to an oval or circle, consider [RenderClipOval].
/// * To clip to a rounded rectangle, consider [RenderClipRRect]. /// * To clip to a rounded rectangle, consider [RenderClipRRect].
class RenderClipPath extends _RenderCustomClip<Path> { 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({ RenderClipPath({
RenderBox child, RenderBox child,
CustomClipper<Path> clipper CustomClipper<Path> clipper
...@@ -1148,6 +1218,9 @@ class RenderDecoratedBox extends RenderProxyBox { ...@@ -1148,6 +1218,9 @@ class RenderDecoratedBox extends RenderProxyBox {
/// Applies a transformation before painting its child. /// Applies a transformation before painting its child.
class RenderTransform extends RenderProxyBox { class RenderTransform extends RenderProxyBox {
/// Creates a render object that transforms its child.
///
/// The [transform] argument must not be null.
RenderTransform({ RenderTransform({
Matrix4 transform, Matrix4 transform,
Offset origin, Offset origin,
...@@ -1312,12 +1385,16 @@ class RenderTransform extends RenderProxyBox { ...@@ -1312,12 +1385,16 @@ class RenderTransform extends RenderProxyBox {
} }
} }
/// Applies a translation transformation before painting its child. The /// Applies a translation transformation before painting its child.
/// translation is expressed as a [FractionalOffset] relative to the ///
/// The translation is expressed as a [FractionalOffset] relative to the
/// RenderFractionalTranslation box's size. Hit tests will only be detected /// RenderFractionalTranslation box's size. Hit tests will only be detected
/// inside the bounds of the RenderFractionalTranslation, even if the contents /// inside the bounds of the RenderFractionalTranslation, even if the contents
/// are offset such that they overflow. /// are offset such that they overflow.
class RenderFractionalTranslation extends RenderProxyBox { class RenderFractionalTranslation extends RenderProxyBox {
/// Creates a render object that translates its child's painting.
///
/// The [translation] argument must not be null.
RenderFractionalTranslation({ RenderFractionalTranslation({
FractionalOffset translation, FractionalOffset translation,
this.transformHitTests: true, this.transformHitTests: true,
...@@ -1472,20 +1549,29 @@ abstract class CustomPainter { ...@@ -1472,20 +1549,29 @@ abstract class CustomPainter {
bool hitTest(Point position) => null; 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 /// When asked to paint, [CustomPaint] first ask its [painter] to paint on the
/// current canvas and then paints its children. After painting its children, /// current canvas, then it paints its child, and then, after painting its
/// custom paint asks foregroundPainter to paint. The coodinate system of the /// child, it ask its [foregroundPainter] to paint. The coodinate system of the
/// canvas matches the coordinate system of the custom paint object. The /// canvas matches the coordinate system of the [CustomPaint] object. The
/// painters are expected to paint within a rectangle starting at the origin /// painters are expected to paint within a rectangle starting at the origin and
/// and encompassing a region of the given size. If the painters paints outside /// encompassing a region of the given size. (If the painters paints outside
/// those bounds, there might be insufficient memory allocated to rasterize the /// 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 /// See also:
/// layout or paint information during the callback. ///
/// * [CustomPainter],
/// * [Canvas]
class RenderCustomPaint extends RenderProxyBox { class RenderCustomPaint extends RenderProxyBox {
/// Creates a render object that delgates its painting.
RenderCustomPaint({ RenderCustomPaint({
CustomPainter painter, CustomPainter painter,
CustomPainter foregroundPainter, CustomPainter foregroundPainter,
...@@ -1633,13 +1719,31 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -1633,13 +1719,31 @@ class RenderCustomPaint extends RenderProxyBox {
} }
} }
/// Signature for listening to [PointerDownEvent] events.
///
/// Used by [Listener] and [RenderPointerListener].
typedef void PointerDownEventListener(PointerDownEvent event); typedef void PointerDownEventListener(PointerDownEvent event);
/// Signature for listening to [PointerMoveEvent] events.
///
/// Used by [Listener] and [RenderPointerListener].
typedef void PointerMoveEventListener(PointerMoveEvent event); typedef void PointerMoveEventListener(PointerMoveEvent event);
/// Signature for listening to [PointerUpEvent] events.
///
/// Used by [Listener] and [RenderPointerListener].
typedef void PointerUpEventListener(PointerUpEvent event); typedef void PointerUpEventListener(PointerUpEvent event);
/// Signature for listening to [PointerCancelEvent] events.
///
/// Used by [Listener] and [RenderPointerListener].
typedef void PointerCancelEventListener(PointerCancelEvent event); typedef void PointerCancelEventListener(PointerCancelEvent event);
/// Calls the callbacks in response to pointer events. /// Calls callbacks in response to pointer events.
class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
/// Creates a render object that forwards point events to callbacks.
///
/// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
RenderPointerListener({ RenderPointerListener({
this.onPointerDown, this.onPointerDown,
this.onPointerMove, this.onPointerMove,
...@@ -1649,9 +1753,16 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { ...@@ -1649,9 +1753,16 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
RenderBox child RenderBox child
}) : super(behavior: behavior, child: child); }) : super(behavior: behavior, child: child);
/// Called when a pointer comes into contact with the screen at this object.
PointerDownEventListener onPointerDown; PointerDownEventListener onPointerDown;
/// Called when a pointer that triggered an [onPointerDown] changes position.
PointerMoveEventListener onPointerMove; PointerMoveEventListener onPointerMove;
/// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen.
PointerUpEventListener onPointerUp; PointerUpEventListener onPointerUp;
/// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver.
PointerCancelEventListener onPointerCancel; PointerCancelEventListener onPointerCancel;
@override @override
...@@ -1710,6 +1821,7 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior { ...@@ -1710,6 +1821,7 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
/// was not. These counts can also be inspected programmatically using /// was not. These counts can also be inspected programmatically using
/// [debugAsymmetricPaintCount] and [debugSymmetricPaintCount] respectively. /// [debugAsymmetricPaintCount] and [debugSymmetricPaintCount] respectively.
class RenderRepaintBoundary extends RenderProxyBox { class RenderRepaintBoundary extends RenderProxyBox {
/// Creates a repaint boundary around [child].
RenderRepaintBoundary({ RenderBox child }) : super(child); RenderRepaintBoundary({ RenderBox child }) : super(child);
@override @override
...@@ -1720,7 +1832,8 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -1720,7 +1832,8 @@ class RenderRepaintBoundary extends RenderProxyBox {
/// paint at different times. When both paint at the same time, the repaint /// paint at different times. When both paint at the same time, the repaint
/// boundary is redundant, and may be actually making performance worse. /// 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] /// Can be reset using [debugResetMetrics]. See [debugAsymmetricPaintCount]
/// for the corresponding count of times where only the parent or only the /// for the corresponding count of times where only the parent or only the
...@@ -1735,7 +1848,8 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -1735,7 +1848,8 @@ class RenderRepaintBoundary extends RenderProxyBox {
/// child, it can improve performance by reducing the number of paint /// child, it can improve performance by reducing the number of paint
/// operations that have to be recorded each frame. /// 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 /// Can be reset using [debugResetMetrics]. See [debugSymmetricPaintCount] for
/// the corresponding count of times where both the parent and the child /// the corresponding count of times where both the parent and the child
...@@ -1746,7 +1860,7 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -1746,7 +1860,7 @@ class RenderRepaintBoundary extends RenderProxyBox {
/// Resets the [debugSymmetricPaintCount] and [debugAsymmetricPaintCount] /// Resets the [debugSymmetricPaintCount] and [debugAsymmetricPaintCount]
/// counts to zero. /// 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() { void debugResetMetrics() {
assert(() { assert(() {
_debugSymmetricPaintCount = 0; _debugSymmetricPaintCount = 0;
...@@ -1813,6 +1927,10 @@ class RenderRepaintBoundary extends RenderProxyBox { ...@@ -1813,6 +1927,10 @@ class RenderRepaintBoundary extends RenderProxyBox {
/// the semantics layer (and thus e.g. accessibility tools). If /// the semantics layer (and thus e.g. accessibility tools). If
/// [ignoringSemantics] is null, it uses the value of [ignoring]. /// [ignoringSemantics] is null, it uses the value of [ignoring].
class RenderIgnorePointer extends RenderProxyBox { 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({ RenderIgnorePointer({
RenderBox child, RenderBox child,
bool ignoring: true, bool ignoring: true,
...@@ -1821,6 +1939,10 @@ class RenderIgnorePointer extends RenderProxyBox { ...@@ -1821,6 +1939,10 @@ class RenderIgnorePointer extends RenderProxyBox {
assert(_ignoring != null); 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 get ignoring => _ignoring;
bool _ignoring; bool _ignoring;
set ignoring(bool value) { set ignoring(bool value) {
...@@ -1832,6 +1954,11 @@ class RenderIgnorePointer extends RenderProxyBox { ...@@ -1832,6 +1954,11 @@ class RenderIgnorePointer extends RenderProxyBox {
markNeedsSemanticsUpdate(); 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 get ignoringSemantics => _ignoringSemantics;
bool _ignoringSemantics; bool _ignoringSemantics;
set ignoringSemantics(bool value) { set ignoringSemantics(bool value) {
...@@ -1869,6 +1996,9 @@ class RenderIgnorePointer extends RenderProxyBox { ...@@ -1869,6 +1996,9 @@ class RenderIgnorePointer extends RenderProxyBox {
/// Holds opaque meta data in the render tree. /// Holds opaque meta data in the render tree.
class RenderMetaData extends RenderProxyBoxWithHitTestBehavior { class RenderMetaData extends RenderProxyBoxWithHitTestBehavior {
/// Creates a render object that hold opaque metadata.
///
/// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
RenderMetaData({ RenderMetaData({
this.metaData, this.metaData,
HitTestBehavior behavior: HitTestBehavior.deferToChild, HitTestBehavior behavior: HitTestBehavior.deferToChild,
......
...@@ -91,6 +91,9 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi ...@@ -91,6 +91,9 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi
/// size. Padding then sizes itself to its child's size, inflated by the /// size. Padding then sizes itself to its child's size, inflated by the
/// padding, effectively creating empty space around the child. /// padding, effectively creating empty space around the child.
class RenderPadding extends RenderShiftedBox { 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({ RenderPadding({
EdgeInsets padding, EdgeInsets padding,
RenderBox child RenderBox child
...@@ -219,12 +222,16 @@ class RenderPadding extends RenderShiftedBox { ...@@ -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 { abstract class RenderAligningShiftedBox extends RenderShiftedBox {
/// Initializes member variables for subclasses.
///
/// The [alignment] argument must not be null.
RenderAligningShiftedBox({ RenderAligningShiftedBox({
RenderBox child, FractionalOffset alignment: FractionalOffset.center,
FractionalOffset alignment: FractionalOffset.center RenderBox child
}) : _alignment = alignment, }) : _alignment = alignment, super(child) {
super(child) {
assert(alignment != null && alignment.dx != null && alignment.dy != null); assert(alignment != null && alignment.dx != null && alignment.dy != null);
} }
...@@ -274,7 +281,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox { ...@@ -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 /// 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, /// tight constraint that is bigger than the child's natural size,
...@@ -285,6 +292,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox { ...@@ -285,6 +292,7 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
/// dimensions. Using widthFactor and heightFactor you can force this latter /// dimensions. Using widthFactor and heightFactor you can force this latter
/// behavior in all cases. /// behavior in all cases.
class RenderPositionedBox extends RenderAligningShiftedBox { class RenderPositionedBox extends RenderAligningShiftedBox {
/// Creates a render object that positions its child.
RenderPositionedBox({ RenderPositionedBox({
RenderBox child, RenderBox child,
double widthFactor, double widthFactor,
...@@ -427,6 +435,7 @@ class RenderPositionedBox extends RenderAligningShiftedBox { ...@@ -427,6 +435,7 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
/// child inside a larger parent, use [RenderPositionedBox] and /// child inside a larger parent, use [RenderPositionedBox] and
/// [RenderConstrainedBox] rather than RenderOverflowBox. /// [RenderConstrainedBox] rather than RenderOverflowBox.
class RenderConstrainedOverflowBox extends RenderAligningShiftedBox { class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
/// Creates a render object that lets its child overflow itself.
RenderConstrainedOverflowBox({ RenderConstrainedOverflowBox({
RenderBox child, RenderBox child,
double minWidth, double minWidth,
...@@ -543,9 +552,12 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox { ...@@ -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. /// through to its child, which will probably overflow.
class RenderSizedOverflowBox extends RenderAligningShiftedBox { 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({ RenderSizedOverflowBox({
RenderBox child, RenderBox child,
Size requestedSize, Size requestedSize,
...@@ -617,6 +629,10 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox { ...@@ -617,6 +629,10 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
/// ///
/// It then tries to size itself to the size of its child. /// It then tries to size itself to the size of its child.
class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox { 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({ RenderFractionallySizedOverflowBox({
RenderBox child, RenderBox child,
double widthFactor, double widthFactor,
...@@ -755,6 +771,9 @@ class SingleChildLayoutDelegate { ...@@ -755,6 +771,9 @@ class SingleChildLayoutDelegate {
/// of the parent, but the size of the parent cannot depend on the size of the /// of the parent, but the size of the parent cannot depend on the size of the
/// child. /// child.
class RenderCustomSingleChildLayoutBox extends RenderShiftedBox { class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
/// Creates a render box that defers its layout to a delgate.
///
/// The [delegate] argument must not be null.
RenderCustomSingleChildLayoutBox({ RenderCustomSingleChildLayoutBox({
RenderBox child, RenderBox child,
SingleChildLayoutDelegate delegate SingleChildLayoutDelegate delegate
......
...@@ -48,6 +48,9 @@ class ViewConfiguration { ...@@ -48,6 +48,9 @@ class ViewConfiguration {
/// bootstrapping the rendering pipeline. The view has a unique child /// bootstrapping the rendering pipeline. The view has a unique child
/// [RenderBox], which is required to fill the entire output surface. /// [RenderBox], which is required to fill the entire output surface.
class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> { class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
/// Creates the root of the render tree.
///
/// Typically created by the binding (e.g., [RendererBinding]).
RenderView({ RenderView({
RenderBox child, RenderBox child,
this.timeForRotation: const Duration(microseconds: 83333), this.timeForRotation: const Duration(microseconds: 83333),
...@@ -115,6 +118,13 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> ...@@ -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() 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 }) { bool hitTest(HitTestResult result, { Point position }) {
if (child != null) if (child != null)
child.hitTest(result, position: position); child.hitTest(result, position: position);
......
...@@ -95,7 +95,14 @@ class Opacity extends SingleChildRenderObjectWidget { ...@@ -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 { 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({ ShaderMask({
Key key, Key key,
this.shaderCallback, this.shaderCallback,
...@@ -106,7 +113,16 @@ class ShaderMask extends SingleChildRenderObjectWidget { ...@@ -106,7 +113,16 @@ class ShaderMask extends SingleChildRenderObjectWidget {
assert(transferMode != 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.
final ShaderCallback shaderCallback; 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; final TransferMode transferMode;
@override @override
...@@ -125,7 +141,11 @@ class ShaderMask extends SingleChildRenderObjectWidget { ...@@ -125,7 +141,11 @@ class ShaderMask extends SingleChildRenderObjectWidget {
} }
} }
/// Applies a filter to the existing painted content and then paints [child].
class BackdropFilter extends SingleChildRenderObjectWidget { class BackdropFilter extends SingleChildRenderObjectWidget {
/// Creates a backdrop filter.
///
/// The [filter] argument must not be null.
BackdropFilter({ BackdropFilter({
Key key, Key key,
this.filter, this.filter,
...@@ -134,6 +154,10 @@ class BackdropFilter extends SingleChildRenderObjectWidget { ...@@ -134,6 +154,10 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
assert(filter != null); 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; final ui.ImageFilter filter;
@override @override
...@@ -183,15 +207,14 @@ class DecoratedBox extends SingleChildRenderObjectWidget { ...@@ -183,15 +207,14 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// Provides a canvas on which to draw during the paint phase. /// Provides a canvas on which to draw during the paint phase.
/// ///
/// When asked to paint, [CustomPaint] objects first ask their [painter] to /// When asked to paint, [CustomPaint] first ask its [painter] to paint on the
/// paint on the current canvas, then they paint their children, and then, after /// current canvas, then it paints its child, and then, after painting its
/// painting their children, ask their [foregroundPainter] to paint. The /// child, it ask its [foregroundPainter] to paint. The coodinate system of the
/// coodinate system of the canvas matches the coordinate system of the /// canvas matches the coordinate system of the [CustomPaint] object. The
/// [CustomPaint] object. The painters are expected to paint within a rectangle /// painters are expected to paint within a rectangle starting at the origin and
/// starting at the origin and encompassing a region of the given size. (If the /// encompassing a region of the given size. (If the painters paints outside
/// painters paints outside those bounds, there might be insufficient memory /// those bounds, there might be insufficient memory allocated to rasterize the
/// allocated to rasterize the painting commands and the resulting behavior is /// painting commands and the resulting behavior is undefined.)
/// undefined.)
/// ///
/// Painters are implemented by subclassing [CustomPainter]. /// Painters are implemented by subclassing [CustomPainter].
/// ///
...@@ -199,8 +222,12 @@ class DecoratedBox extends SingleChildRenderObjectWidget { ...@@ -199,8 +222,12 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// tree as needing a new layout during the callback (the layout for this frame /// tree as needing a new layout during the callback (the layout for this frame
/// has already happened). /// has already happened).
/// ///
/// See: [CustomPainter], [Canvas]. /// See also:
///
/// * [CustomPainter],
/// * [Canvas]
class CustomPaint extends SingleChildRenderObjectWidget { class CustomPaint extends SingleChildRenderObjectWidget {
/// Creates a widget that delgates its painting.
CustomPaint({ Key key, this.painter, this.foregroundPainter, Widget child }) CustomPaint({ Key key, this.painter, this.foregroundPainter, Widget child })
: super(key: key, child: child); : super(key: key, child: child);
...@@ -233,8 +260,14 @@ class CustomPaint extends SingleChildRenderObjectWidget { ...@@ -233,8 +260,14 @@ class CustomPaint extends SingleChildRenderObjectWidget {
/// Clips its child using a rectangle. /// 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 { 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); ClipRect({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
...@@ -260,6 +293,7 @@ class ClipRect extends SingleChildRenderObjectWidget { ...@@ -260,6 +293,7 @@ class ClipRect extends SingleChildRenderObjectWidget {
/// y radius values and prevents its child from painting outside that rounded /// y radius values and prevents its child from painting outside that rounded
/// rectangle. /// rectangle.
class ClipRRect extends SingleChildRenderObjectWidget { class ClipRRect extends SingleChildRenderObjectWidget {
/// Creates a rounded-rectangular clip.
ClipRRect({ Key key, this.xRadius, this.yRadius, Widget child }) ClipRRect({ Key key, this.xRadius, this.yRadius, Widget child })
: super(key: key, child: child); : super(key: key, child: child);
...@@ -288,9 +322,14 @@ class ClipRRect extends SingleChildRenderObjectWidget { ...@@ -288,9 +322,14 @@ class ClipRRect extends SingleChildRenderObjectWidget {
/// Clips its child using an oval. /// Clips its child using an oval.
/// ///
/// Inscribes an oval into its layout dimensions and prevents its child from /// By default, inscribes an oval into its layout dimensions and prevents its
/// painting outside that oval. /// 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 { 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); ClipOval({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
...@@ -331,6 +370,12 @@ class ClipOval extends SingleChildRenderObjectWidget { ...@@ -331,6 +370,12 @@ class ClipOval extends SingleChildRenderObjectWidget {
/// * To clip to an oval or circle, consider [ClipOval]. /// * To clip to an oval or circle, consider [ClipOval].
/// * To clip to a rounded rectangle, consider [ClipRRect]. /// * To clip to a rounded rectangle, consider [ClipRRect].
class ClipPath extends SingleChildRenderObjectWidget { 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); ClipPath({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
...@@ -359,8 +404,17 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -359,8 +404,17 @@ class ClipPath extends SingleChildRenderObjectWidget {
/// Applies a transformation before painting its child. /// Applies a transformation before painting its child.
class Transform extends SingleChildRenderObjectWidget { class Transform extends SingleChildRenderObjectWidget {
Transform({ Key key, this.transform, this.origin, this.alignment, this.transformHitTests: true, Widget child }) /// Creates a widget that transforms its child.
: super(key: key, child: 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); assert(transform != null);
} }
...@@ -404,8 +458,15 @@ class Transform extends SingleChildRenderObjectWidget { ...@@ -404,8 +458,15 @@ class Transform extends SingleChildRenderObjectWidget {
/// Applies a translation expressed as a fraction of the box's size before /// Applies a translation expressed as a fraction of the box's size before
/// painting its child. /// painting its child.
class FractionalTranslation extends SingleChildRenderObjectWidget { class FractionalTranslation extends SingleChildRenderObjectWidget {
FractionalTranslation({ Key key, this.translation, this.transformHitTests: true, Widget child }) /// Creates a widget that translates its child's painting.
: super(key: key, child: child) { ///
/// 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); assert(translation != null);
} }
...@@ -763,6 +824,10 @@ class ConstrainedBox extends SingleChildRenderObjectWidget { ...@@ -763,6 +824,10 @@ class ConstrainedBox extends SingleChildRenderObjectWidget {
/// the child according to a [FractionalOffset] value) /// the child according to a [FractionalOffset] value)
/// * [OverflowBox] /// * [OverflowBox]
class FractionallySizedBox extends SingleChildRenderObjectWidget { 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({ FractionallySizedBox({
Key key, Key key,
this.alignment: FractionalOffset.center, this.alignment: FractionalOffset.center,
...@@ -771,6 +836,8 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget { ...@@ -771,6 +836,8 @@ class FractionallySizedBox extends SingleChildRenderObjectWidget {
Widget child Widget child
}) : super(key: key, child: child) { }) : super(key: key, child: child) {
assert(alignment != null && alignment.dx != null && alignment.dy != null); 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. /// If non-null, the fraction of the incoming width given to the child.
...@@ -863,11 +930,12 @@ class LimitedBox extends SingleChildRenderObjectWidget { ...@@ -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. /// from its parent, possibly allowing the child to overflow the parent.
/// ///
/// See [RenderOverflowBox] for details. /// See [RenderOverflowBox] for details.
class OverflowBox extends SingleChildRenderObjectWidget { class OverflowBox extends SingleChildRenderObjectWidget {
/// Creates a widget that lets its child overflow itself.
OverflowBox({ OverflowBox({
Key key, Key key,
this.alignment: FractionalOffset.center, this.alignment: FractionalOffset.center,
...@@ -939,7 +1007,12 @@ class OverflowBox extends SingleChildRenderObjectWidget { ...@@ -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 { class SizedOverflowBox extends SingleChildRenderObjectWidget {
/// Creates a widget of a given size that lets its child overflow.
///
/// The [requestedSize] argument must not be null.
SizedOverflowBox({ SizedOverflowBox({
Key key, Key key,
this.alignment: FractionalOffset.center, this.alignment: FractionalOffset.center,
...@@ -960,6 +1033,7 @@ class SizedOverflowBox extends SingleChildRenderObjectWidget { ...@@ -960,6 +1033,7 @@ class SizedOverflowBox extends SingleChildRenderObjectWidget {
/// with the center of the parent. /// with the center of the parent.
final FractionalOffset alignment; final FractionalOffset alignment;
/// The size this render box should attempt to be.
final Size size; final Size size;
@override @override
...@@ -2762,7 +2836,14 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { ...@@ -2762,7 +2836,14 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
// EVENT HANDLING // 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 { class Listener extends SingleChildRenderObjectWidget {
/// Creates a widget that forwards point events to callbacks.
///
/// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
Listener({ Listener({
Key key, Key key,
Widget child, Widget child,
...@@ -2775,10 +2856,19 @@ class Listener extends SingleChildRenderObjectWidget { ...@@ -2775,10 +2856,19 @@ class Listener extends SingleChildRenderObjectWidget {
assert(behavior != null); assert(behavior != null);
} }
/// Called when a pointer comes into contact with the screen at this object.
final PointerDownEventListener onPointerDown; final PointerDownEventListener onPointerDown;
/// Called when a pointer that triggered an [onPointerDown] changes position.
final PointerMoveEventListener onPointerMove; final PointerMoveEventListener onPointerMove;
/// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen.
final PointerUpEventListener onPointerUp; final PointerUpEventListener onPointerUp;
/// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver.
final PointerCancelEventListener onPointerCancel; final PointerCancelEventListener onPointerCancel;
/// How to behave during hit testing.
final HitTestBehavior behavior; final HitTestBehavior behavior;
@override @override
...@@ -2857,12 +2947,42 @@ class RepaintBoundary extends SingleChildRenderObjectWidget { ...@@ -2857,12 +2947,42 @@ class RepaintBoundary extends SingleChildRenderObjectWidget {
RenderRepaintBoundary createRenderObject(BuildContext context) => new RenderRepaintBoundary(); 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 { class IgnorePointer extends SingleChildRenderObjectWidget {
IgnorePointer({ Key key, Widget child, this.ignoring: true, this.ignoringSemantics }) /// Creates a widget that is invisivle to hit testing.
: super(key: key, child: child); ///
/// 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 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 @override
RenderIgnorePointer createRenderObject(BuildContext context) => new RenderIgnorePointer( RenderIgnorePointer createRenderObject(BuildContext context) => new RenderIgnorePointer(
...@@ -2878,6 +2998,45 @@ class IgnorePointer extends SingleChildRenderObjectWidget { ...@@ -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 // UTILITY NODES
...@@ -2979,38 +3138,6 @@ class ExcludeSemantics extends SingleChildRenderObjectWidget { ...@@ -2979,38 +3138,6 @@ class ExcludeSemantics extends SingleChildRenderObjectWidget {
RenderExcludeSemantics createRenderObject(BuildContext context) => new RenderExcludeSemantics(); 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. /// Always builds the given child.
/// ///
/// Useful for attaching a key to an existing widget. /// Useful for attaching a key to an existing widget.
......
...@@ -13,8 +13,9 @@ import 'framework.dart'; ...@@ -13,8 +13,9 @@ import 'framework.dart';
/// required on the GPU thread to produce each frame. Ideally, both these values /// 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 /// 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, /// 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. /// 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 /// The simplest way to show the performance overlay is to set
/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] /// [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