Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
45 changes: 42 additions & 3 deletions lib/src/state_machine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ class State extends Disposable implements Function {
});
}

State._none(StateMachine machine) : this._('__none__', machine);
static const _NONE_STATE_NAME = '__none__';

State._none(StateMachine machine) : this._(_NONE_STATE_NAME, machine);

State._wildcard() : this._('__wildcard__', null, listenTo: false);

Expand All @@ -137,10 +139,32 @@ class State extends Disposable implements Function {
return _machine.current == this;
}

/// When starting the machine
/// by calling stm.start(initialState)
/// the initialState State receives an
/// onEnter event where the from state
/// is this stub one.
///
/// You can check that condition with:
///
/// initialState.onEnter((change) {
/// if (!change.from.isNone) {
/// // do something here
/// }
/// })
///
/// to ignore this false initial event.
///
/// bool, true if this state is None,
/// false otherwise
bool get isNone {
return name == _NONE_STATE_NAME;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding isNone to the API for every State instance, could we add a static field to represent the none state and use that? Then the isInitial getter below could be:

bool get isInitial => from == State.none

Copy link
Copy Markdown
Contributor Author

@lidio601 lidio601 Jun 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should looks better now

}

@override
String toString() {
String name = this.name;
if (name == '__none__') {
if (isNone) {
name = 'none - state machine has yet to start';
}
return 'State: $name (active: ${this()}, machine: ${_machine.name})';
Expand All @@ -164,10 +188,24 @@ class StateChange {

StateChange._(State this.from, State this.to, this.payload);

/// StateChange can also occour
/// after stm.start(initialState)
/// To ignore these events you can check
/// this flag and eventually ignore it:
///
/// initialState.onEnter((change) {
/// if (!change.isInitial) {
/// // do something here
/// }
/// })
bool get isInitial {
return this.from.isNone;
}

@override
String toString() {
StringBuffer sb = StringBuffer();
String fromName = from.name == '__none__' ? '(none)' : from.name;
String fromName = from.isNone ? '(none)' : from.name;
sb.writeln('StateChange: ${fromName} --> ${to.name}');
if (payload != null) {
sb.writeln(' payload: $payload');
Expand Down Expand Up @@ -247,6 +285,7 @@ class StateMachine extends Disposable {
/// This allows an initial state transition to occur
/// when the machine is started via [start].
_current = State._none(this);

manageDisposable(_current);
}

Expand Down
1 change: 1 addition & 0 deletions test/state_machine_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void main() {

test('should be in a dummy state until the machine has been started', () {
expect(machine.current.name, equals('__none__'));
expect(machine.current.isNone, isTrue);
});

test('should throw if machine is started more than once', () {
Expand Down
1 change: 1 addition & 0 deletions test/state_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ void main() {

test('.toString() should explain what the __none__ state means', () {
State noneState = machine.current;
expect(noneState.isNone, isTrue);
String s = noneState.toString();
expect(s, contains('machine has yet to start'));
expect(s, isNot(contains('__none__')));
Expand Down