Skip to content

Commit

Permalink
Self review
Browse files Browse the repository at this point in the history
  • Loading branch information
Piinks committed Apr 24, 2024
1 parent ad20105 commit f3390ca
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
}

Map<Type, GestureRecognizerFactory> _getTapRecognizer(
TreeViewNode<String> node) {
TreeViewNode<String> node,
) {
return <Type, GestureRecognizerFactory>{
TapGestureRecognizer:
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class TreeExampleState extends State<TreeExample> {
];

Map<Type, GestureRecognizerFactory> _getTapRecognizer(
TreeViewNode<String> node) {
TreeViewNode<String> node,
) {
return <Type, GestureRecognizerFactory>{
TapGestureRecognizer:
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
Expand All @@ -83,9 +84,7 @@ class TreeExampleState extends State<TreeExample> {

Widget _getTree() {
return DecoratedBox(
decoration: BoxDecoration(
border: Border.all(),
),
decoration: BoxDecoration(border: Border.all()),
child: Scrollbar(
controller: horizontalController,
thumbVisibility: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ void main() {
tester.view.physicalSize = const Size.square(800.0);
await tester.pumpWidget(const MaterialApp(home: InfiniteTableExample()));
await tester.pump();

expect(find.text('0:0'), findsOneWidget);

final Finder verticalScrollable = find.byWidgetPredicate((Widget widget) {
if (widget is Scrollable) {
return widget.axisDirection == AxisDirection.down;
Expand All @@ -21,6 +21,7 @@ void main() {
});
final ScrollPosition verticalPosition =
(tester.state(verticalScrollable) as ScrollableState).position;

final Finder horizontalScrollable = find.byWidgetPredicate((Widget widget) {
if (widget is Scrollable) {
return widget.axisDirection == AxisDirection.right;
Expand All @@ -29,6 +30,7 @@ void main() {
});
final ScrollPosition horizontalPosition =
(tester.state(horizontalScrollable) as ScrollableState).position;

expect(verticalPosition.pixels, 0.0);
expect(verticalPosition.maxScrollExtent, double.infinity);
expect(horizontalPosition.pixels, 0.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ void main() {
testWidgets('Builds and can scroll', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: MergedTableExample()));
await tester.pump();

expect(find.text('Red, 500'), findsOneWidget);

final Finder verticalScrollable = find.byWidgetPredicate((Widget widget) {
if (widget is Scrollable) {
return widget.axisDirection == AxisDirection.down;
Expand All @@ -20,6 +20,7 @@ void main() {
});
final ScrollPosition verticalPosition =
(tester.state(verticalScrollable) as ScrollableState).position;

final Finder horizontalScrollable = find.byWidgetPredicate((Widget widget) {
if (widget is Scrollable) {
return widget.axisDirection == AxisDirection.right;
Expand All @@ -28,6 +29,7 @@ void main() {
});
final ScrollPosition horizontalPosition =
(tester.state(horizontalScrollable) as ScrollableState).position;

expect(verticalPosition.pixels, 0.0);
expect(verticalPosition.maxScrollExtent, 5605.0);
expect(horizontalPosition.pixels, 0.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void main() {
testWidgets('Can scroll ', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: CustomTreeExample()));
await tester.pumpAndSettle();

final Finder verticalScrollable = find.byWidgetPredicate((Widget widget) {
if (widget is Scrollable) {
return widget.axisDirection == AxisDirection.down;
Expand All @@ -32,8 +33,11 @@ void main() {

expect(verticalPosition.maxScrollExtent, 0.0);
expect(verticalPosition.pixels, 0.0);
final CustomTreeExampleState state =
tester.state(find.byType(CustomTreeExample)) as CustomTreeExampleState;

final CustomTreeExampleState state = tester.state(
find.byType(CustomTreeExample),
) as CustomTreeExampleState;

state.treeController.toggleNode(state.treeController.getNodeFor('lib')!);
await tester.pumpAndSettle();
verticalPosition =
Expand All @@ -42,14 +46,18 @@ void main() {
expect(verticalPosition.pixels, 0.0);
state.treeController.toggleNode(state.treeController.getNodeFor('test')!);
await tester.pumpAndSettle();

verticalPosition =
(tester.state(verticalScrollable) as ScrollableState).position;

expect(verticalPosition.maxScrollExtent, 10.0);
expect(verticalPosition.pixels, 0.0);
state.treeController.toggleNode(state.treeController.getNodeFor('src')!);
await tester.pumpAndSettle();

verticalPosition =
(tester.state(verticalScrollable) as ScrollableState).position;

// Enough nodes expanded to allow us to scroll
expect(verticalPosition.maxScrollExtent, 190.0);
expect(verticalPosition.pixels, 0.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ void main() {

expect(horizontalPosition.maxScrollExtent, greaterThan(190));
expect(horizontalPosition.pixels, 0.0);
final TreeExampleState state =
tester.state(find.byType(TreeExample)) as TreeExampleState;
final TreeExampleState state = tester.state(
find.byType(TreeExample),
) as TreeExampleState;

state.treeController.expandAll();
await tester.pumpAndSettle();
horizontalPosition =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {

/// The depth of each currently active node in the tree.
///
/// This is used to properly set the [ChildVicinity] for the [traversalOrder].
/// This is used to properly set the [TreeVicinity] for the [traversalOrder].
Map<int, int> get rowDepths => _rowDepths;
Map<int, int> _rowDepths;
set rowDepths(Map<int, int> value) {
Expand All @@ -103,9 +103,9 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
}

/// The number of pixels by which child nodes will be offset in the cross axis
/// based on their [TreeViewNodeParentData.depth].
/// based on [rowDepths].
///
/// If zero, can alternatively offset children in [TreeView.treeRowBuilder]
/// If zero, children can alternatively be offset in [TreeView.treeRowBuilder]
/// for more options to customize the indented space.
double get indentation => _indentation;
double _indentation;
Expand Down Expand Up @@ -133,11 +133,14 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
bool _verticalOverflows = false;
bool _horizontalOverflows = false;

// Since the index of animating children can change at anytime, we use a
// UniqueKey to track them during the lifetime of the animation.
// Maps the index of parents to the animation key of their children.
final Map<int, UniqueKey> _animationLeadingIndices = <int, UniqueKey>{};
// Maps the key of child node animations to the fixed distance they are
// traversing during the animation. Determined at the start of the animation.
final Map<UniqueKey, double> _animationOffsets = <UniqueKey, double>{};
// Updates the cache at the start of eah layout pass.
void _updateAnimationCache() {
_animationLeadingIndices.clear();
_activeAnimations.forEach(
Expand Down Expand Up @@ -206,21 +209,23 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
}

void _computeAnimationOffsetFor(UniqueKey key, double position) {
// `position` represents the trailing edge of the parent node that initiated
// the animation.
assert(_activeAnimations[key] != null);
double currentPosition = position;
final int startingIndex = _activeAnimations[key]!.fromIndex;
final int lastIndex = _activeAnimations[key]!.toIndex;
int currentIndex = startingIndex;
double totalAnimatingOffset = 0.0;
// We animate only a portion of children that would be visible/in the cache
// extent, unless all children would fit on the screen.
// extent, unless all animating children would fit on the screen.
while (currentIndex <= lastIndex && currentPosition < _targetRowPixel) {
_Span? span = _rowMetrics.remove(currentIndex);
assert(needsDelegateRebuild || span != null);
final TreeRow configuration = needsDelegateRebuild
? delegate.buildRow(ChildVicinity(
xIndex: _rowDepths[currentIndex]!,
yIndex: currentIndex,
? delegate.buildRow(TreeVicinity(
depth: _rowDepths[currentIndex]!,
row: currentIndex,
))
: span!.configuration;
span ??= _Span();
Expand Down Expand Up @@ -255,9 +260,9 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
_Span? span = _rowMetrics.remove(row);
assert(needsDelegateRebuild || span != null);
final TreeRow configuration = needsDelegateRebuild
? delegate.buildRow(ChildVicinity(
xIndex: _rowDepths[row]!,
yIndex: row,
? delegate.buildRow(TreeVicinity(
depth: _rowDepths[row]!,
row: row,
))
: span!.configuration;
span ??= _Span();
Expand Down Expand Up @@ -328,6 +333,7 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
_furthestHorizontalExtent - viewportDimension.width,
);
_horizontalOverflows = maxHorizontalExtent > 0.0;

final double maxVerticalExtent = math.max(
0.0,
_rowMetrics[_lastRow!]!.trailingOffset - viewportDimension.height,
Expand Down Expand Up @@ -377,9 +383,9 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
}
rowOffset += rowSpan.configuration.padding.leading;

final ChildVicinity vicinity = ChildVicinity(
xIndex: _rowDepths[row]!,
yIndex: row,
final TreeVicinity vicinity = TreeVicinity(
depth: _rowDepths[row]!,
row: row,
);
final RenderBox child = buildOrObtainChildFor(vicinity)!;
final TwoDimensionalViewportParentData parentData = parentDataOf(child);
Expand All @@ -402,8 +408,14 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
_updateScrollBounds();
}

// Maps the UniqueKey associated with animating node segments with the clip
// LayerHandle.
final Map<UniqueKey, LayerHandle<ClipRectLayer>> _clipHandles =
<UniqueKey, LayerHandle<ClipRectLayer>>{};
// Used as the UniqueKey for the viewport or leading segment that does not
// have an animation key. When we are not animating, this clips the viewport
// bounds if there is visual overflow. When we are animating, it clips the
// leading segment if there is visual overflow.
final UniqueKey _viewportClipKey = UniqueKey();

@override
Expand All @@ -415,7 +427,7 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
assert(_firstRow != null && _lastRow != null);

if (_animationLeadingIndices.isEmpty) {
// There are no animations running. Clip if there is visual overflow.
// There are no animations running. Clip only if there is visual overflow.
if (_hasVisualOverflow && clipBehavior != Clip.none) {
_clipHandles[_viewportClipKey] ??= LayerHandle<ClipRectLayer>();
_clipHandles[_viewportClipKey]!.layer = context.pushClipRect(
Expand Down Expand Up @@ -547,7 +559,7 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
if (configuration.backgroundDecoration != null ||
configuration.foregroundDecoration != null) {
final RenderBox child = getChildFor(
ChildVicinity(xIndex: _rowDepths[currentRow]!, yIndex: currentRow),
TreeVicinity(depth: _rowDepths[currentRow]!, row: currentRow),
)!;

Rect getRowRect(bool consumePadding) {
Expand Down Expand Up @@ -594,7 +606,7 @@ class RenderTreeViewport extends RenderTwoDimensionalViewport {
// Child nodes.
for (int row = leadingRow; row <= trailingRow; row++) {
final RenderBox child = getChildFor(
ChildVicinity(xIndex: _rowDepths[row]!, yIndex: row),
TreeVicinity(depth: _rowDepths[row]!, row: row),
)!;
final TwoDimensionalViewportParentData rowParentData =
parentDataOf(child);
Expand Down

0 comments on commit f3390ca

Please sign in to comment.