Before we introduce the GUI elements, we discuss briefly how
fudget programs are formed using the function fudlogue
.
F a b
, for some types a and b. The main
program in Haskell should have type IO ()
, so we need a
glue function to be able to plug in the main fudget. The function
fudlogue
is provided for this purpose:
Thefudlogue :: F a b -> IO ()
main
program of a fudget program usually
consists just of a call to fudlogue
with an argument fudget.
like
However, it is possible to combinemain :: IO () main = fudlogue the_main_fudget
fudlogue
with other
monadic I/O operations. For example, to create a program that
starts by reading some configuration file, you could write
Programs with graphical user interfaces need at least one shell (top-level) window. These are created with the functionmain = do config <- readFile config_filename fudlogue (main_fudget config)
shellF
:
The typical GUI program has only one shell window, and the main program thus looks something likeshellF :: String -> F a b -> F a b
A program with more than one shell window could for example look something likemain = fudlogue (shellF window_title main_gui_fudget)
The fudgetmain = fudlogue (shellF title1 fud1 >==< shellF title2 fud2)
shellF
is not restricted to the top level.
You could write the above example as
and achieve the same result.main = fudlogue (shellF title1 (fud1 >==< shellF title2 fud2))
labelF
, which displays static
labels, and intDispF
, which displays numbers that can
change dynamically. There
is also displayF
,
a more general display for dynamically changing values. It can display values of any type in thedisplayF :: (Graphic a) => F a b
Graphic
class. It
could in fact also display numbers, but intDispF
has the
advantage that the numbers are displayed right adjusted.buttonF
,
in the examples above. It provides command buttons, i.e., buttons trigger some action when pressed. The Fudget library also provides toggle buttons and radio groups (Figure 10). Pressing these buttons causes a change that has a lasting visual effect (and probably also some other lasting effect). A toggle button changes between two states (on and off) each time you press it. A radio group allows you to activate one of several mutually exclusive alternatives. The types of these fudgets arebuttonF :: (Graphic a) => a -> F Click Click
The input messages can be used to change the setting under program control.toggleButtonF :: (Graphic a) => a -> F Bool Bool radioGroupF :: (Graphic b, Eq a) => [(a, b)] -> a -> F a a
toggleButtonF "Run" radioGroupF [(1,"P1"),(2,"P2"),(3,"P3"),(0,"Off")] 0Figure 10. Toggle buttons and radio groups.
for entering strings and integers (see Figure 13). For entering other types of values, you can usestringInputF :: F String String intInputF :: F Int Int
stringInputF
and
attach the appropriate printer and parser functions.
stringInputF
and intInputF
do not
produce any output until the user presses the Enter
(or
Return
) key to indicate that the input is complete. This
is often a reasonable behaviour, but there are versions of
these fudgets that provide more detailed information:
These fudgets output messages of typestringF :: F String (InputMsg String) intF :: F Int (InputMsg Int)
InputMsg
,
which contain the current contents of the entry field and an
indication of whether the value is intermediate or complete.
There are some stream processors that are useful when post processing messages from entry fields:
The first one passes through all messages, so that you will know about all changes to the contents of the entry field. The second one outputs a message when the user indicates that the input is complete and when the input focus leaves the entry field. The last one outputs a message only when the input is indicated as complete.stripInputSP :: SP (InputMsg a) a inputLeaveDoneSP :: SP (InputMsg a) a inputDoneSP :: SP (InputMsg a) a
The fudget stringInputF
is defined as
As we saw above, the fudgetstringInputF = absF inputDoneSP >==< stringF
pickListF
also produces
output of type InputMsg
. In this case, input is considered
to be complete when the user double clicks on an
alternative. Hence you use stripInputSP
if a single
click should be enough to make a choice, and inputDoneSP
if a double click should be required.which can display longer text.(Footnote: The names come from the fact that they serve the same purpose as the UNIX programmoreF :: F [String] (InputMsg (Int, String)) moreFileF :: F String (InputMsg (Int, String)) moreFileShellF :: F String (InputMsg (Int, String))
more
.) The input to moreF
is a list of lines of text to
be displayed. The other two fudgets display the contents of file
names received on the input. In addition, moreFileShellF
appears in its own shell window with a title reflecting the name
of the file being displayed.
There also is a text editor fudget (Figure 14),
Figure 14. The text editor fudget
editorF
.
which supports cut/paste editing with the mouse, as well as a small subset of the keystrokes used in GNU emacs. It also has an undo/redo mechanism.
pickListF
, moreF
and editorF
, have scroll bars
attached by default. There are also combinators to explicitly
add scroll bars:ThescrollF, vScrollF, hScrollF :: F a b -> F a b
v
and h
versions give only vertical and
horizontal scroll bars, respectively. The argument fudget can be
any combination of GUI elements.