{-# OPTIONS -fglasgow-exts #-} {- | Module : Graphics.UI.Phooey Copyright : (c) Conal Elliott 2006 License : LGPL Maintainer : conal@conal.net Stability : provisional Portability : portable Phooey presents a simple, functional, and arrow-based interface to UI construction. This module simply re-exports most of "Graphics.UI.Phooey.ArrowUI" (hiding the implementation and extensibility). GUIs are usually programmed in an \"unnatural\" style, in that implementation dependencies are inverted, relative to logical dependencies. This reversal results directly from the imperative orientation of most GUI libraries. While outputs depend on inputs from a user and semantic point of view, the imperative approach imposes an implementation dependence of inputs on outputs. Phooey (\"/ph/unctional /oo/s/e/r /y/nterfaces\") retains the functional style, in which outputs are expressed in terms of inputs. In addition, Phooey supports dynamic input bounds, flexible layout, and mutually-referential widgets. As a first example, here is a simple shopping list GUI. The /total/ displayed at the bottom of the window always shows the sum of the values of the /apples/ and /bananas/ input sliders. When a user changes the inputs, the output updates accordingly. @ <>@ @ ui1 :: 'UI' () () ui1 = 'title' \"Shopping List\" $ proc () -> do a <- 'title' \"apples\" ('islider' 3) -< (0,10) b <- 'title' \"bananas\" ('islider' 7) -< (0,10) 'title' \"total\" 'showDisplay' -< a+b @ To run this example (found in @src\/Examples.hs@ in the source release), do @'runUI' ui1@. A @UI@ value (widget, complete interactive application, or anything in between) represents both functionality /and/ user interface. Each UI has information flowing in and information flowing out. For this reason, @UI@ has two type parameters, the input and output types. For instance, a slider has its (potentially varying) bounds as input and its (varying) value as output, while a display has the value to be displayed as input and a @()@ output. Any UI may be wrapped with a title and automatically routes input and output to and from the wrapped UI. (See below for the types of 'islider', 'showDisplay', and 'title', as used in defining @u1@ above.) The slider bounds in @ui1@ are all static. In the following example, the first two sliders determine the bounds of the third slider. @ <>@ @ ui2 = proc () -> do lo <- 'title' \"lo\" ('islider' 3) -< (0,10) hi <- 'title' \"hi\" ('islider' 8) -< (0,10) val <- 'title' \"val\" ('islider' 5) -< (lo,hi) 'title' \"factorial\" 'showDisplay' -< fact val where fact n = 'product' [1 .. n] @ By default, UI layout follows the order of the specification, with earlier-specified components above later-specified ones. This layout may be overridden by explicit layout functions. For instance, the following definitions form variations of @u1@ laid out from bottom to top and from left to right. GUIs & code: @ <>@ @ <>@ @ uiB1 = 'fromBottom' ui1 uiL1 = 'fromLeft' ui1 @ We can also lay out a sub-assembly, as in @ui3@ below, which uses the arrow @&&&@ operator to feed a single input flow into two UIs and pair up the outputs. @ <>@ @ ui3 = 'fromBottom' $ proc () -> do (a,b) <- 'fromRight' fruit -< (0,10) 'title' \"total\" 'showDisplay' -< a+b where fruit = 'title' \"apples\" ('islider' 3) &&& 'title' \"bananas\" ('islider' 7) @ Next is a recursive example. It is like @ui2@, but the @lo@ and @hi@ sliders are used to bound each other. The specification enforces the constraint that @lo <= hi@. @ <>@ @ ui4 = proc () -> do rec lo <- 'title' \"lo\" ('islider' 3) -< (0,hi) hi <- 'title' \"hi\" ('islider' 8) -< (lo,10) val <- 'title' \"val\" ('islider' 5) -< (lo,hi) 'title' \"factorial\" 'showDisplay' -< fact val returnA -< () @ The final example is tightly recursive. A slider is used to bound /itself/, so that the range is always the current value ±5. @ <>@ @ ui5 = proc () -> do rec val <- 'title' \"val\" ('islider' 6) -< (val-5,val+5) 'title' \"squared\" 'showDisplay' -< val*val @ These last two examples just hang when run. The pictures are from a previous implementation. Hmm. -} module Graphics.UI.Phooey ( -- * The UI arrow UI, runUI, runNamedUI -- * High-level widgets , stringDisplay, showDisplay, textEntry, islider , checkBoxDisplay, checkBoxEntry, title -- * Explicit layout , fromTop, fromBottom, fromLeft, fromRight, flipLayout ) where import Graphics.UI.Phooey.ArrowUI