Add more dartdoc to rendering.dart (#4232)
There are still many more left before rendering.dart is complete.
This commit is contained in:
parent
89678bb7cb
commit
6f3382aa57
@ -11,29 +11,38 @@ import 'object.dart';
|
||||
/// for constraints. Also sets up and manages implicit constraints and edit
|
||||
/// variables.
|
||||
class AutoLayoutRect {
|
||||
AutoLayoutRect() {
|
||||
_left = new al.Param();
|
||||
_right = new al.Param();
|
||||
_top = new al.Param();
|
||||
_bottom = new al.Param();
|
||||
}
|
||||
/// Creates parameters for a rectangle for use with auto layout.
|
||||
AutoLayoutRect()
|
||||
: left = new al.Param(),
|
||||
right = new al.Param(),
|
||||
top = new al.Param(),
|
||||
bottom = new al.Param();
|
||||
|
||||
al.Param _left;
|
||||
al.Param _right;
|
||||
al.Param _top;
|
||||
al.Param _bottom;
|
||||
/// A parameter that represents the left edge of the rectangle.
|
||||
final al.Param left;
|
||||
|
||||
al.Param get left => _left;
|
||||
al.Param get right => _right;
|
||||
al.Param get top => _top;
|
||||
al.Param get bottom => _bottom;
|
||||
/// A parameter that represents the right edge of the rectangle.
|
||||
final al.Param right;
|
||||
|
||||
al.Expression get width => _right - _left;
|
||||
al.Expression get height => _bottom - _top;
|
||||
/// A parameter that represents the top edge of the rectangle.
|
||||
final al.Param top;
|
||||
|
||||
al.Expression get horizontalCenter => (_left + _right) / al.cm(2.0);
|
||||
al.Expression get verticalCenter => (_top + _bottom) / al.cm(2.0);
|
||||
/// A parameter that represents the bottom edge of the rectangle.
|
||||
final al.Param bottom;
|
||||
|
||||
/// An expression that represents the horizontal extent of the rectangle.
|
||||
al.Expression get width => right - left;
|
||||
|
||||
/// An expression that represents the vertical extent of the rectangle.
|
||||
al.Expression get height => bottom - top;
|
||||
|
||||
/// An expression that represents halfway between the left and right edges of the rectangle.
|
||||
al.Expression get horizontalCenter => (left + right) / al.cm(2.0);
|
||||
|
||||
/// An expression that represents halfway between the top and bottom edges of the rectangle.
|
||||
al.Expression get verticalCenter => (top + bottom) / al.cm(2.0);
|
||||
|
||||
/// Constraints that require that this rect contains the given rect.
|
||||
List<al.Constraint> contains(AutoLayoutRect other) {
|
||||
return <al.Constraint>[
|
||||
other.left >= left,
|
||||
@ -44,11 +53,14 @@ class AutoLayoutRect {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parent data for use with [RenderAutoLayout].
|
||||
class AutoLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
||||
/// Creates parent data associated with the given render box.
|
||||
AutoLayoutParentData(this._renderBox);
|
||||
|
||||
final RenderBox _renderBox;
|
||||
|
||||
/// Parameters that represent the size and position of the render box.
|
||||
AutoLayoutRect get rect => _rect;
|
||||
AutoLayoutRect _rect;
|
||||
set rect(AutoLayoutRect value) {
|
||||
@ -63,13 +75,13 @@ class AutoLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
||||
|
||||
BoxConstraints get _constraintsFromSolver {
|
||||
return new BoxConstraints.tightFor(
|
||||
width: _rect._right.value - _rect._left.value,
|
||||
height: _rect._bottom.value - _rect._top.value
|
||||
width: _rect.right.value - _rect.left.value,
|
||||
height: _rect.bottom.value - _rect.top.value
|
||||
);
|
||||
}
|
||||
|
||||
Offset get _offsetFromSolver {
|
||||
return new Offset(_rect._left.value, _rect._top.value);
|
||||
return new Offset(_rect.left.value, _rect.top.value);
|
||||
}
|
||||
|
||||
List<al.Constraint> _implicitConstraints;
|
||||
@ -106,40 +118,66 @@ class AutoLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
||||
/// may return null.
|
||||
List<al.Constraint> _constructImplicitConstraints() {
|
||||
return <al.Constraint>[
|
||||
_rect._left >= al.cm(0.0), // The left edge must be positive.
|
||||
_rect._right >= _rect._left, // Width must be positive.
|
||||
// Why don't we need something similar for the top and the bottom?
|
||||
_rect.left >= al.cm(0.0), // The left edge must be positive.
|
||||
_rect.right >= _rect.left, // Width must be positive.
|
||||
// TODO(chinmay): Check whether we need something similar for the top and
|
||||
// bottom.
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/// Subclass to control the layout of a [RenderAutoLayout].
|
||||
abstract class AutoLayoutDelegate {
|
||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const AutoLayoutDelegate();
|
||||
|
||||
/// Returns the constraints to use when computing layout.
|
||||
///
|
||||
/// The `parent` argument contains the parameters for the parent's position
|
||||
/// and size. Typical implementations will return constraints that determine
|
||||
/// the size and position of each child.
|
||||
///
|
||||
/// The delegate interface does not provide a mechanism for obtaining the
|
||||
/// parameters for children. Subclasses are expected to obtain those
|
||||
/// parameters through some other mechanism.
|
||||
List<al.Constraint> getConstraints(AutoLayoutRect parent);
|
||||
|
||||
/// Override this method to return true when new constraints need to be generated.
|
||||
bool shouldUpdateConstraints(AutoLayoutDelegate oldDelegate);
|
||||
}
|
||||
|
||||
/// Uses the cassowary constraint solver to automatically size and position children.
|
||||
class RenderAutoLayout extends RenderBox
|
||||
with ContainerRenderObjectMixin<RenderBox, AutoLayoutParentData>,
|
||||
RenderBoxContainerDefaultsMixin<RenderBox, AutoLayoutParentData> {
|
||||
|
||||
/// Creates a render box that automatically sizes and positions its children.
|
||||
RenderAutoLayout({
|
||||
AutoLayoutDelegate delegate,
|
||||
List<RenderBox> children
|
||||
}) : _delegate = delegate, _needToUpdateConstraints = (delegate != null) {
|
||||
_solver.addEditVariables(<al.Variable>[
|
||||
_rect._left.variable,
|
||||
_rect._right.variable,
|
||||
_rect._top.variable,
|
||||
_rect._bottom.variable
|
||||
_rect.left.variable,
|
||||
_rect.right.variable,
|
||||
_rect.top.variable,
|
||||
_rect.bottom.variable
|
||||
], al.Priority.required - 1);
|
||||
|
||||
addAll(children);
|
||||
}
|
||||
|
||||
/// The delegate that generates constraints for the layout.
|
||||
///
|
||||
/// If the new delegate is the same as the previous one, this does nothing.
|
||||
///
|
||||
/// If the new delegate is the same class as the previous one, then the new
|
||||
/// delegate has its [AutoLayoutDelegate.shouldUpdateConstraints] called; if
|
||||
/// the result is `true`, then the delegate will be called.
|
||||
///
|
||||
/// If the new delegate is a different class than the previous one, then the
|
||||
/// delegate will be called.
|
||||
///
|
||||
/// If the delgate is null, the layout is unconstrained.
|
||||
AutoLayoutDelegate get delegate => _delegate;
|
||||
AutoLayoutDelegate _delegate;
|
||||
set delegate(AutoLayoutDelegate newDelegate) {
|
||||
@ -228,10 +266,10 @@ class RenderAutoLayout extends RenderBox
|
||||
|
||||
if (size != _previousSize) {
|
||||
_solver
|
||||
..suggestValueForVariable(_rect._left.variable, 0.0)
|
||||
..suggestValueForVariable(_rect._top.variable, 0.0)
|
||||
..suggestValueForVariable(_rect._bottom.variable, size.height)
|
||||
..suggestValueForVariable(_rect._right.variable, size.width);
|
||||
..suggestValueForVariable(_rect.left.variable, 0.0)
|
||||
..suggestValueForVariable(_rect.top.variable, 0.0)
|
||||
..suggestValueForVariable(_rect.bottom.variable, size.height)
|
||||
..suggestValueForVariable(_rect.right.variable, size.width);
|
||||
_previousSize = size;
|
||||
needToFlushUpdates = true;
|
||||
}
|
||||
|
@ -209,6 +209,10 @@ void debugDumpSemanticsTree() {
|
||||
///
|
||||
/// See also [BindingBase].
|
||||
class RenderingFlutterBinding extends BindingBase with SchedulerBinding, GestureBinding, ServicesBinding, RendererBinding {
|
||||
/// Creates a binding for the rendering layer.
|
||||
///
|
||||
/// The `root` render box is attached directly to the [renderView] and is
|
||||
/// given constraints that require it to fill the window.
|
||||
RenderingFlutterBinding({ RenderBox root }) {
|
||||
assert(renderView != null);
|
||||
renderView.child = root;
|
||||
|
@ -25,7 +25,9 @@ typedef double _Constrainer(double value);
|
||||
class RenderBlock extends RenderBox
|
||||
with ContainerRenderObjectMixin<RenderBox, BlockParentData>,
|
||||
RenderBoxContainerDefaultsMixin<RenderBox, BlockParentData> {
|
||||
|
||||
/// Creates a block render object.
|
||||
///
|
||||
/// By default, the block positions children along the vertical axis.
|
||||
RenderBlock({
|
||||
List<RenderBox> children,
|
||||
Axis mainAxis: Axis.vertical
|
||||
|
@ -238,39 +238,43 @@ class BoxConstraints extends Constraints {
|
||||
(minHeight <= size.height) && (size.height <= maxHeight);
|
||||
}
|
||||
|
||||
BoxConstraints operator*(double other) {
|
||||
/// Scales each constraint parameter by the given factor.
|
||||
BoxConstraints operator*(double factor) {
|
||||
return new BoxConstraints(
|
||||
minWidth: minWidth * other,
|
||||
maxWidth: maxWidth * other,
|
||||
minHeight: minHeight * other,
|
||||
maxHeight: maxHeight * other
|
||||
minWidth: minWidth * factor,
|
||||
maxWidth: maxWidth * factor,
|
||||
minHeight: minHeight * factor,
|
||||
maxHeight: maxHeight * factor
|
||||
);
|
||||
}
|
||||
|
||||
BoxConstraints operator/(double other) {
|
||||
/// Scales each constraint parameter by the inverse of the given factor.
|
||||
BoxConstraints operator/(double factor) {
|
||||
return new BoxConstraints(
|
||||
minWidth: minWidth / other,
|
||||
maxWidth: maxWidth / other,
|
||||
minHeight: minHeight / other,
|
||||
maxHeight: maxHeight / other
|
||||
minWidth: minWidth / factor,
|
||||
maxWidth: maxWidth / factor,
|
||||
minHeight: minHeight / factor,
|
||||
maxHeight: maxHeight / factor
|
||||
);
|
||||
}
|
||||
|
||||
BoxConstraints operator~/(double other) {
|
||||
/// Scales each constraint parameter by the inverse of the given factor, rounded to the nearest integer.
|
||||
BoxConstraints operator~/(double factor) {
|
||||
return new BoxConstraints(
|
||||
minWidth: (minWidth ~/ other).toDouble(),
|
||||
maxWidth: (maxWidth ~/ other).toDouble(),
|
||||
minHeight: (minHeight ~/ other).toDouble(),
|
||||
maxHeight: (maxHeight ~/ other).toDouble()
|
||||
minWidth: (minWidth ~/ factor).toDouble(),
|
||||
maxWidth: (maxWidth ~/ factor).toDouble(),
|
||||
minHeight: (minHeight ~/ factor).toDouble(),
|
||||
maxHeight: (maxHeight ~/ factor).toDouble()
|
||||
);
|
||||
}
|
||||
|
||||
BoxConstraints operator%(double other) {
|
||||
/// Computes the remainder of each constraint parameter by the given value.
|
||||
BoxConstraints operator%(double value) {
|
||||
return new BoxConstraints(
|
||||
minWidth: minWidth % other,
|
||||
maxWidth: maxWidth % other,
|
||||
minHeight: minHeight % other,
|
||||
maxHeight: maxHeight % other
|
||||
minWidth: minWidth % value,
|
||||
maxWidth: maxWidth % value,
|
||||
minHeight: minHeight % value,
|
||||
maxHeight: maxHeight % value
|
||||
);
|
||||
}
|
||||
|
||||
@ -374,6 +378,10 @@ class BoxConstraints extends Constraints {
|
||||
return isNormalized;
|
||||
}
|
||||
|
||||
/// Returns a box constraints that [isNormalized].
|
||||
///
|
||||
/// The returned [maxWidth] is at least as large as the [minWidth]. Similarly,
|
||||
/// the returned [maxHeight] is at least as large as the [minHeight].
|
||||
BoxConstraints normalize() {
|
||||
return new BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
@ -425,6 +433,9 @@ class BoxConstraints extends Constraints {
|
||||
|
||||
/// A hit test entry used by [RenderBox].
|
||||
class BoxHitTestEntry extends HitTestEntry {
|
||||
/// Creates a box hit test entry.
|
||||
///
|
||||
/// The [localPosition] argument must not be null.
|
||||
const BoxHitTestEntry(RenderBox target, this.localPosition) : super(target);
|
||||
|
||||
@override
|
||||
@ -515,6 +526,9 @@ abstract class RenderBox extends RenderObject {
|
||||
return constraints.constrainHeight(0.0);
|
||||
}
|
||||
|
||||
/// Whether this render object has undergone layout and has a [size].
|
||||
bool get hasSize => _size != null;
|
||||
|
||||
/// The size of this render box computed during layout.
|
||||
///
|
||||
/// This value is stale whenever this object is marked as needing layout.
|
||||
@ -546,7 +560,6 @@ abstract class RenderBox extends RenderObject {
|
||||
});
|
||||
return _size;
|
||||
}
|
||||
bool get hasSize => _size != null;
|
||||
Size _size;
|
||||
set size(Size value) {
|
||||
assert(!(debugDoingThisResize && debugDoingThisLayout));
|
||||
@ -996,6 +1009,10 @@ abstract class RenderBox extends RenderObject {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// In debug mode, paints a border around this render box.
|
||||
///
|
||||
/// Called for every [RenderBox] when [debugPaintSizeEnabled] is true.
|
||||
void debugPaintSize(PaintingContext context, Offset offset) {
|
||||
assert(() {
|
||||
Paint paint = new Paint()
|
||||
@ -1006,6 +1023,10 @@ abstract class RenderBox extends RenderObject {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// In debug mode, paints a line for each baseline.
|
||||
///
|
||||
/// Called for every [RenderBox] when [debugPaintBaselinesEnabled] is true.
|
||||
void debugPaintBaselines(PaintingContext context, Offset offset) {
|
||||
assert(() {
|
||||
Paint paint = new Paint()
|
||||
@ -1033,6 +1054,10 @@ abstract class RenderBox extends RenderObject {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// In debug mode, paints a rectangle if this render box has received more pointer downs than pointer up events.
|
||||
///
|
||||
/// Called for every [RenderBox] when [debugPaintPointersEnabled] is true.
|
||||
void debugPaintPointers(PaintingContext context, Offset offset) {
|
||||
assert(() {
|
||||
if (_debugActivePointers > 0) {
|
||||
@ -1127,8 +1152,13 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a list containing the children of this render object.
|
||||
///
|
||||
/// This function is useful when you need random-access to the children of
|
||||
/// this render object. If you're accessing the children in order, consider
|
||||
/// walking the child list directly.
|
||||
List<ChildType> getChildrenAsList() {
|
||||
List<ChildType> result = <ChildType>[];
|
||||
final List<ChildType> result = <ChildType>[];
|
||||
RenderBox child = firstChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData;
|
||||
@ -1139,7 +1169,14 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
|
||||
}
|
||||
}
|
||||
|
||||
/// An interpolation between two fractional offsets.
|
||||
///
|
||||
/// This class specializes the interpolation of Tween<FractionalOffset> to be
|
||||
/// appropriate for rectangles.
|
||||
class FractionalOffsetTween extends Tween<FractionalOffset> {
|
||||
/// Creates a fractional offset tween.
|
||||
///
|
||||
/// The [begin] and [end] arguments must not be null.
|
||||
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end }) : super(begin: begin, end: end);
|
||||
|
||||
@override
|
||||
|
@ -208,10 +208,14 @@ class ChildViewConnection {
|
||||
|
||||
/// (mojo-only) A view of a child application.
|
||||
class RenderChildView extends RenderBox {
|
||||
/// Creates a child view render object.
|
||||
///
|
||||
/// The [scale] argument must not be null.
|
||||
RenderChildView({
|
||||
ChildViewConnection child,
|
||||
double scale
|
||||
}) : _scale = scale {
|
||||
assert(scale != null);
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
@ -243,6 +247,7 @@ class RenderChildView extends RenderBox {
|
||||
double get scale => _scale;
|
||||
double _scale;
|
||||
set scale (double value) {
|
||||
assert(value != null);
|
||||
if (value == _scale)
|
||||
return;
|
||||
_scale = value;
|
||||
|
@ -205,6 +205,9 @@ abstract class MultiChildLayoutDelegate {
|
||||
class RenderCustomMultiChildLayoutBox extends RenderBox
|
||||
with ContainerRenderObjectMixin<RenderBox, MultiChildLayoutParentData>,
|
||||
RenderBoxContainerDefaultsMixin<RenderBox, MultiChildLayoutParentData> {
|
||||
/// Creates a render object that customizes the layout of multiple children.
|
||||
///
|
||||
/// The [delegate] argument must not be null.
|
||||
RenderCustomMultiChildLayoutBox({
|
||||
List<RenderBox> children,
|
||||
MultiChildLayoutDelegate delegate
|
||||
|
@ -66,6 +66,7 @@ bool debugPrintMarkNeedsLayoutStacks = false;
|
||||
/// Check the intrinsic sizes of each [RenderBox] during layout.
|
||||
bool debugCheckIntrinsicSizes = false;
|
||||
|
||||
/// Returns a list of strings representing the given transform in a format useful for [RenderObject.debugFillDescription].
|
||||
List<String> debugDescribeTransform(Matrix4 transform) {
|
||||
List<String> matrix = transform.toString().split('\n').map((String s) => ' $s').toList();
|
||||
matrix.removeLast();
|
||||
|
@ -22,7 +22,12 @@ typedef void SelectionChangedHandler(TextSelection selection, RenderEditableLine
|
||||
/// Represents a global screen coordinate of the point in a selection, and the
|
||||
/// text direction at that point.
|
||||
class TextSelectionPoint {
|
||||
TextSelectionPoint(this.point, this.direction);
|
||||
/// Creates a description of a point in a text selection.
|
||||
///
|
||||
/// The [point] argument must not be null.
|
||||
TextSelectionPoint(this.point, this.direction) {
|
||||
assert(point != null);
|
||||
}
|
||||
|
||||
/// Screen coordinates of the lower left or lower right corner of the selection.
|
||||
final Point point;
|
||||
@ -33,6 +38,7 @@ class TextSelectionPoint {
|
||||
|
||||
/// A single line of editable text.
|
||||
class RenderEditableLine extends RenderBox {
|
||||
/// Creates a render object for a single line of editable text.
|
||||
RenderEditableLine({
|
||||
TextSpan text,
|
||||
Color cursorColor,
|
||||
@ -56,7 +62,10 @@ class RenderEditableLine extends RenderBox {
|
||||
..onLongPress = _handleLongPress;
|
||||
}
|
||||
|
||||
/// Called when the selection changes.
|
||||
SelectionChangedHandler onSelectionChanged;
|
||||
|
||||
/// Called when the inner or outer dimensions of this render object change.
|
||||
ViewportDimensionsChangeCallback onPaintOffsetUpdateNeeded;
|
||||
|
||||
/// The text to display
|
||||
@ -72,6 +81,7 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
/// The color to use when painting the cursor.
|
||||
Color get cursorColor => _cursorColor;
|
||||
Color _cursorColor;
|
||||
set cursorColor(Color value) {
|
||||
@ -81,6 +91,7 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// Whether to paint the cursor.
|
||||
bool get showCursor => _showCursor;
|
||||
bool _showCursor;
|
||||
set showCursor(bool value) {
|
||||
@ -90,6 +101,7 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// The color to use when painting the selection.
|
||||
Color get selectionColor => _selectionColor;
|
||||
Color _selectionColor;
|
||||
set selectionColor(Color value) {
|
||||
@ -101,6 +113,7 @@ class RenderEditableLine extends RenderBox {
|
||||
|
||||
List<ui.TextBox> _selectionRects;
|
||||
|
||||
/// The region of text that is selected, if any.
|
||||
TextSelection get selection => _selection;
|
||||
TextSelection _selection;
|
||||
set selection(TextSelection value) {
|
||||
@ -111,6 +124,11 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// The offset at which the text should be painted.
|
||||
///
|
||||
/// If the text content is larger than the editable line itself, the editable
|
||||
/// line clips the text. This property controls which part of the text is
|
||||
/// visible by shifting the text by the given offset before clipping.
|
||||
Offset get paintOffset => _paintOffset;
|
||||
Offset _paintOffset;
|
||||
set paintOffset(Offset value) {
|
||||
@ -120,8 +138,18 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// Returns the global coordinates of the endpoints of the given selection.
|
||||
///
|
||||
/// If the selection is collapsed (and therefore occupies a single point), the
|
||||
/// returned list is of length one. Otherwise, the selection is not collapsed
|
||||
/// and the returned list is of length two. In this case, however, the two
|
||||
/// points might actually be co-located (e.g., because of a bidirectional
|
||||
/// selection that contains some text but whose ends meet in the middle).
|
||||
List<TextSelectionPoint> getEndpointsForSelection(TextSelection selection) {
|
||||
_textPainter.layout(); // TODO(mpcomplete): is this hacky?
|
||||
// TODO(mpcomplete): We should be more disciplined about when we dirty the
|
||||
// layout state of the text painter so that we can know that the layout is
|
||||
// clean at this point.
|
||||
_textPainter.layout();
|
||||
|
||||
Offset offset = _paintOffset + new Offset(0.0, -_kCaretHeightOffset);
|
||||
|
||||
@ -141,9 +169,10 @@ class RenderEditableLine extends RenderBox {
|
||||
}
|
||||
}
|
||||
|
||||
TextPosition getPositionForPoint(Point global) {
|
||||
global += -paintOffset;
|
||||
return _textPainter.getPositionForOffset(globalToLocal(global).toOffset());
|
||||
/// Returns the position in the text for the given global coordinate.
|
||||
TextPosition getPositionForPoint(Point globalPosition) {
|
||||
globalPosition += -paintOffset;
|
||||
return _textPainter.getPositionForOffset(globalToLocal(globalPosition).toOffset());
|
||||
}
|
||||
|
||||
Size _contentSize;
|
||||
|
@ -90,7 +90,10 @@ typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints)
|
||||
/// positioned along the cross axis according to the [crossAxisAlignment] property.
|
||||
class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>,
|
||||
RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData> {
|
||||
|
||||
/// Creates a flex render object.
|
||||
///
|
||||
/// By default, the flex layout is horizontal and children are aligned to the
|
||||
/// start of the main axis and the center of the cross axis.
|
||||
RenderFlex({
|
||||
List<RenderBox> children,
|
||||
FlexDirection direction: FlexDirection.horizontal,
|
||||
|
@ -33,6 +33,16 @@ List<double> _generateRegularOffsets(int count, double size) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Specifies the geometry of tiles in a grid.
|
||||
///
|
||||
/// A grid specificiation divides a fixed width and height into a certain number
|
||||
/// of rows and columns, each with a specific size.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [CustomGrid]
|
||||
/// * [GridDelegate]
|
||||
/// * [RenderGrid]
|
||||
class GridSpecification {
|
||||
/// Creates a grid specification from an explicit list of offsets.
|
||||
GridSpecification.fromOffsets({
|
||||
@ -118,7 +128,17 @@ class GridSpecification {
|
||||
}
|
||||
|
||||
/// Where to place a child within a grid.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [CustomGrid]
|
||||
/// * [GridDelegate]
|
||||
/// * [RenderGrid]
|
||||
class GridChildPlacement {
|
||||
/// Creates a placement for a child in a grid.
|
||||
///
|
||||
/// The [column] and [row] arguments must not be null. By default, the child
|
||||
/// spans a single column and row.
|
||||
GridChildPlacement({
|
||||
this.column,
|
||||
this.row,
|
||||
@ -186,6 +206,9 @@ abstract class GridDelegate {
|
||||
|
||||
/// A [GridDelegate] the places its children in order throughout the grid.
|
||||
abstract class GridDelegateWithInOrderChildPlacement extends GridDelegate {
|
||||
/// Initializes [columnSpacing], [rowSpacing], and [padding] for subclasses.
|
||||
///
|
||||
/// By default, the [columnSpacing], [rowSpacing], and [padding] are zero.
|
||||
GridDelegateWithInOrderChildPlacement({
|
||||
this.columnSpacing: 0.0,
|
||||
this.rowSpacing: 0.0,
|
||||
@ -202,7 +225,7 @@ abstract class GridDelegateWithInOrderChildPlacement extends GridDelegate {
|
||||
/// The vertical distance between rows.
|
||||
final double rowSpacing;
|
||||
|
||||
// Insets for the entire grid.
|
||||
/// Insets for the entire grid.
|
||||
final EdgeInsets padding;
|
||||
|
||||
@override
|
||||
@ -225,6 +248,9 @@ abstract class GridDelegateWithInOrderChildPlacement extends GridDelegate {
|
||||
|
||||
/// A [GridDelegate] that divides the grid's width evenly amount a fixed number of columns.
|
||||
class FixedColumnCountGridDelegate extends GridDelegateWithInOrderChildPlacement {
|
||||
/// Creates a grid delegate that uses a fixed column count.
|
||||
///
|
||||
/// The [columnCount] argument must not be null.
|
||||
FixedColumnCountGridDelegate({
|
||||
this.columnCount,
|
||||
double columnSpacing: 0.0,
|
||||
@ -286,6 +312,9 @@ class FixedColumnCountGridDelegate extends GridDelegateWithInOrderChildPlacement
|
||||
/// - The tile width is at most [maxTileWidth].
|
||||
///
|
||||
class MaxTileWidthGridDelegate extends GridDelegateWithInOrderChildPlacement {
|
||||
/// Creates a grid delegate that uses a max tile width.
|
||||
///
|
||||
/// The [maxTileWidth] argument must not be null.
|
||||
MaxTileWidthGridDelegate({
|
||||
this.maxTileWidth,
|
||||
this.tileAspectRatio: 1.0,
|
||||
@ -363,6 +392,9 @@ class GridParentData extends ContainerBoxParentDataMixin<RenderBox> {
|
||||
/// Additionally, grid layout materializes all of its children, which makes it
|
||||
/// most useful for grids containing a moderate number of tiles.
|
||||
class RenderGrid extends RenderVirtualViewport<GridParentData> {
|
||||
/// Creates a grid render object.
|
||||
///
|
||||
/// The [delegate] argument must not be null.
|
||||
RenderGrid({
|
||||
List<RenderBox> children,
|
||||
GridDelegate delegate,
|
||||
@ -382,6 +414,17 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
|
||||
}
|
||||
|
||||
/// The delegate that controls the layout of the children.
|
||||
///
|
||||
/// If the new delegate is the same as the previous one, this does nothing.
|
||||
///
|
||||
/// If the new delegate is the same class as the previous one, then the new
|
||||
/// delegate has its [GridDelegate.shouldRelayout] called; if the result is
|
||||
/// `true`, then the delegate will be called.
|
||||
///
|
||||
/// If the new delegate is a different class than the previous one, then the
|
||||
/// delegate will be called.
|
||||
///
|
||||
/// The delegate must not be null.
|
||||
GridDelegate get delegate => _delegate;
|
||||
GridDelegate _delegate;
|
||||
set delegate (GridDelegate newDelegate) {
|
||||
@ -457,6 +500,10 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
}
|
||||
|
||||
/// The specification of this grid.
|
||||
///
|
||||
/// The grid specification cannot be set directly. Instead, set a [delegate]
|
||||
/// to control the specification.
|
||||
GridSpecification get specification => _specification;
|
||||
GridSpecification _specification;
|
||||
int _specificationChildCount;
|
||||
|
@ -16,6 +16,7 @@ export 'package:flutter/painting.dart' show
|
||||
/// The render image attempts to find a size for itself that fits in the given
|
||||
/// constraints and preserves the image's intrinisc aspect ratio.
|
||||
class RenderImage extends RenderBox {
|
||||
/// Creates a render box that displays an image.
|
||||
RenderImage({
|
||||
ui.Image image,
|
||||
double width,
|
||||
|
@ -73,8 +73,13 @@ abstract class Layer {
|
||||
@override
|
||||
String toString() => '$runtimeType';
|
||||
|
||||
/// The object responsible for creating this layer.
|
||||
///
|
||||
/// Defaults to the value of [RenderObject.debugCreator] for the render object
|
||||
/// that created this layer. Used in debug messages.
|
||||
dynamic debugCreator;
|
||||
|
||||
/// Returns a string representation of this layer and its descendants.
|
||||
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
|
||||
String result = '$prefixLineOne$this\n';
|
||||
final String childrenDescription = debugDescribeChildren(prefixOtherLines);
|
||||
@ -88,11 +93,13 @@ abstract class Layer {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Add additional information to the given description for use by [toStringDeep].
|
||||
void debugFillDescription(List<String> description) {
|
||||
if (debugCreator != null)
|
||||
description.add('creator: $debugCreator');
|
||||
}
|
||||
|
||||
/// Returns a description of this layer's children for use by [toStringDeep].
|
||||
String debugDescribeChildren(String prefix) => '';
|
||||
}
|
||||
|
||||
@ -109,8 +116,15 @@ class PictureLayer extends Layer {
|
||||
}
|
||||
}
|
||||
|
||||
/// (mojo-only) A layer that represents content from another process.
|
||||
class ChildSceneLayer extends Layer {
|
||||
ChildSceneLayer({ this.offset, this.devicePixelRatio, this.physicalWidth, this.physicalHeight, this.sceneToken });
|
||||
ChildSceneLayer({
|
||||
this.offset,
|
||||
this.devicePixelRatio,
|
||||
this.physicalWidth,
|
||||
this.physicalHeight,
|
||||
this.sceneToken
|
||||
});
|
||||
|
||||
Offset offset;
|
||||
double devicePixelRatio;
|
||||
@ -142,6 +156,7 @@ class ChildSceneLayer extends Layer {
|
||||
/// A layer that indicates to the compositor that it should display
|
||||
/// certain performance statistics within it.
|
||||
class PerformanceOverlayLayer extends Layer {
|
||||
/// Creates a layer that displays a performance overlay.
|
||||
PerformanceOverlayLayer({
|
||||
this.overlayRect,
|
||||
this.optionsMask,
|
||||
@ -151,9 +166,13 @@ class PerformanceOverlayLayer extends Layer {
|
||||
/// The rectangle in this layer's coodinate system that the overlay should occupy.
|
||||
Rect overlayRect;
|
||||
|
||||
/// A mask specifying the statistics to display.
|
||||
/// The mask is created by shifting 1 by the index of the specific
|
||||
/// [PerformanceOverlayOption] to enable.
|
||||
final int optionsMask;
|
||||
|
||||
/// The rasterizer threshold is an integer specifying the number of frame
|
||||
/// intervals that the rasterizer must miss before it decides that the frame
|
||||
/// is suitable for capturing an SkPicture trace for further analysis.
|
||||
final int rasterizerThreshold;
|
||||
|
||||
@override
|
||||
@ -164,7 +183,6 @@ class PerformanceOverlayLayer extends Layer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A composited layer that has a list of children
|
||||
class ContainerLayer extends Layer {
|
||||
/// The first composited layer in this layer's child list
|
||||
@ -284,7 +302,19 @@ class ContainerLayer extends Layer {
|
||||
}
|
||||
}
|
||||
|
||||
/// A layer that is displayed at an offset from its parent layer.
|
||||
///
|
||||
/// Offset layers are key to efficient repainting because they are created by
|
||||
/// repaint boundaries in the [RenderObject] tree (see
|
||||
/// [RenderObject.isRepaintBoundary]). When a render object that is a repaint
|
||||
/// boundary is asked to paint at given offset in a [PaintingContext], the
|
||||
/// render object first checks whether it needs to repaint itself. If not, it
|
||||
/// reuses its existing [OffsetLayer] (and its entire subtree) by mutating its
|
||||
/// [offset] property, cutting off the paint walk.
|
||||
class OffsetLayer extends ContainerLayer {
|
||||
/// Creates an offset layer.
|
||||
///
|
||||
/// By default, [offset] is zero.
|
||||
OffsetLayer({ this.offset: Offset.zero });
|
||||
|
||||
/// Offset from parent in the parent's coordinate system.
|
||||
@ -305,12 +335,14 @@ class OffsetLayer extends ContainerLayer {
|
||||
|
||||
/// A composite layer that clips its children using a rectangle
|
||||
class ClipRectLayer extends ContainerLayer {
|
||||
/// Creates a layer with a rectangular clip.
|
||||
///
|
||||
/// The [clipRect] property must be non-null before the compositing phase of
|
||||
/// the pipeline.
|
||||
ClipRectLayer({ this.clipRect });
|
||||
|
||||
/// The rectangle to clip in the parent's coordinate system
|
||||
Rect clipRect;
|
||||
// TODO(abarth): Why is the rectangle in the parent's coordinate system
|
||||
// instead of in the coordinate system of this layer?
|
||||
|
||||
@override
|
||||
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
|
||||
@ -328,12 +360,14 @@ class ClipRectLayer extends ContainerLayer {
|
||||
|
||||
/// A composite layer that clips its children using a rounded rectangle
|
||||
class ClipRRectLayer extends ContainerLayer {
|
||||
/// Creates a layer with a rounded-rectangular clip.
|
||||
///
|
||||
/// The [clipRRect] property must be non-null before the compositing phase of
|
||||
/// the pipeline.
|
||||
ClipRRectLayer({ this.clipRRect });
|
||||
|
||||
/// The rounded-rect to clip in the parent's coordinate system
|
||||
RRect clipRRect;
|
||||
// TODO(abarth): Why is the rounded-rect in the parent's coordinate system
|
||||
// instead of in the coordinate system of this layer?
|
||||
|
||||
@override
|
||||
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
|
||||
@ -351,12 +385,14 @@ class ClipRRectLayer extends ContainerLayer {
|
||||
|
||||
/// A composite layer that clips its children using a path
|
||||
class ClipPathLayer extends ContainerLayer {
|
||||
/// Creates a layer with a path-based clip.
|
||||
///
|
||||
/// The [clipPath] property must be non-null before the compositing phase of
|
||||
/// the pipeline.
|
||||
ClipPathLayer({ this.clipPath });
|
||||
|
||||
/// The path to clip in the parent's coordinate system
|
||||
Path clipPath;
|
||||
// TODO(abarth): Why is the path in the parent's coordinate system instead of
|
||||
// in the coordinate system of this layer?
|
||||
|
||||
@override
|
||||
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
|
||||
@ -374,7 +410,14 @@ class ClipPathLayer extends ContainerLayer {
|
||||
|
||||
/// A composited layer that applies a transformation matrix to its children
|
||||
class TransformLayer extends OffsetLayer {
|
||||
TransformLayer({ Offset offset: Offset.zero, this.transform }): super(offset: offset);
|
||||
/// Creates a transform layer.
|
||||
///
|
||||
/// The [transform] property must be non-null before the compositing phase of
|
||||
/// the pipeline.
|
||||
TransformLayer({
|
||||
Offset offset: Offset.zero,
|
||||
this.transform
|
||||
}): super(offset: offset);
|
||||
|
||||
/// The matrix to apply
|
||||
Matrix4 transform;
|
||||
@ -398,6 +441,10 @@ class TransformLayer extends OffsetLayer {
|
||||
|
||||
/// A composited layer that makes its children partially transparent
|
||||
class OpacityLayer extends ContainerLayer {
|
||||
/// Creates an opacity layer.
|
||||
///
|
||||
/// The [alpha] property must be non-null before the compositing phase of
|
||||
/// the pipeline.
|
||||
OpacityLayer({ this.alpha });
|
||||
|
||||
/// The amount to multiply into the alpha channel
|
||||
@ -422,6 +469,10 @@ class OpacityLayer extends ContainerLayer {
|
||||
|
||||
/// A composited layer that applies a shader to hits children.
|
||||
class ShaderMaskLayer extends ContainerLayer {
|
||||
/// Creates a shader mask layer.
|
||||
///
|
||||
/// The [shader], [maskRect], and [transferMode] properties must be non-null
|
||||
/// before the compositing phase of the pipeline.
|
||||
ShaderMaskLayer({ this.shader, this.maskRect, this.transferMode });
|
||||
|
||||
/// The shader to apply to the children.
|
||||
@ -451,6 +502,10 @@ class ShaderMaskLayer extends ContainerLayer {
|
||||
|
||||
/// A composited layer that applies a filter to the existing contents of the scene.
|
||||
class BackdropFilterLayer extends ContainerLayer {
|
||||
/// Creates a backdrop filter layer.
|
||||
///
|
||||
/// The [filter] property must be non-null before the compositing phase of the
|
||||
/// pipeline.
|
||||
BackdropFilterLayer({ this.filter });
|
||||
|
||||
/// The filter to apply to the existing contents of the scene.
|
||||
|
@ -11,7 +11,20 @@ import 'viewport.dart';
|
||||
/// Parent data for use with [RenderList].
|
||||
class ListParentData extends ContainerBoxParentDataMixin<RenderBox> { }
|
||||
|
||||
/// A linear layout of children intended for use as a virtual viewport.
|
||||
///
|
||||
/// Children are layout out in order along the main axis. If [itemExtent] is
|
||||
/// non-null, each child is required to have exactly [itemExtent] extent in the
|
||||
/// main axis. If [itemExtent] is null, each child is required to have the same
|
||||
/// extent in the main axis as the list itself.
|
||||
///
|
||||
/// In the cross axis, the render list expands to fill the available space and
|
||||
/// each child is required to have the same extent in the cross axis as the list
|
||||
/// itself.
|
||||
class RenderList extends RenderVirtualViewport<ListParentData> {
|
||||
/// Creates a render list.
|
||||
///
|
||||
/// By default, the list is oriented vertically and anchored at the start.
|
||||
RenderList({
|
||||
List<RenderBox> children,
|
||||
double itemExtent,
|
||||
@ -35,16 +48,20 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
|
||||
addAll(children);
|
||||
}
|
||||
|
||||
/// The main-axis extent of each item in the list.
|
||||
///
|
||||
/// If [itemExtent] is null, the items are required to match the main-axis
|
||||
/// extent of the list itself.
|
||||
double get itemExtent => _itemExtent;
|
||||
double _itemExtent;
|
||||
set itemExtent (double newValue) {
|
||||
assert(newValue != null);
|
||||
if (_itemExtent == newValue)
|
||||
return;
|
||||
_itemExtent = newValue;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
/// The amount of space by which to inset the children inside the list.
|
||||
EdgeInsets get padding => _padding;
|
||||
EdgeInsets _padding;
|
||||
set padding (EdgeInsets newValue) {
|
||||
|
@ -35,6 +35,10 @@ class ParentData {
|
||||
String toString() => '<none>';
|
||||
}
|
||||
|
||||
/// Signature for painting into a [PaintingContext].
|
||||
///
|
||||
/// The `offset` argument is the offset from the origin of the coordinate system
|
||||
/// of the [PaintingContext.canvas] to the coordinate system of the callee.
|
||||
typedef void PaintingContextCallback(PaintingContext context, Offset offset);
|
||||
|
||||
/// A place to paint.
|
||||
@ -208,6 +212,7 @@ class PaintingContext {
|
||||
));
|
||||
}
|
||||
|
||||
/// (mojo-only) Draws content from another process.
|
||||
void pushChildScene(Offset offset, double devicePixelRatio, int physicalWidth, int physicalHeight, mojom.SceneToken sceneToken) {
|
||||
_stopRecordingIfNeeded();
|
||||
_appendLayer(new ChildSceneLayer(
|
||||
@ -458,9 +463,11 @@ abstract class Constraints {
|
||||
});
|
||||
}
|
||||
|
||||
/// Signature for a function that is called for each [RenderObject].
|
||||
typedef void RenderObjectVisitor(RenderObject child);
|
||||
|
||||
/// Signature for a function that is called during layout.
|
||||
typedef void LayoutCallback(Constraints constraints);
|
||||
typedef double ExtentCallback(Constraints constraints);
|
||||
|
||||
class _SemanticsGeometry {
|
||||
_SemanticsGeometry() : transform = new Matrix4.identity();
|
||||
@ -975,6 +982,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
/// Override in subclasses with children and call the visitor for each child
|
||||
void visitChildren(RenderObjectVisitor visitor) { }
|
||||
|
||||
/// The object responsible for creating this render object.
|
||||
///
|
||||
/// Used in debug messages.
|
||||
dynamic debugCreator;
|
||||
void _debugReportException(String method, dynamic exception, StackTrace stack) {
|
||||
FlutterError.reportError(new FlutterErrorDetailsForRendering(
|
||||
@ -1601,7 +1611,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
/// called on).
|
||||
///
|
||||
/// This might be called if, e.g., the device pixel ratio changed.
|
||||
void replaceRootLayer(ContainerLayer rootLayer) {
|
||||
void replaceRootLayer(OffsetLayer rootLayer) {
|
||||
assert(attached);
|
||||
assert(parent is! RenderObject);
|
||||
assert(!owner._debugDoingPaint);
|
||||
|
@ -9,6 +9,7 @@ import 'object.dart';
|
||||
/// without making the child available for hit testing, and without taking any
|
||||
/// room in the parent.
|
||||
class RenderOffStage extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
|
||||
/// Creates an off-stage render object.
|
||||
RenderOffStage({ RenderBox child }) {
|
||||
this.child = child;
|
||||
}
|
||||
|
@ -57,6 +57,9 @@ class RenderPerformanceOverlay extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// The rasterizer threshold is an integer specifying the number of frame
|
||||
/// intervals that the rasterizer must miss before it decides that the frame
|
||||
/// is suitable for capturing an SkPicture trace for further analysis.
|
||||
int get rasterizerThreshold => _rasterizerThreshold;
|
||||
int _rasterizerThreshold;
|
||||
set rasterizerThreshold (int threshold) {
|
||||
@ -82,7 +85,7 @@ class RenderPerformanceOverlay extends RenderBox {
|
||||
return constraints.constrainWidth(0.0);
|
||||
}
|
||||
|
||||
double get intrinsicHeight {
|
||||
double get _intrinsicHeight {
|
||||
const double kDefaultGraphHeight = 80.0;
|
||||
double result = 0.0;
|
||||
if ((optionsMask | (1 << PerformanceOverlayOption.displayRasterizerStatistics.index) > 0) ||
|
||||
@ -96,17 +99,17 @@ class RenderPerformanceOverlay extends RenderBox {
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
||||
return constraints.constrainHeight(intrinsicHeight);
|
||||
return constraints.constrainHeight(_intrinsicHeight);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(BoxConstraints constraints) {
|
||||
return constraints.constrainHeight(intrinsicHeight);
|
||||
return constraints.constrainHeight(_intrinsicHeight);
|
||||
}
|
||||
|
||||
@override
|
||||
void performResize() {
|
||||
size = constraints.constrain(new Size(double.INFINITY, intrinsicHeight));
|
||||
size = constraints.constrain(new Size(double.INFINITY, _intrinsicHeight));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -32,6 +32,11 @@ export 'package:flutter/gestures.dart' show
|
||||
/// for render objects that wish to mimic most, but not all, of the properties
|
||||
/// of their child.
|
||||
class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
|
||||
/// Creates a proxy render box.
|
||||
///
|
||||
/// Proxy render boxes are rarely created directly because they simply proxy
|
||||
/// the render box protocol to [child]. Instead, consider using one of the
|
||||
/// subclasses.
|
||||
RenderProxyBox([RenderBox child = null]) {
|
||||
this.child = child;
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ const double _kQuarterTurnsInRadians = math.PI / 2.0;
|
||||
/// this object applies its rotation prior to layout, which means the entire
|
||||
/// rotated box consumes only as much space as required by the rotated child.
|
||||
class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
|
||||
/// Creates a rotated render box.
|
||||
///
|
||||
/// The [quarterTurns] argument must not be null.
|
||||
RenderRotatedBox({
|
||||
int quarterTurns,
|
||||
RenderBox child
|
||||
|
@ -22,19 +22,30 @@ import 'node.dart';
|
||||
/// contract that semantic annotators must follow.
|
||||
typedef void SemanticAnnotator(SemanticsNode semantics);
|
||||
|
||||
/// Interface for RenderObjects to implement when they want to support
|
||||
/// Interface for [RenderObject]s to implement when they want to support
|
||||
/// being tapped, etc.
|
||||
///
|
||||
/// These handlers will only be called if the relevant flag is set
|
||||
/// (e.g. handleSemanticTap() will only be called if canBeTapped is
|
||||
/// true, handleSemanticScrollDown() will only be called if
|
||||
/// canBeScrolledVertically is true, etc).
|
||||
/// (e.g. [handleSemanticTap]() will only be called if
|
||||
/// [SemanticsNode.canBeTapped] is true, [handleSemanticScrollDown]() will only
|
||||
/// be called if [SemanticsNode.canBeScrolledVertically] is true, etc).
|
||||
abstract class SemanticActionHandler {
|
||||
/// Called when the user taps on the render object.
|
||||
void handleSemanticTap() { }
|
||||
|
||||
/// Called when the user presses on the render object for a long period of time.
|
||||
void handleSemanticLongPress() { }
|
||||
|
||||
/// Called when the user scrolls to the left.
|
||||
void handleSemanticScrollLeft() { }
|
||||
|
||||
/// Called when the user scrolls to the right.
|
||||
void handleSemanticScrollRight() { }
|
||||
|
||||
/// Called when the user scrolls up.
|
||||
void handleSemanticScrollUp() { }
|
||||
|
||||
/// Called when the user scrolls down.
|
||||
void handleSemanticScrollDown() { }
|
||||
}
|
||||
|
||||
@ -49,14 +60,30 @@ enum _SemanticFlags {
|
||||
isChecked,
|
||||
}
|
||||
|
||||
/// Signature for a function that is called for each [SemanticsNode].
|
||||
///
|
||||
/// Return false to stop visiting nodes.
|
||||
typedef bool SemanticsNodeVisitor(SemanticsNode node);
|
||||
|
||||
/// A node that represents some semantic data.
|
||||
///
|
||||
/// The semantics tree is maintained during the semantics phase of the pipeline
|
||||
/// (i.e., during [PipelineOwner.flushSemantics]), which happens after
|
||||
/// compositing. The semantics tree is then uploaded into the engine for use
|
||||
/// by assistive technology.
|
||||
class SemanticsNode extends AbstractNode {
|
||||
/// Creates a semantic node.
|
||||
///
|
||||
/// Each semantic node has a unique identifier that is assigned when the node
|
||||
/// is created.
|
||||
SemanticsNode({
|
||||
SemanticActionHandler handler
|
||||
}) : _id = _generateNewId(),
|
||||
_actionHandler = handler;
|
||||
|
||||
/// Creates a semantic node to represent the root of the semantics tree.
|
||||
///
|
||||
/// The root node is assigned an identifier of zero.
|
||||
SemanticsNode.root({
|
||||
SemanticActionHandler handler,
|
||||
Object owner
|
||||
@ -78,8 +105,13 @@ class SemanticsNode extends AbstractNode {
|
||||
// GEOMETRY
|
||||
// These are automatically handled by RenderObject's own logic
|
||||
|
||||
/// The transform from this node's coordinate system to its parent's coordinate system.
|
||||
///
|
||||
/// By default, the transform is null, which represents the identity
|
||||
/// transformation (i.e., that this node has the same coorinate system as its
|
||||
/// parent).
|
||||
Matrix4 get transform => _transform;
|
||||
Matrix4 _transform; // defaults to null, which we say means the identity matrix
|
||||
Matrix4 _transform;
|
||||
set transform (Matrix4 value) {
|
||||
if (!MatrixUtils.matrixEquals(_transform, value)) {
|
||||
_transform = value;
|
||||
@ -87,6 +119,7 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// The bounding box for this node in its coordinate system.
|
||||
Rect get rect => _rect;
|
||||
Rect _rect = Rect.zero;
|
||||
set rect (Rect value) {
|
||||
@ -97,6 +130,7 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether [rect] might have been influenced by clips applied by ancestors.
|
||||
bool wasAffectedByClip = false;
|
||||
|
||||
|
||||
@ -118,6 +152,7 @@ class SemanticsNode extends AbstractNode {
|
||||
return _actionHandler != null && _flags[flag];
|
||||
}
|
||||
|
||||
/// Whether all this node and all of its descendants should be treated as one logical entity.
|
||||
bool get mergeAllDescendantsIntoThisNode => _flags[_SemanticFlags.mergeAllDescendantsIntoThisNode];
|
||||
set mergeAllDescendantsIntoThisNode(bool value) => _setFlag(_SemanticFlags.mergeAllDescendantsIntoThisNode, value);
|
||||
|
||||
@ -126,24 +161,31 @@ class SemanticsNode extends AbstractNode {
|
||||
|
||||
bool get _shouldMergeAllDescendantsIntoThisNode => mergeAllDescendantsIntoThisNode || _inheritedMergeAllDescendantsIntoThisNode;
|
||||
|
||||
/// Whether this node responds to tap gestures.
|
||||
bool get canBeTapped => _flags[_SemanticFlags.canBeTapped];
|
||||
set canBeTapped(bool value) => _setFlag(_SemanticFlags.canBeTapped, value, needsHandler: true);
|
||||
|
||||
/// Whether this node responds to long-press gestures.
|
||||
bool get canBeLongPressed => _flags[_SemanticFlags.canBeLongPressed];
|
||||
set canBeLongPressed(bool value) => _setFlag(_SemanticFlags.canBeLongPressed, value, needsHandler: true);
|
||||
|
||||
/// Whether this node responds to horizontal scrolling.
|
||||
bool get canBeScrolledHorizontally => _flags[_SemanticFlags.canBeScrolledHorizontally];
|
||||
set canBeScrolledHorizontally(bool value) => _setFlag(_SemanticFlags.canBeScrolledHorizontally, value, needsHandler: true);
|
||||
|
||||
/// Whether this node responds to vertical scrolling.
|
||||
bool get canBeScrolledVertically => _flags[_SemanticFlags.canBeScrolledVertically];
|
||||
set canBeScrolledVertically(bool value) => _setFlag(_SemanticFlags.canBeScrolledVertically, value, needsHandler: true);
|
||||
|
||||
/// Whether this node has Boolean state that can be controlled by the user.
|
||||
bool get hasCheckedState => _flags[_SemanticFlags.hasCheckedState];
|
||||
set hasCheckedState(bool value) => _setFlag(_SemanticFlags.hasCheckedState, value);
|
||||
|
||||
/// If this node has Boolean state that can be controlled by the user, whether that state is on or off, cooresponding to `true` and `false`, respectively.
|
||||
bool get isChecked => _flags[_SemanticFlags.isChecked];
|
||||
set isChecked(bool value) => _setFlag(_SemanticFlags.isChecked, value);
|
||||
|
||||
/// A textual description of this node.
|
||||
String get label => _label;
|
||||
String _label = '';
|
||||
set label(String value) {
|
||||
@ -154,6 +196,7 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Restore this node to its default state.
|
||||
void reset() {
|
||||
bool hadInheritedMergeAllDescendantsIntoThisNode = _inheritedMergeAllDescendantsIntoThisNode;
|
||||
_flags.reset();
|
||||
@ -164,6 +207,8 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
|
||||
List<SemanticsNode> _newChildren;
|
||||
|
||||
/// Append the given children as children of this node.
|
||||
void addChildren(Iterable<SemanticsNode> children) {
|
||||
_newChildren ??= <SemanticsNode>[];
|
||||
_newChildren.addAll(children);
|
||||
@ -189,8 +234,16 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
|
||||
List<SemanticsNode> _children;
|
||||
|
||||
/// Whether this node has a non-zero number of children.
|
||||
bool get hasChildren => _children?.isNotEmpty ?? false;
|
||||
bool _dead = false;
|
||||
|
||||
/// Called during the compilation phase after all the children of this node have been compiled.
|
||||
///
|
||||
/// This function lets the semantic node respond to all the changes to its
|
||||
/// child list for the given frame at once instead of needing to process the
|
||||
/// changes incrementally as new children are compiled.
|
||||
void finalizeChildren() {
|
||||
if (_children != null) {
|
||||
for (SemanticsNode child in _children)
|
||||
@ -353,8 +406,23 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
|
||||
static List<mojom.SemanticsListener> _listeners;
|
||||
|
||||
/// Whether there are currently any consumers of semantic data.
|
||||
///
|
||||
/// If there are no consumers of semantic data, there is no need to compile
|
||||
/// semantic data into a [SemanticsNode] tree.
|
||||
static bool get hasListeners => _listeners != null && _listeners.length > 0;
|
||||
static VoidCallback onSemanticsEnabled; // set by the binding
|
||||
|
||||
/// Called when the first consumer of semantic data arrives.
|
||||
///
|
||||
/// Typically set by [RendererBinding].
|
||||
static VoidCallback onSemanticsEnabled;
|
||||
|
||||
/// Add a consumer of semantic data.
|
||||
///
|
||||
/// After the [PipelineOwner] updates the semantic data for a given frame, it
|
||||
/// calls [sendSemanticsTree], which uploads the data to each listener
|
||||
/// registered with this function.
|
||||
static void addListener(mojom.SemanticsListener listener) {
|
||||
if (!hasListeners) {
|
||||
assert(onSemanticsEnabled != null); // initialise the binding _before_ adding listeners
|
||||
@ -364,6 +432,7 @@ class SemanticsNode extends AbstractNode {
|
||||
_listeners.add(listener);
|
||||
}
|
||||
|
||||
/// Uploads the semantics tree to the listeners registered with [addListener].
|
||||
static void sendSemanticsTree() {
|
||||
assert(hasListeners);
|
||||
for (SemanticsNode oldNode in _detachedNodes) {
|
||||
@ -430,7 +499,7 @@ class SemanticsNode extends AbstractNode {
|
||||
_dirtyNodes.clear();
|
||||
}
|
||||
|
||||
static SemanticActionHandler getSemanticActionHandlerForId(int id, { _SemanticFlags neededFlag }) {
|
||||
static SemanticActionHandler _getSemanticActionHandlerForId(int id, { _SemanticFlags neededFlag }) {
|
||||
assert(neededFlag != null);
|
||||
SemanticsNode result = _nodes[id];
|
||||
if (result != null && result._shouldMergeAllDescendantsIntoThisNode && !result._canHandle(neededFlag)) {
|
||||
@ -463,6 +532,7 @@ class SemanticsNode extends AbstractNode {
|
||||
')';
|
||||
}
|
||||
|
||||
/// Returns a string representation of this node and its descendants.
|
||||
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
|
||||
String result = '$prefixLineOne$this\n';
|
||||
if (_children != null && _children.isNotEmpty) {
|
||||
@ -476,39 +546,42 @@ class SemanticsNode extends AbstractNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Exposes the [SemanticsNode] tree to the underlying platform.
|
||||
class SemanticsServer extends mojom.SemanticsServer {
|
||||
@override
|
||||
void addSemanticsListener(mojom.SemanticsListenerProxy listener) {
|
||||
// TODO(abarth): We should remove the listener when this pipe closes.
|
||||
// See <https://github.com/flutter/flutter/issues/3342>.
|
||||
SemanticsNode.addListener(listener.ptr);
|
||||
}
|
||||
|
||||
@override
|
||||
void tap(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeTapped)?.handleSemanticTap();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeTapped)?.handleSemanticTap();
|
||||
}
|
||||
|
||||
@override
|
||||
void longPress(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeLongPressed)?.handleSemanticLongPress();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeLongPressed)?.handleSemanticLongPress();
|
||||
}
|
||||
|
||||
@override
|
||||
void scrollLeft(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledHorizontally)?.handleSemanticScrollLeft();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledHorizontally)?.handleSemanticScrollLeft();
|
||||
}
|
||||
|
||||
@override
|
||||
void scrollRight(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledHorizontally)?.handleSemanticScrollRight();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledHorizontally)?.handleSemanticScrollRight();
|
||||
}
|
||||
|
||||
@override
|
||||
void scrollUp(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledVertically)?.handleSemanticScrollUp();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledVertically)?.handleSemanticScrollUp();
|
||||
}
|
||||
|
||||
@override
|
||||
void scrollDown(int nodeID) {
|
||||
SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledVertically)?.handleSemanticScrollDown();
|
||||
SemanticsNode._getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeScrolledVertically)?.handleSemanticScrollDown();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import 'object.dart';
|
||||
/// Abstract class for one-child-layout render boxes that provide control over
|
||||
/// the child's position.
|
||||
abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
|
||||
/// Initializes the [child] property for sublasses.
|
||||
RenderShiftedBox(RenderBox child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ class RelativeRect {
|
||||
);
|
||||
}
|
||||
|
||||
/// A rect that covers the entire container.
|
||||
static final RelativeRect fill = new RelativeRect.fromLTRB(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
/// Distance from the left side of the container to the left side of this rectangle.
|
||||
|
@ -10,6 +10,7 @@ import 'object.dart';
|
||||
|
||||
/// Parent data used by [RenderTable] for its children.
|
||||
class TableCellParentData extends BoxParentData {
|
||||
/// Where this cell should be placed vertically.
|
||||
TableCellVerticalAlignment verticalAlignment;
|
||||
|
||||
/// The column that the child was in the last time it was laid out.
|
||||
@ -74,7 +75,7 @@ abstract class TableColumnWidth {
|
||||
/// A flex value can be provided. If specified (and non-null), the
|
||||
/// column will participate in the distribution of remaining space
|
||||
/// once all the non-flexible columns have been sized.
|
||||
class IntrinsicColumnWidth extends TableColumnWidth {
|
||||
class IntrinsicColumnWidth extends TableColumnWidth {
|
||||
const IntrinsicColumnWidth({ double flex }) : _flex = flex;
|
||||
|
||||
@override
|
||||
@ -500,7 +501,7 @@ class RenderTable extends RenderBox {
|
||||
_border = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
|
||||
List<Decoration> get rowDecorations => new List<Decoration>.unmodifiable(_rowDecorations ?? const <Decoration>[]);
|
||||
List<Decoration> _rowDecorations;
|
||||
List<BoxPainter> _rowDecorationPainters;
|
||||
@ -830,7 +831,7 @@ class RenderTable extends RenderBox {
|
||||
// least as big as the target width.
|
||||
double targetWidth;
|
||||
if (maxWidthConstraint.isFinite) {
|
||||
targetWidth = maxWidthConstraint;
|
||||
targetWidth = maxWidthConstraint;
|
||||
} else {
|
||||
targetWidth = minWidthConstraint;
|
||||
}
|
||||
@ -1098,7 +1099,7 @@ class RenderTable extends RenderBox {
|
||||
for (int index = 0; index < _children.length; index += 1) {
|
||||
RenderBox child = _children[index];
|
||||
if (child != null) {
|
||||
final BoxParentData childParentData = child.parentData;
|
||||
final BoxParentData childParentData = child.parentData;
|
||||
context.paintChild(child, childParentData.offset + offset);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ import 'binding.dart';
|
||||
|
||||
/// The layout constraints for the root render object.
|
||||
class ViewConfiguration {
|
||||
/// Creates a view configuration.
|
||||
///
|
||||
/// By default, the view has zero [size] and a [devicePixelRatio] of 1.0.
|
||||
const ViewConfiguration({
|
||||
this.size: Size.zero,
|
||||
this.devicePixelRatio: 1.0,
|
||||
|
@ -24,6 +24,9 @@ enum ViewportAnchor {
|
||||
|
||||
/// The interior and exterior dimensions of a viewport.
|
||||
class ViewportDimensions {
|
||||
/// Creates dimensions for a viewport.
|
||||
///
|
||||
/// By default, the content and container sizes are zero.
|
||||
const ViewportDimensions({
|
||||
this.contentSize: Size.zero,
|
||||
this.containerSize: Size.zero
|
||||
|
@ -27,7 +27,9 @@ class _ChildViewWidget extends LeafRenderObjectWidget {
|
||||
_ChildViewWidget({
|
||||
ChildViewConnection child,
|
||||
this.scale
|
||||
}) : child = child, super(key: new GlobalObjectKey(child));
|
||||
}) : child = child, super(key: new GlobalObjectKey(child)) {
|
||||
assert(scale != null);
|
||||
}
|
||||
|
||||
final ChildViewConnection child;
|
||||
final double scale;
|
||||
|
Loading…
x
Reference in New Issue
Block a user