title: Computer game in Haskell — widget toolkit wanted
body: <p>I am writing a small RTS game in Haskell, and the time has come to
  create some GUI for it (buttons, menus and such).  However, I don't
  have any experience in GUI toolkit creation, so I would be thankful
  for ideas on how to choose right data types, event handling routines
  and such.</p>
  
  <p>Desired functionality: menu screens (main, load/save, settings,
  network game), text inputs, game interface (main screen (C&amp;C-like)
  with buttons, selects and checkboxes.</p>
  
  <p>My current approach is to represent the whole GUI as a state machine
  that has a number of states and transitions between them that are
  triggered when an event arrives:</p>
  
  <pre><code>-- Local client state.  Actual game state is stored on the server
  -- and is updated/synced separately.
  data ClientState = […]
  
  -- Keyboard state, mouse state, quadtree of clickables, list of
  -- widgets.
  data UIState = […]
  
  uiCycle :: UIState -&gt; ClientState -&gt; IO ()
  uiCycle uiState clientState = do
    event &lt;- waitEvent
    let widget = findWidget uiState event
    let (uiState', clientStateAction, ioAction) =
          uiTransition widget event uiState clientState
    -- Update game state (execute game logic).
    let clientState' = clientStateAction clientState
    -- Redraw appropriate surfaces etc.
    ioAction
    uiCycle uiState' clientState'
  </code></pre>
  
  <p>Widget is something like</p>
  
  <pre><code>data Widget =
    Widget { wtType          :: WidgetType
           , wtParent        :: Maybe Widget
           --, wtRelated       :: [Widget] -- Feels hacky.
           , wtBox           :: Rect
           , wtPosition      :: WidgetPosition
           , wtAnchors       :: [WidgetAnchor]
           , wtEventHandlers :: Map Event EventHandler
           , wtDisabled      :: Bool
           }
  </code></pre>
  
  <p>where</p>
  
  <pre><code>type EventHandler = (Event -&gt; (UIState, ClientState) -&gt;
                      (UIState, ClientState, IO ()))
  </code></pre>
  
  <p>When an event comes and appropriate widget is found, my program looks
  for a handler for this kind of event in <code>wtEventHandlers</code> for this widget,
  and executes an action if such handler is found.</p>
  
  <p>When a widget is created, its rect is added to a <code>QuadTree</code>, which is
  queried by <code>findWidget</code>.  The tree is updated when widgets are created
  or removed.</p>
  
  <p>However, it is very difficult to program in that way because UI states
  are already numerous (even for a simple UI with a few buttons and no
  menus).</p>
  
  <p>I thought about implementing each widget as a state machine and
  composing these machines so that the number of states and transitions
  will be reduced.  Perhaps it would be good to wrap it into a monad (like
  it is done in XMonad).</p>
  
  <p>Things I have looked at:</p>
  
  <ul>
  <li>pygame dot org/tags/gui ← didn't get any usable ideas because
  everything there is very object-oriented;</li>
  <li><a href="http://joyridelabs.de/game/code/">http://joyridelabs.de/game/code/</a> ← not applicable because they use
  Qt and I don't want such dependency;</li>
  <li><a href="http://www.scribd.com/doc/19503176/The-Design-and-Implementation-of-xmonad">http://www.scribd.com/doc/19503176/The-Design-and-Implementation-of-xmonad</a></li>
  </ul>
  
  <p>My questions are:</p>
  
  <ul>
  <li>Does describing widgets as state machines that "react" to certain events and "ignore" all others make sense to a widget toolkit designer?  Is there a better (easier) way?</li>
  <li>Is organizing interface description into a <code>Monad</code> a good idea?</li>
  </ul>
  
  <p>E. g.</p>
  
  <pre><code>mkGameScreenButtons = runGuiDef $ do
    panicExitButton /// MouseDown ==&gt; liftM exitGameNow
    panicExitButton /// MouseIn ==&gt; do hideGameScreen
                                       muteSounds
                                       muteMusic
    panicExitButton /// MouseOut ==&gt; do unhideGameScreen
                                        unmuteSounds
                                        unmuteMusic
    gameSpeedSlider /// MouseUp ==&gt; changeSpeed (wtValue gameSpeedSlider)
    [...]
   where panicExitButton = mkButton (5, 5) [AnchorTop, AnchorRight] "BOSS BUTTON"
   [...]
  </code></pre>
  
  <ul>
  <li>Is there any relevant literature I could read before moving further?  Emphasis on functional approach would be nice.</li>
  <li>Is there a way to avoid writing a widget toolkit altogether?  I want my game to be able to run in fullscreen mode, so Gtk2hs won't work.</li>
  </ul>