Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
c1bd6af9
Commit
c1bd6af9
authored
Sep 01, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add dartdocs for RenderObject
... and other code in object.dart.
parent
99356d10
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
380 additions
and
64 deletions
+380
-64
rendering.dart
packages/flutter/lib/rendering.dart
+4
-1
object.dart
packages/flutter/lib/rendering/object.dart
+372
-62
widgets.dart
packages/flutter/lib/widgets.dart
+4
-1
No files found.
packages/flutter/lib/rendering.dart
View file @
c1bd6af9
...
@@ -2,7 +2,10 @@
...
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
/// Includes and re-exports all Sky rendering classes.
// Includes and re-exports all Sky rendering classes.
/// The Sky render tree
library
rendering
;
export
'package:sky/rendering/auto_layout.dart'
;
export
'package:sky/rendering/auto_layout.dart'
;
export
'package:sky/rendering/block.dart'
;
export
'package:sky/rendering/block.dart'
;
...
...
packages/flutter/lib/rendering/object.dart
View file @
c1bd6af9
...
@@ -16,50 +16,71 @@ import 'package:vector_math/vector_math.dart';
...
@@ -16,50 +16,71 @@ import 'package:vector_math/vector_math.dart';
export
'dart:sky'
show
Point
,
Offset
,
Size
,
Rect
,
Color
,
Paint
,
Path
;
export
'dart:sky'
show
Point
,
Offset
,
Size
,
Rect
,
Color
,
Paint
,
Path
;
export
'package:sky/base/hit_test.dart'
show
EventDisposition
,
HitTestTarget
,
HitTestEntry
,
HitTestResult
;
export
'package:sky/base/hit_test.dart'
show
EventDisposition
,
HitTestTarget
,
HitTestEntry
,
HitTestResult
;
/// Base class for data associated with a [RenderObject] by its parent
///
/// Some render objects wish to store data on their children, such as their
/// input parameters to the parent's layout algorithm or their position relative
/// to other children.
class
ParentData
{
class
ParentData
{
void
detach
()
{
void
detach
()
{
detachSiblings
();
detachSiblings
();
}
}
void
detachSiblings
()
{
}
// workaround for lack of inter-class mixins in Dart
void
detachSiblings
()
{
}
// workaround for lack of inter-class mixins in Dart
/// Override this function in subclasses to merge in data from other instance into this instance
void
merge
(
ParentData
other
)
{
void
merge
(
ParentData
other
)
{
// override this in subclasses to merge in data from other into this
assert
(
other
.
runtimeType
==
this
.
runtimeType
);
assert
(
other
.
runtimeType
==
this
.
runtimeType
);
}
}
String
toString
()
=>
'<none>'
;
String
toString
()
=>
'<none>'
;
}
}
/// Obsolete class that will be removed eventually
class
PaintingCanvas
extends
sky
.
Canvas
{
class
PaintingCanvas
extends
sky
.
Canvas
{
PaintingCanvas
(
sky
.
PictureRecorder
recorder
,
Rect
bounds
)
:
super
(
recorder
,
bounds
);
PaintingCanvas
(
sky
.
PictureRecorder
recorder
,
Rect
bounds
)
:
super
(
recorder
,
bounds
);
// TODO(ianh): Just use sky.Canvas everywhere instead
// TODO(ianh): Just use sky.Canvas everywhere instead
}
}
/// A place to paint
///
/// Rather than holding a canvas directly, render objects paint using a painting
/// context. The painting context has a canvas, which receives the
/// individual draw operations, and also has functions for painting child
/// render objects.
///
/// When painting a child render object, the canvas held by the painting context
/// can change because the draw operations issued before and after painting the
/// child might be recorded in separate compositing layers. For this reason, do
/// not hold a reference to the canvas across operations that might paint
/// child render objects.
class
PaintingContext
{
class
PaintingContext
{
/// Construct a painting context at a given offset with the given bounds
// A PaintingContext wraps a canvas, so that the canvas can be
// hot-swapped whenever we need to start a new layer.
// Don't keep a reference to the PaintingContext.canvas, since it
// can change dynamically after any call to this object's methods.
PaintingContext
.
withOffset
(
Offset
offset
,
Rect
paintBounds
)
{
PaintingContext
.
withOffset
(
Offset
offset
,
Rect
paintBounds
)
{
_containerLayer
=
new
ContainerLayer
(
offset:
offset
);
_containerLayer
=
new
ContainerLayer
(
offset:
offset
);
_startRecording
(
paintBounds
);
_startRecording
(
paintBounds
);
}
}
/// Construct a painting context for paiting into the given layer with the given bounds
PaintingContext
.
withLayer
(
ContainerLayer
containerLayer
,
Rect
paintBounds
)
{
PaintingContext
.
withLayer
(
ContainerLayer
containerLayer
,
Rect
paintBounds
)
{
_containerLayer
=
containerLayer
;
_containerLayer
=
containerLayer
;
_startRecording
(
paintBounds
);
_startRecording
(
paintBounds
);
}
}
/// A backdoor for testing that lets the test set a specific canvas
PaintingContext
.
forTesting
(
this
.
_canvas
);
PaintingContext
.
forTesting
(
this
.
_canvas
);
ContainerLayer
_containerLayer
;
ContainerLayer
_containerLayer
;
/// The layer contain all the composting layers that will be used for this context
ContainerLayer
get
containerLayer
=>
_containerLayer
;
ContainerLayer
get
containerLayer
=>
_containerLayer
;
PictureLayer
_currentLayer
;
PictureLayer
_currentLayer
;
sky
.
PictureRecorder
_recorder
;
sky
.
PictureRecorder
_recorder
;
PaintingCanvas
_canvas
;
PaintingCanvas
_canvas
;
PaintingCanvas
get
canvas
=>
_canvas
;
// Paint on this.
/// The canvas on which to paint
///
/// This getter can return a different canvas object after painting child
/// render objects using this canvas because draw operations before and after
/// a child might need to be recorded in separate compositing layers.
PaintingCanvas
get
canvas
=>
_canvas
;
void
_startRecording
(
Rect
paintBounds
)
{
void
_startRecording
(
Rect
paintBounds
)
{
assert
(
_currentLayer
==
null
);
assert
(
_currentLayer
==
null
);
...
@@ -71,6 +92,7 @@ class PaintingContext {
...
@@ -71,6 +92,7 @@ class PaintingContext {
_containerLayer
.
add
(
_currentLayer
);
_containerLayer
.
add
(
_currentLayer
);
}
}
/// Stop recording draw operations into the current compositing layer
void
endRecording
()
{
void
endRecording
()
{
assert
(
_currentLayer
!=
null
);
assert
(
_currentLayer
!=
null
);
assert
(
_recorder
!=
null
);
assert
(
_recorder
!=
null
);
...
@@ -81,6 +103,7 @@ class PaintingContext {
...
@@ -81,6 +103,7 @@ class PaintingContext {
_canvas
=
null
;
_canvas
=
null
;
}
}
/// Whether the canvas is in a state that permits drawing the given child
bool
debugCanPaintChild
(
RenderObject
child
)
{
bool
debugCanPaintChild
(
RenderObject
child
)
{
// You need to use layers if you are applying transforms, clips,
// You need to use layers if you are applying transforms, clips,
// or similar, to a child. To do so, use the paintChildWith*()
// or similar, to a child. To do so, use the paintChildWith*()
...
@@ -90,6 +113,13 @@ class PaintingContext {
...
@@ -90,6 +113,13 @@ class PaintingContext {
return
true
;
return
true
;
}
}
/// Paint a child render object at the given position
///
/// If the child needs compositing, a new composited layer will be created
/// and inserted into the containerLayer. If the child does not require
/// compositing, the child will be painted into the current canvas.
///
/// Note: After calling this function, the current canvas might change.
void
paintChild
(
RenderObject
child
,
Point
childPosition
)
{
void
paintChild
(
RenderObject
child
,
Point
childPosition
)
{
assert
(
debugCanPaintChild
(
child
));
assert
(
debugCanPaintChild
(
child
));
final
Offset
childOffset
=
childPosition
.
toOffset
();
final
Offset
childOffset
=
childPosition
.
toOffset
();
...
@@ -116,8 +146,13 @@ class PaintingContext {
...
@@ -116,8 +146,13 @@ class PaintingContext {
static
final
Paint
_disableAntialias
=
new
Paint
()..
isAntiAlias
=
false
;
static
final
Paint
_disableAntialias
=
new
Paint
()..
isAntiAlias
=
false
;
/// Paint a child with a rectangular clip
///
/// If the child needs compositing, the clip will be applied by a
/// compositing layer. Otherwise, the clip will be applied by the canvas.
///
/// Note: clipRect is in the parent's coordinate space
void
paintChildWithClipRect
(
RenderObject
child
,
Point
childPosition
,
Rect
clipRect
)
{
void
paintChildWithClipRect
(
RenderObject
child
,
Point
childPosition
,
Rect
clipRect
)
{
// clipRect is in the parent's coordinate space
assert
(
debugCanPaintChild
(
child
));
assert
(
debugCanPaintChild
(
child
));
final
Offset
childOffset
=
childPosition
.
toOffset
();
final
Offset
childOffset
=
childPosition
.
toOffset
();
if
(!
child
.
needsCompositing
)
{
if
(!
child
.
needsCompositing
)
{
...
@@ -132,8 +167,13 @@ class PaintingContext {
...
@@ -132,8 +167,13 @@ class PaintingContext {
}
}
}
}
/// Paint a child with a rounded-rectangular clip
///
/// If the child needs compositing, the clip will be applied by a
/// compositing layer. Otherwise, the clip will be applied by the canvas.
///
/// Note: clipRRect is in the parent's coordinate space
void
paintChildWithClipRRect
(
RenderObject
child
,
Point
childPosition
,
Rect
bounds
,
sky
.
RRect
clipRRect
)
{
void
paintChildWithClipRRect
(
RenderObject
child
,
Point
childPosition
,
Rect
bounds
,
sky
.
RRect
clipRRect
)
{
// clipRRect is in the parent's coordinate space
assert
(
debugCanPaintChild
(
child
));
assert
(
debugCanPaintChild
(
child
));
final
Offset
childOffset
=
childPosition
.
toOffset
();
final
Offset
childOffset
=
childPosition
.
toOffset
();
if
(!
child
.
needsCompositing
)
{
if
(!
child
.
needsCompositing
)
{
...
@@ -148,8 +188,13 @@ class PaintingContext {
...
@@ -148,8 +188,13 @@ class PaintingContext {
}
}
}
}
/// Paint a child with a clip path
///
/// If the child needs compositing, the clip will be applied by a
/// compositing layer. Otherwise, the clip will be applied by the canvas.
///
/// Note: bounds and clipPath are in the parent's coordinate space
void
paintChildWithClipPath
(
RenderObject
child
,
Point
childPosition
,
Rect
bounds
,
Path
clipPath
)
{
void
paintChildWithClipPath
(
RenderObject
child
,
Point
childPosition
,
Rect
bounds
,
Path
clipPath
)
{
// bounds and clipPath are in the parent's coordinate space
assert
(
debugCanPaintChild
(
child
));
assert
(
debugCanPaintChild
(
child
));
final
Offset
childOffset
=
childPosition
.
toOffset
();
final
Offset
childOffset
=
childPosition
.
toOffset
();
if
(!
child
.
needsCompositing
)
{
if
(!
child
.
needsCompositing
)
{
...
@@ -165,6 +210,10 @@ class PaintingContext {
...
@@ -165,6 +210,10 @@ class PaintingContext {
}
}
}
}
/// Paint a child with a transform
///
/// If the child needs compositing, the transform will be applied by a
/// compositing layer. Otherwise, the transform will be applied by the canvas.
void
paintChildWithTransform
(
RenderObject
child
,
Point
childPosition
,
Matrix4
transform
)
{
void
paintChildWithTransform
(
RenderObject
child
,
Point
childPosition
,
Matrix4
transform
)
{
assert
(
debugCanPaintChild
(
child
));
assert
(
debugCanPaintChild
(
child
));
final
Offset
childOffset
=
childPosition
.
toOffset
();
final
Offset
childOffset
=
childPosition
.
toOffset
();
...
@@ -188,6 +237,11 @@ class PaintingContext {
...
@@ -188,6 +237,11 @@ class PaintingContext {
..
isAntiAlias
=
false
;
..
isAntiAlias
=
false
;
}
}
/// Paint a child with an opacity
///
/// If the child needs compositing, the blending operation will be applied by
/// a compositing layer. Otherwise, the blending operation will be applied by
/// the canvas.
void
paintChildWithOpacity
(
RenderObject
child
,
void
paintChildWithOpacity
(
RenderObject
child
,
Point
childPosition
,
Point
childPosition
,
Rect
bounds
,
Rect
bounds
,
...
@@ -215,6 +269,14 @@ class PaintingContext {
...
@@ -215,6 +269,14 @@ class PaintingContext {
..
isAntiAlias
=
false
;
..
isAntiAlias
=
false
;
}
}
/// Paint a child with a color filter
///
/// The color filter is constructed by combining the given color and the given
/// transfer mode, as if they were passed to the [ColorFilter.mode] constructor.
///
/// If the child needs compositing, the blending operation will be applied by
/// a compositing layer. Otherwise, the blending operation will be applied by
/// the canvas.
void
paintChildWithColorFilter
(
RenderObject
child
,
void
paintChildWithColorFilter
(
RenderObject
child
,
Point
childPosition
,
Point
childPosition
,
Rect
bounds
,
Rect
bounds
,
...
@@ -238,12 +300,18 @@ class PaintingContext {
...
@@ -238,12 +300,18 @@ class PaintingContext {
}
}
}
}
// do not call directly
/// Instructs the child to draw itself onto this context at the given offset
///
/// Do not call directly. This function is visible so that it can be
/// overridden in tests.
void
insertChild
(
RenderObject
child
,
Offset
offset
)
{
void
insertChild
(
RenderObject
child
,
Offset
offset
)
{
child
.
_paintWithContext
(
this
,
offset
);
child
.
_paintWithContext
(
this
,
offset
);
}
}
// do not call directly
/// Instructs the child to paint itself into a new composited layer using this context
///
/// Do not call directly. This function is visible so that it can be
/// overridden in tests.
void
compositeChild
(
RenderObject
child
,
{
Offset
childOffset:
Offset
.
zero
,
ContainerLayer
parentLayer
})
{
void
compositeChild
(
RenderObject
child
,
{
Offset
childOffset:
Offset
.
zero
,
ContainerLayer
parentLayer
})
{
// This ends the current layer and starts a new layer for the
// This ends the current layer and starts a new layer for the
// remainder of our rendering. It also creates a new layer for the
// remainder of our rendering. It also creates a new layer for the
...
@@ -285,8 +353,14 @@ class PaintingContext {
...
@@ -285,8 +353,14 @@ class PaintingContext {
}
}
/// An abstract set of layout constraints
///
/// Concrete layout models (such as box) will create concrete subclasses to
/// communicate layout constraints between parents and children.
abstract
class
Constraints
{
abstract
class
Constraints
{
const
Constraints
();
const
Constraints
();
/// Whether there is exactly one size possible given these constraints
bool
get
isTight
;
bool
get
isTight
;
}
}
...
@@ -294,31 +368,61 @@ typedef void RenderObjectVisitor(RenderObject child);
...
@@ -294,31 +368,61 @@ typedef void RenderObjectVisitor(RenderObject child);
typedef
void
LayoutCallback
(
Constraints
constraints
);
typedef
void
LayoutCallback
(
Constraints
constraints
);
typedef
double
DimensionCallback
(
Constraints
constraints
);
typedef
double
DimensionCallback
(
Constraints
constraints
);
/// An object in the render tree
///
/// Render objects have a reference to their parent but do not commit to a model
/// for their children.
abstract
class
RenderObject
extends
AbstractNode
implements
HitTestTarget
{
abstract
class
RenderObject
extends
AbstractNode
implements
HitTestTarget
{
// LAYOUT
// LAYOUT
// parentData is only for use by the RenderObject that actually lays this
/// Data for use by the parent render object
// node out, and any other nodes who happen to know exactly what
///
// kind of node that is.
/// The parent data is used by the render object that lays out this object
/// (typically this object's parent in the render tree) to store information
/// relevant to itself and to any other nodes who happen to know exactly what
/// the data means. The parent data is opaque to the child.
///
/// - The parent data object must inherit from [ParentData] (despite being
/// typed as `dynamic`).
/// - The parent data field must not be directly set, except by calling
/// [setupParentData] on the parent node.
/// - The parent data can be set before the child is added to the parent, by
/// calling [setupParentData] on the future parent node.
/// - The conventions for using the parent data depend on the layout protocol
/// used between the parent and child. For example, in box layout, the
/// parent data is completely opaque but in sector layout the child is
/// permitted to read some fields of the parent data.
dynamic
parentData
;
// TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer
dynamic
parentData
;
// TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer
/// Override to setup parent data correctly for your children
///
/// You can call this function to set up the parent data for child before the
/// child is added to the parent's child list.
void
setupParentData
(
RenderObject
child
)
{
void
setupParentData
(
RenderObject
child
)
{
// override this to setup .parentData correctly for your class
assert
(
debugCanPerformMutations
);
assert
(
debugCanPerformMutations
);
if
(
child
.
parentData
is
!
ParentData
)
if
(
child
.
parentData
is
!
ParentData
)
child
.
parentData
=
new
ParentData
();
child
.
parentData
=
new
ParentData
();
}
}
void
adoptChild
(
RenderObject
child
)
{
// only for use by subclasses
/// Called by subclases when they decide a render object is a child
// call this whenever you decide a node is a child
///
/// Only for use by subclasses when changing their child lists. Calling this
/// in other cases will lead to an inconsistent tree and probably cause crashes.
void
adoptChild
(
RenderObject
child
)
{
assert
(
debugCanPerformMutations
);
assert
(
debugCanPerformMutations
);
assert
(
child
!=
null
);
assert
(
child
!=
null
);
setupParentData
(
child
);
setupParentData
(
child
);
super
.
adoptChild
(
child
);
super
.
adoptChild
(
child
);
markNeedsLayout
();
markNeedsLayout
();
markNeedsCompositingBitsUpdate
();
_
markNeedsCompositingBitsUpdate
();
}
}
void
dropChild
(
RenderObject
child
)
{
// only for use by subclasses
/// Called by subclases when they decide a render object is no longer a child
///
/// Only for use by subclasses when changing their child lists. Calling this
/// in other cases will lead to an inconsistent tree and probably cause crashes.
void
dropChild
(
RenderObject
child
)
{
assert
(
debugCanPerformMutations
);
assert
(
debugCanPerformMutations
);
assert
(
child
!=
null
);
assert
(
child
!=
null
);
assert
(
child
.
parentData
!=
null
);
assert
(
child
.
parentData
!=
null
);
...
@@ -326,10 +430,12 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -326,10 +430,12 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
child
.
parentData
.
detach
();
child
.
parentData
.
detach
();
super
.
dropChild
(
child
);
super
.
dropChild
(
child
);
markNeedsLayout
();
markNeedsLayout
();
markNeedsCompositingBitsUpdate
();
_
markNeedsCompositingBitsUpdate
();
}
}
// Override in subclasses with children and call the visitor for each child.
/// Calls visitor for each immediate child of this render object
///
/// Override in subclasses with children and call the visitor for each child
void
visitChildren
(
RenderObjectVisitor
visitor
)
{
}
void
visitChildren
(
RenderObjectVisitor
visitor
)
{
}
dynamic
debugExceptionContext
=
''
;
dynamic
debugExceptionContext
=
''
;
...
@@ -376,12 +482,15 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -376,12 +482,15 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
static
List
<
RenderObject
>
_nodesNeedingLayout
=
new
List
<
RenderObject
>();
static
List
<
RenderObject
>
_nodesNeedingLayout
=
new
List
<
RenderObject
>();
bool
_needsLayout
=
true
;
bool
_needsLayout
=
true
;
/// Whether this render object's layout information is dirty
bool
get
needsLayout
=>
_needsLayout
;
bool
get
needsLayout
=>
_needsLayout
;
RenderObject
_relayoutSubtreeRoot
;
RenderObject
_relayoutSubtreeRoot
;
bool
_doingThisLayoutWithCallback
=
false
;
bool
_doingThisLayoutWithCallback
=
false
;
Constraints
_constraints
;
Constraints
_constraints
;
/// The layout constraints most recently supplied by the parent
Constraints
get
constraints
=>
_constraints
;
Constraints
get
constraints
=>
_constraints
;
bool
debugDoesMeetConstraints
();
// override this in a subclass to verify that your state matches the constraints object
/// Override this function in a subclass to verify that your state matches the constraints object
bool
debugDoesMeetConstraints
();
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
...
@@ -396,6 +505,21 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -396,6 +505,21 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
assert
(
node
.
_relayoutSubtreeRoot
==
node
);
assert
(
node
.
_relayoutSubtreeRoot
==
node
);
return
true
;
return
true
;
}
}
/// Mark this render object's layout information as dirty
///
/// Rather than eagerly updating layout information in response to writes into
/// this render object, we instead mark the layout information as dirty, which
/// schedules a visual update. As part of the visual update, the rendering
/// pipeline will update this render object's layout information.
///
/// This mechanism batches the layout work so that multiple sequential writes
/// are coalesced, removing redundant computation.
///
/// Causes [needsLayout] to return true for this render object. If the parent
/// render object indicated that it uses the size of this render object in
/// computing its layout information, this function will also mark the parent
/// as needing layout.
void
markNeedsLayout
()
{
void
markNeedsLayout
()
{
assert
(
debugCanPerformMutations
);
assert
(
debugCanPerformMutations
);
if
(
_needsLayout
)
{
if
(
_needsLayout
)
{
...
@@ -418,6 +542,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -418,6 +542,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
scheduler
.
ensureVisualUpdate
();
scheduler
.
ensureVisualUpdate
();
}
}
}
}
void
_cleanRelayoutSubtreeRoot
()
{
void
_cleanRelayoutSubtreeRoot
()
{
if
(
_relayoutSubtreeRoot
!=
this
)
{
if
(
_relayoutSubtreeRoot
!=
this
)
{
_relayoutSubtreeRoot
=
null
;
_relayoutSubtreeRoot
=
null
;
...
@@ -427,6 +552,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -427,6 +552,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
});
});
}
}
}
}
/// Bootstrap the rendering pipeline by scheduling the very first layout
///
/// Requires this render object to be attached and that this render object
/// is the root of the render tree.
///
/// See [RenderView] for an example of how this function is used.
void
scheduleInitialLayout
()
{
void
scheduleInitialLayout
()
{
assert
(
attached
);
assert
(
attached
);
assert
(
parent
is
!
RenderObject
);
assert
(
parent
is
!
RenderObject
);
...
@@ -439,6 +571,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -439,6 +571,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
});
});
_nodesNeedingLayout
.
add
(
this
);
_nodesNeedingLayout
.
add
(
this
);
}
}
/// Update the layout information for all dirty render objects
///
/// This function is one of the core stages of the rendering pipeline. Layout
/// information is cleaned prior to painting so that render objects will
/// appear on screen in their up-to-date locations.
///
/// See [SkyBinding] for an example of how this function is used.
static
void
flushLayout
()
{
static
void
flushLayout
()
{
sky
.
tracing
.
begin
(
'RenderObject.flushLayout'
);
sky
.
tracing
.
begin
(
'RenderObject.flushLayout'
);
_debugDoingLayout
=
true
;
_debugDoingLayout
=
true
;
...
@@ -449,7 +589,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -449,7 +589,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
_nodesNeedingLayout
=
new
List
<
RenderObject
>();
_nodesNeedingLayout
=
new
List
<
RenderObject
>();
dirtyNodes
..
sort
((
a
,
b
)
=>
a
.
depth
-
b
.
depth
)..
forEach
((
node
)
{
dirtyNodes
..
sort
((
a
,
b
)
=>
a
.
depth
-
b
.
depth
)..
forEach
((
node
)
{
if
(
node
.
_needsLayout
&&
node
.
attached
)
if
(
node
.
_needsLayout
&&
node
.
attached
)
node
.
layoutWithoutResize
();
node
.
_
layoutWithoutResize
();
});
});
}
}
}
finally
{
}
finally
{
...
@@ -457,7 +597,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -457,7 +597,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
sky
.
tracing
.
end
(
'RenderObject.flushLayout'
);
sky
.
tracing
.
end
(
'RenderObject.flushLayout'
);
}
}
}
}
void
layoutWithoutResize
()
{
void
_
layoutWithoutResize
()
{
try
{
try
{
assert
(
_relayoutSubtreeRoot
==
this
);
assert
(
_relayoutSubtreeRoot
==
this
);
RenderObject
debugPreviousActiveLayout
;
RenderObject
debugPreviousActiveLayout
;
...
@@ -485,6 +625,29 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -485,6 +625,29 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
_needsLayout
=
false
;
_needsLayout
=
false
;
markNeedsPaint
();
markNeedsPaint
();
}
}
/// Compute the layout for this render object
///
/// This function is the main entry point for parents to ask their children to
/// update their layout information. The parent passes a constraints object,
/// which informs the child as which layouts are permissible. The child is
/// required to obey the given constraints.
///
/// If the parent reads information computed during the child's layout, the
/// parent must pass true for parentUsesSize. In that case, the parent will be
/// marked as needing layout whenever the child is marked as needing layout
/// because the parent's layout information depends on the child's layout
/// information. If the parent uses the default value (false) for
/// parentUsesSize, the child can change its layout information (subject to
/// the given constraints) without informing the parent.
///
/// Subclasses should not override layout directly. Instead, they should
/// override performResize and/or performLayout.
///
/// The parent's performLayout method should call the layout of all its
/// children unconditionally. It is the layout functions's responsibility (as
/// implemented here) to return early if the child does not need to do any
/// work to update its layout information.
void
layout
(
Constraints
constraints
,
{
bool
parentUsesSize:
false
})
{
void
layout
(
Constraints
constraints
,
{
bool
parentUsesSize:
false
})
{
final
parent
=
this
.
parent
;
// TODO(ianh): Remove this once the analyzer is cleverer
final
parent
=
this
.
parent
;
// TODO(ianh): Remove this once the analyzer is cleverer
RenderObject
relayoutSubtreeRoot
;
RenderObject
relayoutSubtreeRoot
;
...
@@ -533,20 +696,51 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -533,20 +696,51 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
markNeedsPaint
();
markNeedsPaint
();
assert
(
parent
==
this
.
parent
);
// TODO(ianh): Remove this once the analyzer is cleverer
assert
(
parent
==
this
.
parent
);
// TODO(ianh): Remove this once the analyzer is cleverer
}
}
bool
get
sizedByParent
=>
false
;
// return true if the constraints are the only input to the sizing algorithm (in particular, child nodes have no impact)
void
performResize
();
// set the local dimensions, using only the constraints (only called if sizedByParent is true)
/// Whether the constraints are the only input to the sizing algorithm (in
/// particular, child nodes have no impact)
///
/// Returning false is always correct, but returning true can be more
/// efficient when computing the size of this render object because we don't
/// need to recompute the size if the constraints don't change.
bool
get
sizedByParent
=>
false
;
/// Updates the render objects size using only the constraints
///
/// Do not call this function directly: call [layout] instead. This function
/// is called by [layout] when there is actually work to be done by this
/// render object during layout. The layout constraints provided by your
/// parent are available via the [constraints] getter.
///
/// Subclasses that set [sizedByParent] to true should override this function
/// to compute their size.
///
/// Note: This function is called only if [sizedByParent] is true.
void
performResize
();
/// Do the work of computing the layout for this render object
///
/// Do not call this function directly: call [layout] instead. This function
/// is called by [layout] when there is actually work to be done by this
/// render object during layout. The layout constraints provided by your
/// parent are available via the [constraints] getter.
///
/// If [sizedByParent] is true, then this function should not actually change
/// the dimensions of this render object. Instead, that work should be done by
/// [performResize]. If [sizedByParent] is false, then this function should
/// both change the dimensions of this render object and instruct its children
/// to layout.
///
/// In implementing this function, you must call [layout] on each of your
/// children, passing true for parentUsesSize if your layout information is
/// dependent on your child's layout information. Passing true for
/// parentUsesSize ensures that this render object will undergo layout if the
/// child undergoes layout. Otherwise, the child can changes its layout
/// information without informing this render object.
void
performLayout
();
void
performLayout
();
// Override this to perform relayout without your parent's
// involvement.
/// Allows this render object to mutation its child list during layout and
//
/// invokes callback
// This is called during layout. If sizedByParent is true, then
// performLayout() should not change your dimensions, only do that
// in performResize(). If sizedByParent is false, then set both
// your dimensions and do your children's layout here.
//
// When calling layout() on your children, pass in
// "parentUsesSize: true" if your size or layout is dependent on
// your child's size or intrinsic dimensions.
void
invokeLayoutCallback
(
LayoutCallback
callback
)
{
void
invokeLayoutCallback
(
LayoutCallback
callback
)
{
assert
(
_debugMutationsLocked
);
assert
(
_debugMutationsLocked
);
assert
(
_debugDoingThisLayout
);
assert
(
_debugDoingThisLayout
);
...
@@ -559,6 +753,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -559,6 +753,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
}
}
}
}
/// Rotate this render object (not yet implemented)
void
rotate
({
int
oldAngle
,
// 0..3
int
newAngle
,
// 0..3
Duration
time
})
{
}
// when the parent has rotated (e.g. when the screen has been turned
// when the parent has rotated (e.g. when the screen has been turned
// 90 degrees), immediately prior to layout() being called for the
// 90 degrees), immediately prior to layout() being called for the
// new dimensions, rotate() is called with the old and new angles.
// new dimensions, rotate() is called with the old and new angles.
...
@@ -569,12 +770,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -569,12 +770,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
// pixel, on the output device. Then, the layout() method or
// pixel, on the output device. Then, the layout() method or
// equivalent will be invoked.
// equivalent will be invoked.
void
rotate
({
int
oldAngle
,
// 0..3
int
newAngle
,
// 0..3
Duration
time
})
{
}
// PAINTING
// PAINTING
...
@@ -590,36 +785,54 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -590,36 +785,54 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
static
List
<
RenderObject
>
_nodesNeedingPaint
=
new
List
<
RenderObject
>();
static
List
<
RenderObject
>
_nodesNeedingPaint
=
new
List
<
RenderObject
>();
// Override this in subclasses to indicate that instances of your
/// Whether this render object paints using a composited layer
// class need to have their own Layer. For example, videos.
///
/// Override this in subclasses to indicate that instances of your class need
/// to have their own compositing layer. For example, videos should return
/// true if they use hardware decoders.
///
/// Note: This getter must not change value over the lifetime of this object.
bool
get
hasLayer
=>
false
;
bool
get
hasLayer
=>
false
;
ContainerLayer
_layer
;
ContainerLayer
_layer
;
/// The compositing layer that this render object uses to paint
///
/// Call only when [hasLayer] is true.
ContainerLayer
get
layer
{
ContainerLayer
get
layer
{
assert
(
hasLayer
);
assert
(
hasLayer
);
assert
(!
_needsPaint
);
assert
(!
_needsPaint
);
return
_layer
;
return
_layer
;
}
}
// When the subtree is mutated, we need to recompute our
// "needsCompositing" bit, and our ancestors need to do the
// same (in case ours changed). adoptChild() and dropChild() thus
// call markNeedsCompositingBitsUpdate().
bool
_needsCompositingBitsUpdate
=
true
;
bool
_needsCompositingBitsUpdate
=
true
;
void
markNeedsCompositingBitsUpdate
()
{
/// Mark the compositing state for this render object as dirty
///
/// When the subtree is mutated, we need to recompute our [needsCompositing]
/// bit, and our ancestors need to do the same (in case ours changed).
/// Therefore, [adoptChild] and [dropChild] call
/// [markNeedsCompositingBitsUpdate].
void
_markNeedsCompositingBitsUpdate
()
{
if
(
_needsCompositingBitsUpdate
)
if
(
_needsCompositingBitsUpdate
)
return
;
return
;
_needsCompositingBitsUpdate
=
true
;
_needsCompositingBitsUpdate
=
true
;
final
AbstractNode
parent
=
this
.
parent
;
// TODO(ianh): remove the once the analyzer is cleverer
final
AbstractNode
parent
=
this
.
parent
;
// TODO(ianh): remove the once the analyzer is cleverer
if
(
parent
is
RenderObject
)
if
(
parent
is
RenderObject
)
parent
.
markNeedsCompositingBitsUpdate
();
parent
.
_
markNeedsCompositingBitsUpdate
();
}
}
bool
_needsCompositing
=
false
;
bool
_needsCompositing
=
false
;
/// Whether we or one of our descendants has a compositing layer
///
/// Only legal to call after [flushLayout] and [updateCompositingBits] have
/// been called.
bool
get
needsCompositing
{
bool
get
needsCompositing
{
// needsCompositing is true if either we have a layer or one of our descendants has a layer
assert
(!
_needsCompositingBitsUpdate
);
// make sure we don't use this bit when it is dirty
assert
(!
_needsCompositingBitsUpdate
);
// make sure we don't use this bit when it is dirty
return
_needsCompositing
;
return
_needsCompositing
;
}
}
/// Updates the [needsCompositing] bits
///
/// Called as part of the rendering pipeline after [flushLayout] and before
/// [flushPaint].
void
updateCompositingBits
()
{
void
updateCompositingBits
()
{
if
(!
_needsCompositingBitsUpdate
)
if
(!
_needsCompositingBitsUpdate
)
return
;
return
;
...
@@ -637,7 +850,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -637,7 +850,19 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
}
}
bool
_needsPaint
=
true
;
bool
_needsPaint
=
true
;
/// The visual appearance of this render object has changed since it last painted
bool
get
needsPaint
=>
_needsPaint
;
bool
get
needsPaint
=>
_needsPaint
;
/// Mark this render object as having changed its visual appearance
///
/// Rather than eagerly updating this render object's display list
/// in response to writes, we instead mark the the render object as needing to
/// paint, which schedules a visual update. As part of the visual update, the
/// rendering pipeline will give this render object an opportunity to update
/// its display list.
///
/// This mechanism batches the painting work so that multiple sequential
/// writes are coalesced, removing redundant computation.
void
markNeedsPaint
()
{
void
markNeedsPaint
()
{
assert
(!
debugDoingPaint
);
assert
(!
debugDoingPaint
);
if
(!
attached
)
return
;
// Don't try painting things that aren't in the hierarchy
if
(!
attached
)
return
;
// Don't try painting things that aren't in the hierarchy
...
@@ -664,6 +889,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -664,6 +889,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
scheduler
.
ensureVisualUpdate
();
scheduler
.
ensureVisualUpdate
();
}
}
}
}
/// Update the display lists for all render objects
///
/// This function is one of the core stages of the rendering pipeline.
/// Painting occurs after layout and before the scene is recomposited so that
/// scene is composited with up-to-date display lists for every render object.
///
/// See [SkyBinding] for an example of how this function is used.
static
void
flushPaint
()
{
static
void
flushPaint
()
{
sky
.
tracing
.
begin
(
'RenderObject.flushPaint'
);
sky
.
tracing
.
begin
(
'RenderObject.flushPaint'
);
_debugDoingPaint
=
true
;
_debugDoingPaint
=
true
;
...
@@ -682,6 +915,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -682,6 +915,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
sky
.
tracing
.
end
(
'RenderObject.flushPaint'
);
sky
.
tracing
.
end
(
'RenderObject.flushPaint'
);
}
}
}
}
/// Bootstrap the rendering pipeline by scheduling the very first paint
///
/// Requires that this render object is attached, is the root of the render
/// tree, and has a composited layer.
///
/// See [RenderView] for an example of how this function is used.
void
scheduleInitialPaint
(
ContainerLayer
rootLayer
)
{
void
scheduleInitialPaint
(
ContainerLayer
rootLayer
)
{
assert
(
attached
);
assert
(
attached
);
assert
(
parent
is
!
RenderObject
);
assert
(
parent
is
!
RenderObject
);
...
@@ -736,18 +976,50 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -736,18 +976,50 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
});
});
}
}
/// The bounds within which this render object will paint
///
/// A render object is permitted to paint outside the region it occupies
/// during layout but is not permitted to paint outside these paints bounds.
/// These paint bounds are used to construct memory-efficient composited
/// layers, which means attempting to paint outside these bounds can attempt
/// to write to pixels that do not exist in this render object's composited
/// layer.
Rect
get
paintBounds
;
Rect
get
paintBounds
;
/// Override this function to paint debugging information
void
debugPaint
(
PaintingContext
context
,
Offset
offset
)
{
}
void
debugPaint
(
PaintingContext
context
,
Offset
offset
)
{
}
/// Paint this render object into the given context at the given offset
///
/// Subclasses should override this function to provide a visual appearance
/// for themselves. The render object's local coordinate system is
/// axis-aligned with the coordinate system of the context's canvas and the
/// render object's local origin (i.e, x=0 and y=0) is placed at the given
/// offset in the context's canvas.
///
/// Do not call this function directly. If you wish to paint yourself, call
/// [markNeedsPaint] instead to schedule a call to this function. If you wish
/// to paint one of your children, call one of the paint child functions on
/// the given context, such as [paintChild] or [paintChildWithClipRect].
///
/// When painting one of your children (via a paint child function on the
/// given context), the current canvas held by the context might change
/// because draw operations before and after painting children might need to
/// be recorded on separate compositing layers.
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
}
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
}
/// If this render object applies a transform before painting, apply that
/// transform to the given matrix
///
/// Used by coordinate conversion functions to translate coordiantes local to
/// one render object into coordinates local to another render object.
void
applyPaintTransform
(
Matrix4
transform
)
{
}
void
applyPaintTransform
(
Matrix4
transform
)
{
}
// EVENTS
// EVENTS
/// Override this function to handle events that hit this render object
EventDisposition
handleEvent
(
sky
.
Event
event
,
HitTestEntry
entry
)
{
EventDisposition
handleEvent
(
sky
.
Event
event
,
HitTestEntry
entry
)
{
// override this if you have a client, to hand it to the client
// override this if you want to do anything with the event
return
EventDisposition
.
ignored
;
return
EventDisposition
.
ignored
;
}
}
...
@@ -781,6 +1053,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -781,6 +1053,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
_debugActiveLayout
=
debugPreviousActiveLayout
;
_debugActiveLayout
=
debugPreviousActiveLayout
;
return
result
;
return
result
;
}
}
/// Returns a human understandable name
String
toStringName
()
{
String
toStringName
()
{
String
header
=
'
${runtimeType}
'
;
String
header
=
'
${runtimeType}
'
;
if
(
_relayoutSubtreeRoot
!=
null
&&
_relayoutSubtreeRoot
!=
this
)
{
if
(
_relayoutSubtreeRoot
!=
null
&&
_relayoutSubtreeRoot
!=
this
)
{
...
@@ -798,11 +1072,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
...
@@ -798,11 +1072,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
header
+=
' DETACHED'
;
header
+=
' DETACHED'
;
return
header
;
return
header
;
}
}
String
debugDescribeSettings
(
String
prefix
)
=>
'
${prefix}
parentData:
${parentData}
\n
${prefix}
constraints:
${constraints}
\n
'
;
String
debugDescribeSettings
(
String
prefix
)
=>
'
${prefix}
parentData:
${parentData}
\n
${prefix}
constraints:
${constraints}
\n
'
;
String
debugDescribeChildren
(
String
prefix
)
=>
''
;
String
debugDescribeChildren
(
String
prefix
)
=>
''
;
}
}
/// Obsolete function that will be removed eventually
double
clamp
(
{
double
min:
0.0
,
double
value:
0.0
,
double
max:
double
.
INFINITY
})
{
double
clamp
(
{
double
min:
0.0
,
double
value:
0.0
,
double
max:
double
.
INFINITY
})
{
assert
(
min
!=
null
);
assert
(
min
!=
null
);
assert
(
value
!=
null
);
assert
(
value
!=
null
);
...
@@ -811,10 +1087,12 @@ double clamp({ double min: 0.0, double value: 0.0, double max: double.INFINITY }
...
@@ -811,10 +1087,12 @@ double clamp({ double min: 0.0, double value: 0.0, double max: double.INFINITY }
}
}
// GENERIC MIXIN FOR RENDER NODES WITH ONE CHILD
/// Generic mixin for render objects with one child
///
/// Provides a child model for a render object subclass that has a unique child
abstract
class
RenderObjectWithChildMixin
<
ChildType
extends
RenderObject
>
implements
RenderObject
{
abstract
class
RenderObjectWithChildMixin
<
ChildType
extends
RenderObject
>
implements
RenderObject
{
ChildType
_child
;
ChildType
_child
;
/// The render object's unique child
ChildType
get
child
=>
_child
;
ChildType
get
child
=>
_child
;
void
set
child
(
ChildType
value
)
{
void
set
child
(
ChildType
value
)
{
if
(
_child
!=
null
)
if
(
_child
!=
null
)
...
@@ -842,12 +1120,14 @@ abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem
...
@@ -842,12 +1120,14 @@ abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem
}
}
}
}
/// Parent data to support a doubly-linked list of children
// GENERIC MIXIN FOR RENDER NODES WITH A LIST OF CHILDREN
abstract
class
ContainerParentDataMixin
<
ChildType
extends
RenderObject
>
{
abstract
class
ContainerParentDataMixin
<
ChildType
extends
RenderObject
>
{
/// The previous sibling in the parent's child list
ChildType
previousSibling
;
ChildType
previousSibling
;
/// The next sibling in the parent's child list
ChildType
nextSibling
;
ChildType
nextSibling
;
/// Clear the sibling pointers.
void
detachSiblings
()
{
void
detachSiblings
()
{
if
(
previousSibling
!=
null
)
{
if
(
previousSibling
!=
null
)
{
assert
(
previousSibling
.
parentData
is
ContainerParentDataMixin
<
ChildType
>);
assert
(
previousSibling
.
parentData
is
ContainerParentDataMixin
<
ChildType
>);
...
@@ -866,6 +1146,10 @@ abstract class ContainerParentDataMixin<ChildType extends RenderObject> {
...
@@ -866,6 +1146,10 @@ abstract class ContainerParentDataMixin<ChildType extends RenderObject> {
}
}
}
}
/// Generic mixin for render objects with a list of children
///
/// Provides a child model for a render object subclass that has a doubly-linked
/// list of children.
abstract
class
ContainerRenderObjectMixin
<
ChildType
extends
RenderObject
,
ParentDataType
extends
ContainerParentDataMixin
<
ChildType
>>
implements
RenderObject
{
abstract
class
ContainerRenderObjectMixin
<
ChildType
extends
RenderObject
,
ParentDataType
extends
ContainerParentDataMixin
<
ChildType
>>
implements
RenderObject
{
bool
_debugUltimatePreviousSiblingOf
(
ChildType
child
,
{
ChildType
equals
})
{
bool
_debugUltimatePreviousSiblingOf
(
ChildType
child
,
{
ChildType
equals
})
{
...
@@ -888,6 +1172,7 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -888,6 +1172,7 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
}
}
int
_childCount
=
0
;
int
_childCount
=
0
;
/// The number of children
int
get
childCount
=>
_childCount
;
int
get
childCount
=>
_childCount
;
ChildType
_firstChild
;
ChildType
_firstChild
;
...
@@ -934,6 +1219,9 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -934,6 +1219,9 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
}
}
}
}
}
}
/// Insert child into this render object's child list before the given child
///
/// To insert a child at the end of the child list, omit the before parameter.
void
add
(
ChildType
child
,
{
ChildType
before
})
{
void
add
(
ChildType
child
,
{
ChildType
before
})
{
assert
(
child
!=
this
);
assert
(
child
!=
this
);
assert
(
before
!=
this
);
assert
(
before
!=
this
);
...
@@ -943,11 +1231,14 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -943,11 +1231,14 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
adoptChild
(
child
);
adoptChild
(
child
);
_addToChildList
(
child
,
before:
before
);
_addToChildList
(
child
,
before:
before
);
}
}
/// Add all the children to the end of this render object's child list
void
addAll
(
List
<
ChildType
>
children
)
{
void
addAll
(
List
<
ChildType
>
children
)
{
if
(
children
!=
null
)
if
(
children
!=
null
)
for
(
ChildType
child
in
children
)
for
(
ChildType
child
in
children
)
add
(
child
);
add
(
child
);
}
}
void
_removeFromChildList
(
ChildType
child
)
{
void
_removeFromChildList
(
ChildType
child
)
{
assert
(
child
.
parentData
is
ParentDataType
);
assert
(
child
.
parentData
is
ParentDataType
);
assert
(
_debugUltimatePreviousSiblingOf
(
child
,
equals:
_firstChild
));
assert
(
_debugUltimatePreviousSiblingOf
(
child
,
equals:
_firstChild
));
...
@@ -971,10 +1262,18 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -971,10 +1262,18 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
child
.
parentData
.
nextSibling
=
null
;
child
.
parentData
.
nextSibling
=
null
;
_childCount
-=
1
;
_childCount
-=
1
;
}
}
/// Remove this child from the child list
///
/// Requires the child to be present in the child list.
void
remove
(
ChildType
child
)
{
void
remove
(
ChildType
child
)
{
_removeFromChildList
(
child
);
_removeFromChildList
(
child
);
dropChild
(
child
);
dropChild
(
child
);
}
}
/// Remove all their children from this render object's child list
///
/// More efficient than removing them individually.
void
removeAll
()
{
void
removeAll
()
{
ChildType
child
=
_firstChild
;
ChildType
child
=
_firstChild
;
while
(
child
!=
null
)
{
while
(
child
!=
null
)
{
...
@@ -989,6 +1288,12 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -989,6 +1288,12 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
_lastChild
=
null
;
_lastChild
=
null
;
_childCount
=
0
;
_childCount
=
0
;
}
}
/// Move this child in the child list to be before the given child
///
/// More efficient than removing and re-adding the child. Requires the child
/// to already be in the child list at some position. Pass null for before to
/// move the child to the end of the child list.
void
move
(
ChildType
child
,
{
ChildType
before
})
{
void
move
(
ChildType
child
,
{
ChildType
before
})
{
assert
(
child
!=
this
);
assert
(
child
!=
this
);
assert
(
before
!=
this
);
assert
(
before
!=
this
);
...
@@ -1033,8 +1338,13 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
...
@@ -1033,8 +1338,13 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
}
}
}
}
/// The first child in the child list
ChildType
get
firstChild
=>
_firstChild
;
ChildType
get
firstChild
=>
_firstChild
;
/// The last child in the child list
ChildType
get
lastChild
=>
_lastChild
;
ChildType
get
lastChild
=>
_lastChild
;
/// The next child after the given child in the child list
ChildType
childAfter
(
ChildType
child
)
{
ChildType
childAfter
(
ChildType
child
)
{
assert
(
child
.
parentData
is
ParentDataType
);
assert
(
child
.
parentData
is
ParentDataType
);
return
child
.
parentData
.
nextSibling
;
return
child
.
parentData
.
nextSibling
;
...
...
packages/flutter/lib/widgets.dart
View file @
c1bd6af9
...
@@ -2,7 +2,10 @@
...
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
/// Includes and re-exports all Sky widgets classes.
// Includes and re-exports all Sky widgets classes.
/// The Sky widget framework
library
widgets
;
export
'package:sky/widgets/animated_component.dart'
;
export
'package:sky/widgets/animated_component.dart'
;
export
'package:sky/widgets/animated_container.dart'
;
export
'package:sky/widgets/animated_container.dart'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment