UISF- Library for Arrowized Graphical User Interfaces.

Safe HaskellNone




A simple Graphical User Interface with concepts borrowed from Phooey by Conal Elliot.


UI Type Definition

newtype UI a Source

A UI widget runs under a given context and any focus information from earlier widgets and maps input signals to outputs, which consists of 6 parts:

  • its layout,
  • whether the widget needs to be redrawn,
  • any focus information that needs to be conveyed to future widgets
  • the action (to render graphics or/and sounds),
  • any new ThreadIds to keep track of (for proper shutdown when finished),
  • and the parametrized output type.




ioToUI :: IO a -> UI aSource

Lifts an 'IO a' to a 'UI a'

Control Data

type ControlData = [ThreadId]Source

The control data is simply a list of Thread Ids.

nullCD :: ControlDataSource

No new thread ids.

addThreadID :: ThreadId -> UI ()Source

A thread handler for the UI monad.

mergeCD :: ControlData -> ControlData -> ControlDataSource

A method for merging to control data objects.

Rendering Context

data CTX Source

A rendering context specifies the following:




flow :: Flow

A layout direction to flow widgets.

bounds :: Rect

A rectangle bound of current drawing area to render a UI component. It specifies the max size of a widget, not the actual size. It's up to each individual widget to decide where in this bound to put itself.

isConjoined :: Bool

A flag to tell whether we are in a conjoined state or not. A conjoined context will duplicate itself for subcomponents rather than splitting. This can be useful for making compound widgets when one widget takes up space and the other performs some side effect having to do with that space.

data Flow Source

Flow determines widget ordering.


type Dimension = (Int, Int)Source

A dimension specifies size.

type Rect = (Point, Dimension)Source

A rectangle has a corner point and a dimension.

UI Layout

data Layout Source

The layout of a widget provides data to calculate its actual size in a given context.

  1. hFill/vFill specify how much stretching space (in units) in horizontal/vertical direction should be allocated for this widget.
  2. hFixedvFixed specify how much non-stretching space (widthheight in pixels) should be allocated for this widget.
  3. minWminH specify minimum values (widthheight in pixels) for the widget's dimensions.




hFill :: Int
vFill :: Int
hFixed :: Int
vFixed :: Int
minW :: Int
minH :: Int


data LayoutType Source

A dimension can either be:



Stretchy with a minimum size in pixels


minSize :: Int

Fixed with a size measured in pixels


fixedSize :: Int

makeLayout :: LayoutType -> LayoutType -> LayoutSource

This function takes layout information for first the horizontal dimension and then the vertical.

nullLayout :: LayoutSource

The null layout is useful for "widgets" that do not appear or take up space on the screen.

Context and Layout Functions

divideCTX :: CTX -> Layout -> Layout -> (CTX, CTX)Source

Divides the CTX according to the ratio of a widget's layout and the overall layout of the widget that receives this CTX. Therefore, the first layout argument should basically be a sublayout of the second.

mergeLayout :: Flow -> Layout -> Layout -> LayoutSource

Merge two layouts into one.

Action and System State

type Action = (Graphic, Sound)Source

Actions include both Graphics and Sound output. Even though both are indeed just IO monads, we separate them because Sound output must be immediately delivered, while graphics can wait until the next screen refresh.

type Sound = IO ()Source

A type synonym for sounds.

nullSound :: SoundSource

This is used when there is no sound produced.

nullAction :: ActionSource

This is used when no Action happens at all.

justSoundAction :: Sound -> ActionSource

Convert a Sound to an Action with no Graphic.

justGraphicAction :: Graphic -> ActionSource

Convert a Graphic to an Action with no Sound.

mergeAction :: Monad m => (Graphic, m a) -> (Graphic, m b) -> (Graphic, m b)Source

Merge two actions into one.

scissorAction :: CTX -> Action -> ActionSource

Use a context to bound the graphical effects of an action.

type Focus = (WidgetID, FocusInfo)Source

The Focus type helps focusable widgets communicate with each other about which widget is in focus. It consists of a WidgetID and a FocusInfo.

type WidgetID = IntSource

The WidgetID for any given widget is dynamic based on how many focusable widgets are active at the moment. It is designed basically as a counter that focusable widgets will automatically (via the focusable function) increment.

data FocusInfo Source

The FocusInfo means one of the following:



Indicates that this widget is a subwidget of a widget that is in focus. Thus, this widget too is in focus, and this widget should pass HasFocus forward.


Indicates that there is no focus information to communicate between widgets.

SetFocusTo WidgetID

Indicates that the widget whose id is given should take focus. That widget should then pass NoFocus onward.

type DirtyBit = BoolSource

The dirty bit is a bit to indicate if the widget needs to be redrawn.