Search code examples
haskellevent-handlinggtkgtk2hs

Toggle between event handlers in gtk2hs


I would like to do something like this:

handlerOn = do
  cid <- canvas `on` buttonPressEvent $ tryEvent do
    signalDisconnect cid
    handlerOff
  putStrLn "handlerOn"

handlerOff = do
  cid <- canvas `on` buttonPressEvent $ tryEvent do
    signalDisconnect cid
    handlerOn
  putStrLn "handlerOff"

This won't work as it is, of course, because I'm trying to use cid inside a code block where cid is not assigned yet.

The idea is to register an event listener that when it receives an event, it will deregister itself and register a different event listener which will do the same, back and forth.


Solution

  • GHC supports recursive do.

    handlerOn = do
      rec cid <- canvas `on` buttonPressEvent $ tryEvent do
        signalDisconnect cid
        handlerOff
      putStrLn "handlerOn"
    

    You could also use Control.Monad.Fix.

    handlerOff = do
      mfix $ \cid -> canvas `on` buttonPressEvent $ tryEvent do
        signalDisconnect cid
        handlerOn
      putStrLn "handlerOff"
    

    Or manage the handler yourself.

    do ...
        h <- newIORef undefined
        let handlerOn = do
                ...
                writeIORef h handlerOff
            handlerOff = do
                ...
                writeIORef h handlerOn
        writeIORef h handlerOn
        canvas `on` buttonPressEvent $ tryEvent =<< readIORef h
    

    Or just make everything into a single handler.

    do ...
        ms <- newIORef False
        canvas `on` buttonPressEvent $ tryEvent do
            s <- readIORef ms
            if s
                then ...
                else ...