trigger method
Future<StateOfMind>
trigger(
- Graph graph,
- StateOfMind stateOfMind,
- TransitionNotification<
E> transition, { - required bool applySideEffects,
Applies transition
to the current statemachine and returns
the resulting
StateOfMind
.
As the statemachine can be in multiple states the stateOfMind
argument indicates what
stateOfMind
the transition
is to be processed against.
/
Implementation
Future<StateOfMind> trigger(Graph graph, StateOfMind stateOfMind,
TransitionNotification<E> transition,
{required bool applySideEffects}) async {
final exitPaths = <PartialStatePath>[];
final enterPaths = <PartialStatePath>[];
final fromPath = StatePath.fromLeaf(graph, transition.from!.stateType);
final toPath = StatePath.fromLeaf(graph, transition.to!.stateType);
final commonAncestor = findCommonAncestor(graph, fromPath, toPath);
if (!transition.skipExit) {
exitPaths.addAll(_getExitPaths(stateOfMind, fromPath, commonAncestor));
}
if (!transition.skipEnter) {
enterPaths.add(_getEnterPaths(toPath, commonAncestor));
}
final exitStates = dedupPaths(exitPaths);
final enterStates = dedupPaths(enterPaths);
final fromStateDefinition =
graph.stateDefinitions[transition.from.runtimeType];
if (applySideEffects) {
await _callOnExits(fromStateDefinition, transition.event, exitStates);
await _callSideEffect(transition);
}
// when entering we must start from the root and work
// towards the leaf.
await _callOnEnters(enterStates.reversed.toList(), transition.event);
for (final statePath in exitPaths.toSet()) {
/// check that a transition occured
if (statePath.isNotEmpty) {
removePath(stateOfMind, statePath.fullPath(graph));
}
}
for (final statePath in enterPaths.toSet()) {
/// check that a transition occured
if (statePath.isNotEmpty) {
addPath(stateOfMind, statePath.fullPath(graph));
}
}
// If we transitioned up to a parent [toPath]
// then we will have removed the child (and all its parents) so
// we need re-add the parent [toPath].
// No need to call onEnter as we were already in the parent state.
if (toPath.leaf == commonAncestor) {
addPath(stateOfMind, toPath);
}
/// If we transition from a child to a parent then we need to
/// remove the parent
/// No need to run onExit as we are still in the parent state
/// due to the child.
stateOfMind.stripRedundantParents();
log('Updated stateOfMind: $stateOfMind');
return stateOfMind;
}