I'm building a multi-modal editor using reactive-banana
- and for the most part it's going perfect. To expand on my scenario, the editor is some mapping software, or you could think of it as a very simple vector graphics editor. It currently has two states - selection mode and polygon creation mode. In selection mode, the user is able to select previously created polygons with the right mouse button (which would in theory take you to a new selected mode) or they can begin creating a new polygon with the left mouse button.
The intention is, when the left mouse button is pressed, we switch from selection mode into polygon creation mode. In this mode, a left mouse button means "add a new vertex", until the user returns to the original vertex. At this point, they have closed the polygon, so we return to selection mode.
I've implemented this a few different ways, and recently noticed that event switch almost makes this very elegant. I can have:
defaultMode :: Frameworks t => HadoomGUI -> Moment t (Behavior t Diagram)
defaultMode gui@HadoomGUI{..} =
do mouseMoved <- registerMotionNotify guiMap
mouseClicked <- registerMouseClicked guiMap
let lmbClicked = ...
gridCoords = ...
diagram = ...
switchToCreateSector <- execute ((\m ->
FrameworksMoment
(=<< trimB =<< createSectorMode gui emptySectorBuilder m)) <$>
(gridCoords <@ lmbClicked))
return (switchB diagram switchToCreateSector)
Along with
createSectorMode :: Frameworks t
=> HadoomGUI
-> SectorBuilder
-> Point V2 Double
-> Moment t (Behavior t Diagram)
createSectorMode HadoomGUI{..} initialSectorBuilder firstVertex =
do mouseClicked <- registerMouseClicked guiMap
...
This certainly works - for a single mouse click. If I click on the map once, I switch into sector creation mode from the state I was just in. However, if I click again, defaultMode
receives the click event and switches into a new polygon creation mode, throwing away my previous state.
What I'd like to do is switch in defaultMode
once and never have the possibility of coming back. Essentially I want to "swap" the Behavior t Diagram
produced by defaultMode
with the result of createSectorMode
.
I understand reactive-banana
has problems with garbage collection of dynamic events, but I'm willing to live with that for now. The above formulation is significantly more precise than anything else I've written so far - such as having a single CurrentState
variable and filtering various events based on the contents of that. The problem I have with this is that it's too big, and leaves way too much scope for me to mess things up. With switching, I only have in scope the events I can about.
once
as you still have the problem that old "modes" are still receiving events, even when they ask to be switched away? I'll be sure to have a play with this and see what I find. – Mcalpin