Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions packages/flame/lib/src/experimental/layout_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,30 @@ abstract class LayoutComponent extends PositionComponent {
double? get layoutSizeX => _layoutSizeX;
double? get layoutSizeY => _layoutSizeY;

/// Avoid using within layout logic.
/// Instead, use [setLayoutAxisLength], as it allows selective setting of
/// vector components, and subsequently selective setting of the
/// size components.
/// Sets both layout axes at the same time, and consequently, sets the [size]
/// in one go.
/// If you intend to only selectively set one axis length at a time, use
/// [setLayoutAxisLength].
///
/// This is *not* equivalent to calling [setLayoutAxisLength] for both
/// axes. Doing so would result size listeners being called twice: once for
/// the x axis, and again for the y axis.
void setLayoutSize(double? layoutSizeX, double? layoutSizeY) {
setLayoutAxisLength(LayoutAxis.x, layoutSizeX);
setLayoutAxisLength(LayoutAxis.y, layoutSizeY);
_layoutSizeX = layoutSizeX;
_layoutSizeY = layoutSizeY;
resetSize();
}

/// A helper function to set the appropriate layout dimension based on
/// [axis]. This is needed because currently there's no other way, at the
/// [LayoutComponent] level, to selective set width or height without setting
/// both.
/// e.g. if [axis] is [LayoutAxis.y], then that's the y axis.
/// Sets the appropriate layout dimension based on [axis]. This is needed
/// because currently there's no other way, at the [LayoutComponent] level,
/// to selectively set width or height without setting both.
/// e.g. to set Y axis to 100, `setLayoutAxisLength(LayoutAxis.y, 100)`
///
/// If you intend to set both axes at the same time, use [setLayoutSize]
///
/// This is *not* equivalent to calling [setLayoutSize] with one of the axes
/// set to null. Doing so would actually set the axis to the intrinsic length
/// of that dimension.
void setLayoutAxisLength(LayoutAxis axis, double? value) {
// This is necessary because we cannot extend the accessor assignment of
// NullableVector2 to trigger some extra functionality
Expand All @@ -65,8 +75,10 @@ abstract class LayoutComponent extends PositionComponent {
/// Reset the size of this [LayoutComponent] to either the layout dimensions
/// or the [intrinsicSize].
void resetSize() {
width = _layoutSizeX ?? intrinsicSize.x;
height = _layoutSizeY ?? intrinsicSize.y;
size.setValues(
_layoutSizeX ?? intrinsicSize.x,
_layoutSizeY ?? intrinsicSize.y,
);
}

bool isShrinkWrappedIn(LayoutAxis axis) {
Expand Down
30 changes: 30 additions & 0 deletions packages/flame/test/experimental/linear_layout_component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,36 @@ void main() {
expect(textBoxComponent.boxConfig.maxWidth, layoutComponent.width);
},
);
testWithFlameGame(
'setLayoutSize and setLayoutAxisLength each notify once',
(game) async {
final layoutComponent = ColumnComponent();
await game.ensureAdd(layoutComponent);
var setLayoutSizeCallCount = 0;
var setLayoutAxisLengthCallCount = 0;
void firstListener() {
setLayoutSizeCallCount += 1;
}

void secondListener() {
setLayoutAxisLengthCallCount += 1;
}

layoutComponent.size.addListener(firstListener);
layoutComponent.setLayoutSize(100, 100);
await game.lifecycleEventsProcessed;
layoutComponent.size.removeListener(firstListener);
expect(setLayoutSizeCallCount, 1);
expect(layoutComponent.size, Vector2(100, 100));

layoutComponent.size.addListener(secondListener);
layoutComponent.setLayoutAxisLength(LayoutAxis.x, 200);
await game.lifecycleEventsProcessed;
layoutComponent.size.removeListener(secondListener);
expect(setLayoutAxisLengthCallCount, 1);
expect(layoutComponent.size, Vector2(200, 100));
},
);
});
});
}