Performing a single switch in a reactive banana

I am creating a multimodal editor using reactive-banana - and for the most part it is perfect. To expand my script, the editor is some kind of mapping software, or you might think of it as a very simple graphical editor. Currently, it has two states - selection mode and polygon creation mode. In the selection mode, the user can select previously created polygons with the right mouse button (which theoretically leads you to the new selected mode), or they can start creating a new polygon with the left mouse button.

The intention is that when you click the left mouse button, we switch from selection mode to polygon creation mode. In this mode, the left mouse button means β€œadd a new vertex” until the user returns to the original vertex. At this point, they closed the polygon, so back to the selection mode.

I implemented this in several different ways, and recently noticed that the event switcher almost makes it very elegant. I can:

 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) 

As well as

 createSectorMode :: Frameworks t => HadoomGUI -> SectorBuilder -> Point V2 Double -> Moment t (Behavior t Diagram) createSectorMode HadoomGUI{..} initialSectorBuilder firstVertex = do mouseClicked <- registerMouseClicked guiMap ... 

It certainly works - for a single click. If I click on the map once, I will switch to the sector creation mode from the state I was in. However, if I click again, defaultMode will receive a click event and switch to the new polygon creation mode, discarding the previous state.

What I would like to do is enable defaultMode once and never be able to return. Essentially, I want to "swap" the Behavior t Diagram created by defaultMode result of createSectorMode .

I understand that reactive-banana has problems building dynamic events, but I am ready to live with it at the moment. The above wording is much more accurate than everything I have written so far - for example, having a single CurrentState variable and filtering various events based on its contents. The problem I am facing is that it is too big and I have too many opportunities for me to ruin everything. With switching, I mean only those events that I can talk about.

+6
source share
1 answer

The problem is somewhat open, so I can not give a definite answer. But I can, of course, give my opinion .; -)

However, what I'm likely to do is to separate the switching between modes from mode behavior. If we forget about FRP for a moment, your program is a bit like a couple of functions that call themselves recursively:

 defaultMode = ... `andthen` sectorMode sectorMode = ... `andthen` defaultMode 

It is a bit like a "sequential" program, "do this mode first, then execute this mode." I think there is nothing wrong with this, although by default the API reactive banana, in particular switchB , does not support this style very well. You mentioned (privately) that you can write

 once :: Event ta -> Event ta 

which skips the first event, but discards the rest. This is really what you need for a consistent style.

Since you always return to the default mode, I would probably try a different approach in which each mode has an event indicating that it wants to be disabled. The switching itself takes on an "external" entity. The idea is to avoid explicit recursion in the program above by some higher order combinator. In pseudo code, it looks something like this:

 modeManager = switchB initialMode changeMode changeMode = defaultModeSwitch `union` sectorModeSwitch 

although I'm a little unsure of the details. Actually, I'm not quite sure if it works at all, you probably still need a combinator once .

Anyway, this is just an idea on how to go about switching. I completely agree that switching is the right way to work with different modes.

+3
source

Source: https://habr.com/ru/post/980639/


All Articles