content: {-# language
    GADTs
    , ExistentialQuantification
    , ScopedTypeVariables
    , RankNTypes
  #-}
  
  module Rasa.Internal.Listeners
    ( beforeEveryRender
    , beforeEveryRender_
    , dispatchBeforeRender
  
    , onEveryRender
    , onEveryRender_
    , dispatchOnRender
  
    , afterEveryRender
    , afterEveryRender_
    , dispatchAfterRender
  
    , onExit
  
    , onKeypress
    , dispatchKeypress
    ) where
  
  import Eve
  import Rasa.Internal.Events
  
  import Control.Monad
  
  -- | Trigger an 'App' on a 'Keypress'
  onKeypress :: (Keypress -> App result) -> App ListenerId
  onKeypress actionF = addListener (void <$> actionF)
  
  -- | Dispatch a 'Keypress' event.
  dispatchKeypress :: Keypress -> App ()
  dispatchKeypress = dispatchEvent
  
  -- | Registers an action to be performed BEFORE each render phase.
  --
  -- This is a good spot to add information useful to the renderer
  -- since all actions have been performed. Only cosmetic changes should
  -- occur during this phase.
  beforeEveryRender :: App a -> App ListenerId
  beforeEveryRender action = addListener (const (void action) :: BeforeRender -> App ())
  
  beforeEveryRender_ :: App a -> App ()
  beforeEveryRender_ = void . beforeEveryRender
  
  -- | Dispatch the 'BeforeRender' action.
  dispatchBeforeRender :: App ()
  dispatchBeforeRender = dispatchEvent BeforeRender
  
  -- | Registers an action to be performed during each render phase.
  --
  -- This phase should only be used by extensions which actually render something.
  onEveryRender :: App a -> App ListenerId
  onEveryRender action = addListener (const $ void action :: OnRender -> App ())
  
  onEveryRender_ :: App a -> App ()
  onEveryRender_ = void . onEveryRender
  
  -- | Dispatch the 'OnRender' action.
  dispatchOnRender :: App ()
  dispatchOnRender = dispatchEvent OnRender
  
  -- | Registers an action to be performed AFTER each render phase.
  --
  -- This is useful for cleaning up extension state that was registered for the
  -- renderer, but needs to be cleared before the next iteration.
  afterEveryRender :: App a -> App ListenerId
  afterEveryRender action = addListener (const $ void action :: AfterRender -> App ())
  
  afterEveryRender_ :: App a -> App ()
  afterEveryRender_ = void . afterEveryRender
  
  -- | Dispatch the 'AfterRender' action.
  dispatchAfterRender :: App ()
  dispatchAfterRender = dispatchEvent AfterRender
  