vty-ui-1.0: doc/ch1/getting_started.tex
\section{Getting Started}
\label{sec:gettingStarted}
To get started using the library, you'll need to import the main library
module:
\begin{haskellcode}
import Graphics.Vty.Widgets.All
\end{haskellcode}
The \fw{All} module exports everything exported by the library; if you
prefer, you may import specific modules depending on your needs.
As a demonstration, we'll create a program which presents an editing
widget in the middle of the screen. You'll be able to provide some
text input and press Enter, at which point the program will exit and
will print what you entered. The code for this program is as follows:
\begin{haskellcode}
main :: IO ()
main = do
e <- editWidget
ui <- centered e
fg <- newFocusGroup
addToFocusGroup fg e
c <- newCollection
addToCollection c ui fg
e `onActivate` \this ->
getEditText this >>= (error . ("You entered: " ++))
runUi c defaultContext
\end{haskellcode}
There are some interesting things to note about this program. First,
it withstands changes in your terminal size automatically, even though
the size of the terminal is not an explicit part of the program.
Second, it only took a few lines of code to create a rich editing
interface and position it in the terminal as desired. Now we'll go
into some depth on this example.
\begin{haskellcode}
e <- editWidget
\end{haskellcode}
This line creates an \fw{Edit} widget. This type of widget provides
an editing interface for a single line of text and supports some
Emacs-style editing keybindings. The \fw{Edit} widget also takes care
of horizontal scrolling when its input doesn't fit into the allowed
space. For more information on this widget type, see Section
\ref{sec:edit}.
\begin{haskellcode}
ui <- centered e
\end{haskellcode}
This creates a new \fw{Centered} widget, \fw{ui}, which centers the
\fw{Edit} widget vertically and horizontally. This is a common
pattern: create one widget and wrap it in another to affect its
behavior. For more information on the \fw{Centered} widget type, see
Section \ref{sec:centering}.
\begin{haskellcode}
fg <- newFocusGroup
\end{haskellcode}
This creates a \fw{FocusGroup} widget. A ``focus group'' is an
ordered sequence of widgets that will receive focus as you cycle
between them. By default, this cycling is done with the \fw{Tab} key.
Every \vtyui\ interface requires a focus group.
\begin{haskellcode}
addToFocusGroup fg e
\end{haskellcode}
This adds the \fw{Edit} widget to the \fw{FocusGroup}. The first
widget to be added to a \fw{Focus\-Group} automatically receives the
initial focus, and widgets receive focus in the order in which they
are added to the group.
\begin{haskellcode}
c <- newCollection
\end{haskellcode}
This creates a new \fw{Collection}. A ``collection'' is group of
widgets, each with its own \fw{FocusGroup}, and the \fw{Collection}
makes it possible to switch between these interfaces. Think of an
e-mail client whose initial interface might be listing the contents of
the inbox; subsequent interactions might change the interface to
present only the selected message on the screen, with different
navigation keystrokes, one of which returns to the inbox interface.
\fw{Collection}s make it easy to switch between such interface modes.
Every \vtyui\ program requires a \fw{Collection}.
\begin{haskellcode}
addToCollection ui fg
\end{haskellcode}
This adds the top-level user interface widget, \fw{ui}, to the
\fw{Collection} and sets its focus group to \fw{fg}. This means that
the widgets to receive the user’s focus (and, consequently, input)
will be those in the focus group \fw{fg} and the interface to be
presented will be \fw{ui}.
\begin{haskellcode}
e `onActivate` \this -> getEditText this >>=
(error . ("You entered: " ++))
\end{haskellcode}
This binds an event handler to the ``activation'' of the \fw{Edit}
widget. Activation occurs when the user focuses the \fw{Edit} widget
and presses \fw{Enter}. The handler for this event is an \fw{IO}
action which takes the \fw{Edit} widget itself as its only parameter.
The \fw{getEditText} function gets the current text of the \fw{Edit}
widget, and we use \fw{error} to abort the program and print the text.
\begin{haskellcode}
runUi c defaultContext
\end{haskellcode}
This runs the main \vtyui\ event loop with the \fw{Collection} we
created above. We pass a ``default rendering context'' which provides
defaults for the rendering process, such as the default foreground and
background colors to be used for normal and focused widgets, as well
as a “skin” for line-drawing. The main event loop processes input
events from the Vty library and re-draws the interface after calling
any event handlers. It also shuts down Vty in the event of an
exception.
We've now seen the general structure of a \vtyui\ program:
\begin{itemize}
\item Create and compose widgets,
\item Create a \fw{FocusGroup} and add input-receiving widgets to the
group,
\item Create a \fw{Collection} and add the top-level widget(s) and
\fw{FocusGroup}(s) to the \fw{Collection}, and
\item Invoke the main event loop with the \fw{Collection} and some
default rendering settings.
\end{itemize}