Go to the first, previous, next, last section, table of contents.

Abstract interaction devices

The tour of Haggis has so far concentrated on the user interface aspect of an application, but an equally important feature of a user interface system is how convenient it is to combine the interactive, graphical `surface' with the underlying code that implements the application.

The approach taken is simply an extension of what catchDeviceEv does, returning a handle that reports user interaction abstractly. As an example, take the Button abstraction in Haggis:

button :: Picture -> a -> Component (Button a, DisplayHandle)

It takes as arguments the Picture label to use and the value to report each time the user clicks on the button. The Button handle returned is parameterised over this value's type, such that when performing the action

getButtonClick :: Button a -> IO a

it will block until the user clicks the button, at which point the action returns the value the button was configured with.

This represent a more abstract view of user interaction, instead of having to catch and interpret user events, the Button handle will only report the `semantically significant' events, such as the completion of a button click interaction.

To demonstrate the use of these handles, here's a little counter:

main =
 mkDC ["*title: Counter"]       >>= \ env ->
  button (text "Inc") (+1) env  >>= \ (btn, button_dh) ->
  label "0" env                 >>= \ (lab, label_dh) ->
 realiseDH env (hbox [button_dh, label_dh]) >>
 let
  loop n =
    getButtonClick btn >>= \ f ->
    let
     n' = f n 
    in
    setLabel lab (show n') >>
    loop n'
 in
 loop 0

Counter

The Button is configured to output the function value (+1) each time it is clicked. So each time the loop that listens for button clicks sees a value, it applies the current value to this function value and updates the counter display and continues. The Button has abstracted away from the look and feel of the user interface, presenting to the application (which in this case is a silly counter) an application specific view of the component. In fact, the Button handle is an instance of a general, non-user interface specific, communication abstraction, called a Trigger, See section Trigger abstraction.

The benefit of doing all this is, of course, separation of concerns. By having the application-specific code operate on abstract representations of the user interface components makes it easier to make changes to the user interface without affecting the application code.


Go to the first, previous, next, last section, table of contents.