Skip to content

Commit

Permalink
feat: add ParentIsA to force parent child relations (#1566)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfenrain authored Apr 27, 2022
1 parent 666a2b1 commit 2cdf386
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
20 changes: 19 additions & 1 deletion doc/flame/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ available eventually: after they are loaded and mounted. We can only assure
that they will appear in the children list in the same order as they were
scheduled for addition.

### Ensuring a component has a given parent

When a component requires to be added to a specific parent type the
`ParentIsA` mixin can be used to enforce a strongly typed parent.

Example:

```dart
class MyComponent extends Component with ParentIsA<MyParentComponent> {
@override
Future<void> onLoad() async {
// parent is of type MyParentComponent
print(parent.myValue);
}
}
```

If you try to add `MyComponent` to a parent that is not `MyParentComponent`,
an assertion error will be thrown.

### Querying child components

Expand Down Expand Up @@ -305,7 +324,6 @@ Future<void> onLoad() async {
Remember that most components that are rendered on the screen are `PositionComponent`s, so
this pattern can be used in for example [](#spritecomponent) and [](#spriteanimationcomponent) too.


### Render PositionComponent

When implementing the `render` method for a component that extends `PositionComponent` remember to
Expand Down
1 change: 1 addition & 0 deletions packages/flame/lib/components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export 'src/components/mixins/has_game_ref.dart';
export 'src/components/mixins/has_paint.dart';
export 'src/components/mixins/hoverable.dart';
export 'src/components/mixins/keyboard_handler.dart';
export 'src/components/mixins/parent_is_a.dart';
export 'src/components/mixins/single_child_particle.dart';
export 'src/components/mixins/tappable.dart';
export 'src/components/nine_tile_box_component.dart';
Expand Down
13 changes: 13 additions & 0 deletions packages/flame/lib/src/components/mixins/parent_is_a.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import '../../../components.dart';

/// A mixin that ensures a parent is of the given type [T].
mixin ParentIsA<T extends Component> on Component {
@override
T get parent => super.parent! as T;

@override
void onMount() {
assert(super.parent is T, 'Parent must be of type $T');
super.onMount();
}
}
35 changes: 35 additions & 0 deletions packages/flame/test/components/mixins/parent_is_a_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';

class ParentComponent extends Component {}

class DifferentComponent extends Component {}

class TestComponent extends Component with ParentIsA<ParentComponent> {}

void main() {
group('ParentIsA', () {
testWithFlameGame('successfully sets the parent link', (game) async {
final parent = ParentComponent();
final component = TestComponent();

await parent.add(component);
await game.add(parent);

expect(component.parent, isA<ParentComponent>());
});

test('throws assertion error when the wrong parent is used', () {
final parent = DifferentComponent();
final component = TestComponent();

parent.add(component);

expect(
component.onMount,
failsAssert('Parent must be of type ParentComponent'),
);
});
});
}

0 comments on commit 2cdf386

Please sign in to comment.