-
Notifications
You must be signed in to change notification settings - Fork 4
States
The most basic states, these are leafs in our state chart and can be transitioned to and from.
In the following example both On
and Off
are atomic states.
final machine = StateMachine.create(
(g) => g
..initial<Off>()
..state<Off>(builder: (g) => g..on<OnToggle, On>())
..state<On>(builder: (g) => g..on<OnToggle, Off>())
);
Conceptually known as "Final" states, these are states to which a state machine cant transition from.
In the following example Dead
is a terminal state.
final machine = StateMachine.create(
(g) => g
..initial<Alive>()
..state<Alive>(builder: (g) => g..on<OnDie, Dead>())
..state<Dead>(type: StateNodeType.terminal)
);
Compound states are not leafs, they contain children nodes and whenever a compound state is active, one of it's child nodes is also active.
In the following example, Alive
is a compound state composed by Young
, MiddleAged
and Old
child states.
final machine = StateMachine.create(
(g) => g
..initial<Alive>()
..state<Alive>(
builder: (b) => b
..initial<Young>()
..on<OnBirthday, Young>(...)
..on<OnBirthday, MiddleAged>(...)
..on<OnBirthday, Old>(...)
..on<OnDeath, Purgatory>()
..state<Young>()
..state<MiddleAged>()
..state<Old>(),
)
..state<Dead>(),
);
Conceptually known as "Orthogonal regions". Whenever a parallel state is active, all it's children are active as well.
In the following example both, MainKeypad
and NumericKeypad
are active.
final machine = StateMachine.create(
(g) => g
..initial<Keyboard>()
..state<Keyboard>(
builder: (b) => b
..state<MainKeypad>(
builder: (b) => b
..initial<Default>()
..state<Default>((b) => b..on<ToggleCaps, CapsOn>())
..state<CapsOn>((b) => b..on<ToggleCaps, Default>()),
)
..state<NumericKeypad>(
builder: (b) => b
..initial<Numbers>()
..state<Numbers>((b) => b..on<ToggleCaps, NumLock>())
..state<Arrows>((b) => b..on<ToggleCaps, NumLock>()),
),
),
);
This element represents the default initial state for a complex element (i.e. one containing child or elements.
In the following example the machine will start with Alive > Young
as initial state. And if we transition from Dead
to Alive
, the machine will automatically enter the Young
state.
final machine = StateMachine.create(
(g) => g
..initial<Alive>()
..state<Alive>(
builder: (b) => b
..initial<Young>()
..state<Young>()
..state<MiddleAged>()
..state<Old>(),
)
..state<Dead>(
builder: (b) => b..on<Resurrect, Alive>()
),
);
To see if your machine is in a given state, you can either use isInState(Type)
or matchesStatePath(List<Type>)
.
Usually the isInState
is enough, you'll only need matchesStatePath
if you have states with the same type under different parallel machines.
In the following example you have the states _Walk
, _Wait
and _Stop
under both _Crosswalk1
and _Crosswalk1
.
final machine = StateMachine.create(
(g) => g
..initial<_Green>()
..state<_Green>(
builder: (b) => b..on<_OnTimer, _Yellow>(),
)
..state<_Yellow>(
builder: (b) => b..on<_OnTimer, _Red>(),
)
..state<_Red>(
type: StateNodeType.parallel,
builder: (b) => b
..state<_Crosswalk1>(
builder: (b) => b
..initial<_Walk>()
..state<_Walk>(
builder: (b) => b..on<_OnPedWait, _Wait>(),
)
..state<_Wait>(
builder: (b) => b..on<_OnPedStop, _Stop>(),
)
..state<_Stop>(
type: StateNodeType.terminal,
)
)
..state<_Crosswalk2>(
builder: (b) => b
..initial<_Walk>()
..state<_Walk>(
builder: (b) => b..on<_OnPedWait, _Wait>(),
)
..state<_Wait>(
builder: (b) => b..on<_OnPedStop, _Stop>(),
)
..state<_Stop>(
type: StateNodeType.terminal
)
)
..onDone(
type: StateNodeType.terminal,
actions: [(_) => actions.prepareGreenLight()],
),
)
);
If you use isInState
it will return true if any of these crosswalks is in that state, but if you want to be more specific you'll have to use matchesStatePath
. To use matchesStatePath
you need to pass a List of States and they are checked against the path of each active node.
// Match a unique state
finalMachine.isInState(_Red)
// Match states by their path.
finalMachine.matchesStatePath([_Crosswalk1, _Walk])
finalMachine.matchesStatePath([_Crosswalk2, _Walk])