vty-ui-1.8: doc/ch3/rendering.tex
\section{Rendering}
The \fw{render\_} function is responsible for generating a visual
representation of the widget based on various factors, including:
\begin{itemize}
\item The focus state of the widget
\item The available space specified by the \fw{size} parameter to the
\fw{render\_} function
\item The widget's own internal state in its \fw{state} field
\item All child widgets
\item Attributes stored in the widget as well as those provided in the
\fw{RenderContext}
\end{itemize}
This involves constructing \fw{Image}s using the Vty library's
primitives. Some primitives include:
\begin{itemize}
\item \fw{string} -- Creates an image from a string using the
specified attribute.
\item \fw{char} -- Creates an image from a character using the
specified attribute.
\item \fw{charFill} -- Creates an image with the specified width and
height, filled with the specified character and attribute.
\item \fw{<->} -- Vertical concatenation of images.
\item \fw{<|>} -- Horizontal concatenation of images.
\end{itemize}
While these functions should be sufficient to render most widgets, if
your widget wraps other widgets, you'll have to use the top-level
\fw{render} function provided by the \fw{Core} module. It has the
following type:
\begin{haskellcode}
render :: Widget a -> DisplayRegion -> RenderContext -> IO Image
\end{haskellcode}
This function looks a lot like the \fw{render\_} function in the
\fw{WidgetImpl} type, and that's intentional; the difference is that
\fw{render} \textit{calls} \fw{render\_} on the widget that is passed
to it, and it does some other important things:
\begin{itemize}
\item It gets the normal and focus attributes stored in the widget, if
any, and merges them into the \fw{RenderContext}. This means that
the \fw{render\_} function doesn't have to specifically look those
attributes up; it just needs to use whatever is in the context.
\item It invokes the \fw{render\_} function to get the resulting
\fw{Image}.
\item It measures the size of the resulting \fw{Image} against the
\fw{DisplayRegion} given to it and raises an exception (of type
\fw{RenderError}) if the image is too large.
\item If the size check passes, it calls \fw{setCurrentSize} on the
widget with the size of the generated \fw{Image}.
\end{itemize}
All of this book-keeping is vital to ensuring that the rendering
process works correctly; as a result, whenever you are rendering other
widgets inside your \fw{render\_} implementation, you \textit{must}
use \fw{render} to do it instead of extracting and calling the
\fw{render\_} function on your child widgets.