Thanks for the explanation. However, I am still puzzled. (Fx: Transatlantic groan.)
Let's say you're in the 'edit' state and you click something that will take you to the 'list' state.
That click should lead to a notification that causes a PopUpMediator hears and shows its Popup asking if you want to save.
Suppose, for the sake of argument, the action is clicking on another record in the grid. The grid mediator generates a SELECT_RECORD notification.
My PopUpMediator (you seem to be saying) consumes this. But it needs to know if I am in the edit state. If I am, it pops up and does its thing as you describe. If I am in the list state, it creates an action to change the state back to list state, and somehow forwards the notification so that the mediator that owns the 'Display this record' component loads up the new record.
So now my PopUpMediator has to know what the FSM state is, and test it. Doesn't it? Is that ok? Surely its behaviour should fall out of the transitions that take place, rather than by explicitly querying state? We seem to have moved the logic of the state transitions out of the XML definition of the FSM, and into the code inside the PopUpMediator.
I was thinking of a design something like this:
The SELECT_RECORD notification, issued when the user clicks on a different record in the grid, is changed into a StateMachine.ACTION called SELECT_RECORD that causes the state machine to try to exit the 'edit' state. This is defined in the FSM.
I set up an AsyncCommand that detects attempts to exit 'edit' state and runs the popup, gathering the result in its callback. When the popup dialog returns, and we are still trying to exit the state, and the following logic gets executed:
- if the user has clicked 'Yes, save my edited record' then the callback triggers a notification for AsyncMacroCommand comprising two parts: 1) save the record, 2) select the clicked-on record. If the 'save the record' part fails, by the way, I most likely issue a StateMachine.CANCEL notification.
- if the user has clicked 'No, ditch my edited record' then just perform the 'select the clicked-on record' part as described above.
- if the user has clicked 'cancel, let's keep on editing' then the callback in the async command generates a StateMachine.CANCEL notification - aborting the state transition
But this design contradicts the very first sentence in your answer, viz:
With the StateMachine, you need to be sure that its safe to change states BEFORE sending the StateMachine.ACTION notification that kicks off the transition.
because I want to be able to abort an ongoing transition. What is CANCEL for if not to abort a transition?
Sorry to be thick, and thanks for your ongoing patience.