vty-ui-1.0: doc/ch4/CheckBox.tex
\section{Checkboxes and Radio Buttons}
The \fw{CheckBox} module provides a rich API for creating ``check
box'' and ``radio button'' widgets. Radio button widgets can be
grouped together into ``radio groups'' to determine their collective
exclusion behavior.
The \fw{CheckBox} module provides generalized, ``multi-state''
checkboxes which may be in one of an arbitrary number of states, each
having its own ``checked character'' visible in the checkbox. The
``binary'' checkbox provided by the module is of the traditional
two-state variety that we usually mean when we say ``check box.''
Most of the \fw{CheckBox} module's functions are polymorphic on the
\fw{CheckBox}'s value type.
Add a \fw{CheckBox} to your interface and insert it into a
\fw{FocusGroup} to use it.
\subsection{Binary Checkboxes}
Binary checkboxes can be created with the \fw{newCheckbox} function,
which returns a \fw{Wid\-get (Check\-Box Bool)}. Each checkbox has a
text label which is passed to the constructor:
\begin{haskellcode}
cb <- newCheckbox "Fancy Graphics"
\end{haskellcode}
Binary \fw{CheckBox}es look like this:
\begin{verbatim}
[ ] Fancy Graphics
[x] Fancy Graphics
\end{verbatim}
The user uses the \fw{Space} key to change the \fw{CheckBox} state.
Event handlers for checkbox state changes can be registered with
\fw{onCheckboxChange} and take a single parameter, which is the value
of the checkbox after the state change occurs. In general, for a
checkbox of type \fw{Widget (CheckBox a)}, the parameter to the event
handler is of type \fw{a}.
\begin{haskellcode}
cb `onCheckboxChange` \val ->
...
\end{haskellcode}
Binary \fw{CheckBox}es can be manipulated with the functions
\fw{set\-Checkbox\-Checked}, \fw{set\-Checkbox\-Unchecked}, and
\fw{toggle\-Checkbox}.
\subsection{Radio Buttons}
\label{sec:radio_buttons}
A radio button is essentially a checkbox, but with restrictions. We
use the \fw{CheckBox} implementation to create radio buttons and use a
``radio group'' type to enforce the mutual exclusion required to make
radio buttons work. As a result, only ``binary'' checkboxes (of type
\fw{Widget (CheckBox Bool)}) may be used as radio buttons.
Radio buttons may be created by creating normal binary \fw{CheckBoxes}
and adding them to \fw{RadioGroup}s. A \fw{RadioGroup} can be created
with the \fw{newRadioGroup} function.
\begin{haskellcode}
rg <- newRadioGroup
cb1 <- newCheckbox "Cake"
cb2 <- newCheckbox "Death"
\end{haskellcode}
Once you have created the checkboxes and \fw{RadioGroup}, you can add
the checkboxes to the radio group with \fw{addToRadioGroup}:
\begin{haskellcode}
addToRadioGroup rg cb1
addToRadioGroup rg cb2
\end{haskellcode}
Once a \fw{CheckBox} has been added to a \fw{RadioGroup}, its
appearance will be changed to indicate that it has a different
behavior. \fw{CheckBox}es in \fw{RadioGroup}s look like this:
\begin{verbatim}
( ) Cake
(*) Death
\end{verbatim}
If you'd like to know when a \fw{RadioGroup}'s currently-selected
\fw{CheckBox} changes, you can register an event handler for this
event with \fw{onRadioChange}. Its parameter will be a reference to
the \fw{CheckBox} that became selected:
\begin{haskellcode}
rg `onRadioChange` \theCb ->
...
\end{haskellcode}
Once you have a reference to a \fw{CheckBox}, you can get its state
with \fw{getCheckboxState}. For example, for binary checkboxes this
value will be a \fw{Bool}.
\begin{haskellcode}
rg `onRadioChange` \theCb -> do
st <- getCheckboxState theCb
...
\end{haskellcode}
A \fw{CheckBox}'s state can be changed with the \fw{setCheckboxState}
function. If you attempt to set the state to an invalid value, a
\fw{CheckBoxError} exception (\fw{Bad\-Checkbox\-State}) will be
thrown.
In addition to using an event handler to be notified when a
\fw{RadioGroup} changes state, you can also use the
\fw{getCurrentRadio} function to get a \fw{Radio\-Group}'s current
\fw{Check\-Box} at any time.
\subsection{Generalized, Multi-State Checkboxes}
Although binary checkboxes may serve most purposes, they are a
specific case of generalized checkboxes which associated characters
(like \fw{'x'} and \fw{'*'} above) with values of any type. A
multi-state checkbox can have any number of these states, and the user
can toggle between them in order.
To create a new multi-state checkbox, you must specify value-character
mappings in addition to a text label. The checkbox's initial state is
the first one in the list passed to the constructor.
\begin{haskellcode}
-- cb :: Widget (CheckBox Int)
cb <- newMultiStateCheckbox "Number of Cakes" [ (1, '1')
, (2, '2')
, (3, '3')
]
\end{haskellcode}
When the user interacts with a multi-state \fw{CheckBox}, repeated
state changes will cycle through the list of values specified in the
constructor. In all other respects, multi-state checkboxes are the
same as binary checkboxes, and all polymorphic API functions can be
used on them.
\subsection{Customizing a \fw{CheckBox}'s Appearance}
We saw in Section \ref{sec:radio_buttons} that the appearance of a
\fw{CheckBox} can be changed. This is accomplished with the following
functions:
\begin{itemize}
\item \fw{setStateChar} -- given a \fw{CheckBox} and a state value,
the character representation of that state will be set. If the
state value is invalid, \fw{CheckBoxError}
(\fw{Bad\-State\-Argument}) will be thrown. As an example, the
default state characters for binary checkboxes for \fw{True} and
\fw{False}, respectively, are \fw{'x'} and \fw{' '}.
\item \fw{setBracketChars} -- given a \fw{CheckBox} and two
\fw{Char}s, this sets the left and right characters, respectively,
which surround the state character. The defaults are \fw{'['} and
\fw{']'}.
\end{itemize}
\subsubsection{Growth Policy}
All \fw{CheckBox}es are fixed-size and do not grow in either
dimension.