How do you handle the execution and unwinding of multi-step interactive transactions with non-modal dialogs?
Let’s define a transaction as multiple changes in a data model that make sense only as a whole. For example, scripted stuff like adding tracks to a DAW based on predefined templates, or dropping MIDI files and letting the user pick target tracks and sounds. Let’s assume they implement a flow diagram with user interaction (e.g. select something, yes, no, cancel).
With modal dialogs, one can simply use the stack (RAII) and show any dialog along the way when a decision is needed. Easy coding and maintenance, but blocks the UI.
A non-modal alternative is emulating a transaction as a state machine that branches and continues only after user interaction. It needs to maintain its own stack (akin to Undo). If you make sure only a single such transaction can run at a time, your screen won’t fill up with dialogs of half-completed transactions (and conflicting states). Just make the screen look and feel as if it was modal, although it actually isn’t. The cumbersomeness here is that you need to disable all commands while the transaction is running (widgets, menus, toolbars). A smart UI framework can handle this transparently, but w/o such a framework you are in for a forced labor experience.
Another approach is to gather all decision-relevant information from the user in advance, by running a pre-flight or something, and start the transaction based on a single dialog (which essentially predetermines the path through the flow diagram). Logic for example, does this “mission briefing” thing when you add a new track. I think it’s a beautiful solution.
And then there’s keyboard modifiers (alt, shift, ctrl, command, …) that could be used to branch along different paths after dropping an object, but these are notoriously difficult to remember.
I get that the days of just popping up dialogs along the way as you need them are gone. But coding every transaction as a state machine, or building “mission briefing dialogs” with pre-flights seems overkill if you have many transactions of this kind.
How do you (would you) handle this?