% \VignetteIndexEntry{The gWidgets2 package}
% \VignetteDepends{gWidgets2, gWidgets2RGtk2}
% \VignetteKeywords{foreign interface, GUI}
% \VignettePackage{gWidgets2}

\documentclass[12pt]{article}

\usepackage{times}              % for fonts
\usepackage[]{geometry}
\usepackage{mathptm}            % for math fonts type 1
\usepackage{graphicx}           % for graphics files
\usepackage{amsmath}            % for amslatex stuff
\usepackage{amsfonts}           % for amsfonts
\usepackage{url}                % for \url,
\usepackage{hyperref}
\usepackage{color}
\usepackage{booktabs}
\renewcommand\topfraction{.9}
\renewcommand\bottomfraction{.9}
\renewcommand\textfraction{.1}
\setcounter{totalnumber}{50}
\setcounter{topnumber}{50}
\setcounter{bottomnumber}{50}

%% My abbreviations
\newcommand{\pkg}[1]{\textbf{#1}}
\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\proglang}[1]{{\textsf{#1}}}
\newcommand{\kbd}[1]{\textsf{#1}}
\newcommand{\R}{\proglang{R}}
\newcommand{\ASSIGN}{$<$-}


%%\SweaveOpts{keep.source=TRUE}

\title{The gWidgets2 package}
\author{John Verzani}
\date{\today}

<<setup1, echo=FALSE>>=
options(replace.assign=TRUE)
options(width=80)

opts_chunk$set(tidy=FALSE,
               highlight=TRUE,  
               #fig.width=5, fig.height=5,
               fig.show='hold', cache=FALSE, par=TRUE) 
knit_hooks$set(par=function(before, options, envir){
if (before && options$fig.show!='none') 
  par(mar=c(5,4,2,2) + 0.1, #c(4,4,.1,.1),
      cex.lab=.95,cex.axis=.9
      ,mgp=c(2,.7,0),tcl=-.3
                )
}, crop=hook_pdfcrop)

@ 
\begin{document}

<<setup, echo=FALSE, results="hide">>=
options(width=72)
##options(prompt='  ',continue='  ')  # remove prompt characters at start of lines
@ 



\maketitle



%% intro
The \pkg{gWidgets2} provides a programming interface for writing
graphical user interfaces within \R. The package depends on one of
several different interfaces to underlying toolkit libraries:
\proglang{tcltk}, \proglang{RGtk2}, or \proglang{Qt}.~\footnote{A
  related -- but independent -- package, \pkg{gWidgetsWWW2}, provides an interface for
  programming web GUIs.} The package provides many of the common
features of the above toolkits using more or less standard \R\/
idioms, making it fairly easy for the \R\/ user to quickly begin
building user interfaces.

The \pkg{gWidgets2} package is a rewrite of the \pkg{gWidgets}
package.~\footnote{The \pkg{gWidgets} package is documented in a 2007
  \textit{R News} article ``An Introduction to {gWidgets}'' and the
  book \textit{Programming Graphical User Interfaces in R}, by
  Lawrence and Verzani, CRC Press.} Most changes are not visible to
the end user, but there were significant enough ones that the package
name was changed. The goals of the rewrite included:
\begin{itemize}
\item simplifying of the code base using the powerful combination of
  \pkg{devtools} and GitHub (\url{github.com/jverzani}) making it much
  easier to document, test, and deploy changes in the underlying
  packages;
\item replacing S4 methods with reference class methods resulting in a
  cleaner code base;
\item better consistency across toolkits;
\item speed improvements; and
\item better documentation.
\end{itemize}

For the most part this has been achieved. Most \pkg{gWidgets} scripts
run unchanged, save for, perhaps, a few minor adjustments. Some others
will be problematic. (To make more cross-toolkit, some of the drag and
drop features of \pkg{gWidgetsRGtk2} have been dropped.)


As with the original package, \pkg{gWidgets2} provides the abstract
interface. A toolkit package (one of \pkg{gWidgets2RGtk2},
\pkg{gWidgets2tcltk}, \pkg{gWidgets2Qt}) provides the link to the
underlying \R{} toolkit that binds to the graphical
toolkit. Typically, the only issues with installation arise from the
underlying toolkits, which often require separate
downloads.~\footnote{Well, not always. The \pkg{tcltk} is a base
  package and the underlying libraries are usually available, the
  \pkg{RGtk2} and \pkg{Qt} packages make an effort to install the
  underlying libraries.}  The \pkg{devtools} package's
\code{install\_github} function can be used to install the development
versions from GitHub.


\begin{figure}
  \centering
  \includegraphics[width=.3\textwidth]{rgtk2-t-test.png} \quad
  \includegraphics[width=.3\textwidth]{tcltk-t-test.png} \quad
  \includegraphics[width=.3\textwidth]{qtbase-t-test.png}
  \caption{Screenshots of the same \pkg{gWidgets2} GUI using \proglang{RGtk2}, \proglang{tcltk}, and \proglang{qtbase}.}
  \label{fig:screenshots-t-test}
\end{figure}



%% Basic example
\section{Requisite ``Hello World'' example}

We begin with a simple example to illustrate what a script looks like:
<<hello_world, results="hide">>=
library(gWidgets2)
options(guiToolkit="RGtk2")
## containers
win <- gwindow("Basic example", visible=FALSE)
gp <- gvbox(container=win)
## control
btn <- gbutton("click me for a message", container=gp)
## interactivity
addHandlerClicked(btn, handler=function(h,...) {
  galert("Hello world!", parent = win)  # a dialog call
})
## a method call
visible(win) <- TRUE
@ 
%%
The above will produce a titled window with a button. When the user
clicks the button, a dialog will appear with a very important message.

The first two lines load the package and force the choice of
toolkit. If the second line is not given, the user is prompted for a
toolkit choice, as needed.

The structure of programming in \pkg{gWidgets2} is mostly illustrated
above. The basic components -- containers, controls, and dialogs -- are defined by
constructors. In the above we see the window constructor
(\code{gwindow}), a vertical box container constructor (\code{gvbox}), a button
widget constructor (\code{gbutton}) and a dialog constructor (\code{galert}).



The top level window constructor has two arguments specified, one for
the title, the other to suppress the initial drawing. The latter allows the
toolkit to compute the requested size before drawing, which can make
the initial appearance seem faster.

The box container and button constructors have the argument
\code{container}. This is used to define the widget hierarchy and
layout of the GUI. The dialog has the similar \code{parent}
argument. This argument does not imply the child is rendered within
the parent, as \code{container} does, but rather indicates a
relationship. In this case, the alert dialog will be drawn relative to
the parent window.

Except for dialogs, the constructors return objects which have S3
methods defined for them. Table~\ref{tab:methods} lists most of the
new generics defined by the package.~\footnote{Constructors return
  reference class objects, so they also have reference class methods
  defined. There are a few cases where these are standardized across
  toolkits, for example, the \code{set\_borderwidth} argument for box
  containers. Otherwise, though the reference class methods may be
  used directly, doing so will often break portability of the code to
  other toolkits.}. The last line shows the \code{visible} assignment
method. For top-level windows, this can be used to either hide or make
the window visible. The most common method is \code{svalue}, which is
defined to return or set the most basic property of a widget.

The interactivity of \pkg{gWidgets2}'s GUIs is introduced by event
handlers. Handlers for the most common event can be assigned during
the construction of the object, but more commonly handlers are done
after the layout of the GUI is finished, as above.



The above handler simply calls the \code{galert} dialog to create a
transient message.


There are other examples available in the demos for the toolkit
packages, e.g., \code{demo("gWidgets2RGtk2")}.

\begin{table}
  \centering
  \begin{tabular}{@{}l@{\quad}l@{}}
    \toprule
    Method & Description\\
    \midrule
    \code{svalue\ASSIGN} & set main property\\
    \code{enabled\ASSIGN} & adjust if widget is sensitive to user input\\
    \code{visible\ASSIGN} & adjust ``visibility'' of widget\\
    \code{focus\ASSIGN} & give widget keyboard focus\\
    \code{editable\ASSIGN} & adjust if widget can be edited\\
    \code{font\ASSIGN} & adjust font of widget\\
    \code{tab\ASSIGN} & store property in widget's environment\\
    \code{size\ASSIGN} & adjust size of widget\\
    \code{tooltip\ASSIGN} & add tooltip to widget\\
    \code{dispose} & dispose of widget or part of widget\\
    \code{delete} & delete child from parent container\\
    \bottomrule
  \end{tabular}
  \caption{Generic methods defined in the \pkg{gWidgets2}
    package to manipulate the state of the GUI objects. Most
    ``setters'' have
    corresponding ``getter'' versions.}
  \label{tab:methods}
\end{table}





\section{Overview}
\label{sec:overview}

The basic example above shows the main areas of \pkg{gWidgets2}. Here we
give a bit more detail.


\subsection{Containers}
\label{sec:containers}

A GUI is laid out by nesting child components within containers, which
in turn may be nested within other containers. All the children sit
within some top-level window. In \pkg{gWidgets2}, top-level windows are
constructed with \code{gwindow}.

The most basic containers are the ``box containers,'' \code{ggroup}
(and its shortcut \code{gvbox}), \code{gframe}, and
\code{gexpandgroup}). Box containers pack in their child components
from left to right or top to bottom. The packing of each child can be
adjusted through specifications of \code{expand} (to have the
allocated space grow if the window size grows), \code{fill} (to have
the child widget grow to fill the allocated space), or \code{anchor}
(to align the child widget within the allocated space). The spacing
between children is controlled by the main property and border
spacing, by the aforementioned reference class method \code{add\_borderwidth}.

Other containers are
\begin{description}
\item[glayout] A grid layout container
\item[gformlayout] A special case of a grid layout container for
  quickly building up forms.
\item[gpanedgroup] A container to hold two children, separated by a
  sash. This is used to allow the user to allocate the allotted space.
\item[gnotebook]  A notebook widget uses tabs to organized different
  ``pages'' from which the user can easily select.
\item[gstackwidget] Like \code{gnotebook}, though no tabs are
  presented so selection is done programmatically.
\item[gbasicdialog] A dialog that can be used to create a modal window
\end{description}


The containers can be nested to build up a hierarchy. This examples
shows how nested groups can be used to create a button group at the
bottom of a page:

<<nested_container, results="hide">>=
## Some filler
lorem <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
##
win <- gwindow("Nested groups")
g <- gvbox(container=win)
g$set_borderwidth(10L)
##
txt <- gtext(lorem, container=g,        # text widget
             expand=TRUE, fill=TRUE) 
##
bg <- ggroup(cont=g)
addSpring(bg)
gbutton("dismiss", container=bg, 
        handler=function(h,...) dispose(win))
gbutton("about", container=bg, handler=function(h,...) {
  gmessage("Shows lorem ipsum text", parent=win)
})
@ 

In the above, we have nested box containers, \code{g} a vertical one,
and \code{bg} a horizontal one. (The \code{gvbox} call is a
simpler-to-type version of \code{ggroup} with
\code{horizontal=FALSE}.) The \code{set\_borderwidth} reference method
call is not essential, but does give some extra space around the edges
of \code{g}. The \code{svalue} method is used to set padding between
children, this call sets the border within the box. The spring is
added to \code{bg} container to right justify the buttons. When
buttons are packed into box containers, they expand to fill the
direction orthogonal to the direction of packing. As such, it is best
to put buttons in a horizontal box container, as done above.


\subsection{Widgets}
\label{sec:widgets}

Containers are needed for organizing the GUI, but more important are
the controls that allow the user to enter information into a GUI or
get information out of a GUI.

A summary of the basic controls is given in Table~\ref{tab:basic-controls}.

\begin{table}
  \centering
\begin{tabular}{@{}l@{\quad}l@{\quad}l@{}}
  \toprule
  Type   & Constructor & Description\\
  \midrule
  labels & \code{glabel} & label widget\\
         & \code{gstatusbar} & messages in page bottom\\
         & \code{galert} & transient messages\\
         & \code{ghtml} & if supported (\code{Qt})\\
  action & \code{gbutton} & button action\\
         & \code{gmenu} & menu bar and popup menus\\
         & \code{gtoolbar} & tool bar\\
  selection & \code{gcheckbox} & Boolean\\
         & \code{gradio} & one of many\\
         & \code{gcheckboxgroup} & one or more of many\\
         & \code{gcombobox} & one of many\\
         & \code{gtable} & one, or one or more of many\\
         & \code{gslider} & slide to select from range\\
         & \code{gspinbutton} & click to select from range\\
         & \code{gcalendar} & select date\\
         & \code{gfilebrowse} & select file, directory\\
  Text   & \code{gedit} & single line text\\
         & \code{gtext} & multi line text\\
  Data   & \code{gtable} & select from rectangular data\\
         & \code{gtree} & select from hierarchical data\\
         & \code{gdf} & edit a data frame\\
  Graphics & \code{ggraphics} & graphic device\\
         & \code{gimage} & image file display\\
         \bottomrule
\end{tabular}
  
  \caption{List of basic controls in \pkg{gWidgets2}}
  \label{tab:basic-controls}
\end{table}


The basic use is straightforward. A widget has some data that is
needed to configure it, and most widgets have common arguments to
specify the parent container (\code{container}) and a handler for the
most common event (\code{handler}, which just maps to \code{addHandlerChanged}).

The following example shows a GUI that could be used to collect
arguments for a $t$-test (Figure~\ref{fig:screenshots-t-test}).  We
use the convenient \code{gformlayout} container, new to \pkg{gWidgets2}.

<<gformlayout_example, results="hide">>=
win <- gwindow("t-test", visible=FALSE)
g <- gvbox(container=win)
g$set_borderwidth(10L)
##
flyt <- gformlayout(container=g, expand=TRUE)
## 
gedit("", initial.msg="variable", 
      label="x", container=flyt)
gcombobox(c("two.sided", "less", "greater"), 
          label="alternative", container=flyt)
gedit("0", coerce.with=as.numeric,  
      label="mu", container=flyt)
gcheckbox("", checked=FALSE, 
          label="paired", container=flyt)
gslider(from=0.5, to = 1.0, by=.01, value=0.95, 
        label="conf.level",  container=flyt)
##
bg <- ggroup(container=g)
addSpring(bg)
gbutton("values...", container=bg, handler=function(h,...) {
  print(svalue(flyt))                   # replace me...
})
addSpring(g)                            # better for Qt
##
size(win) <- c(400, 250)
visible(win) <- TRUE
@ 
%%
We see that some arguments are specific to the widget. For example,
\code{initial.msg} to use an initial message for \code{gedit};
\code{coerce.with} to specify a function to coerce a character string
for \code{gedit} (and others) or \code{checked} to set the initial
state for \code{gcheckbox}.

The \code{expand} argument and \code{label} argument do not belong to
the widget constructor, but are passed through \code{...} to the
\code{add} method for \code{ggroup} and \code{gformlayout}. These
control how the child is laid out within the parent container. For
\code{gformlayout}, the \code{label} argument also names the value
returned by its \code{svalue} method.

The above, is just the part of the GUI that collects the user input. One
would need to write something intelligent to do with the
values. Though, if the labels are chosen well, this can be as simple
as using something like \code{do.call(FUN,
  svalue(form\_layout\_object))}.




\subsection{Event handlers}
\label{sec:event-handlers}

GUIs become interactive through the use of event handlers. The basic
idea being the user initiates an event through a control, the control
then emits a signal, and any listeners for the signal are called. In
\pkg{gWidgets2} there are various ``\code{addHandlerXXX}'' methods to
attach a callback (a handler) for different events a widget may
signal. The most basic event is bound to through
\code{addHandlerChanged}, which for many widgets is an alias for a
more aptly named event. (For example, \code{addHandlerClicked} for the
button widget.) Most others are listed in
Table~\ref{tab:event-methods} (though some are not, such as the
different ones for column clicks in the table widgets).

The callbacks all have the same signature, \code{(h, ...)}.  The main
argument is \code{h}, a list with components \code{obj} to refer to
the emitter of the signal and \code{action}, an optional user-supplied
value to parameterize the callback. Some events pass back more
information. For example, the keystroke handler passes back key
information through \code{h}.  The \code{...} values are used by some
toolkits to pass back information given by the toolkit about the
signal. This may be of interest to some, but using it breaks
portability of \pkg{gWidgets2} code across toolkits.

\begin{table}
  \centering
  \begin{tabular}{l@{\quad}l}
    \toprule
    Method & Description\\
    \midrule
    \code{addHandlerChanged} & most typical event\\
    \code{addHandlerClicked} & click event\\
    \code{addHandlerDoubleclick} & double-click event\\
    \code{addHandlerSelect} & Select or activate event (typically the
    change event)\\
    \code{addHandlerSelectionChanged} & Selection changes \\
    \code{addHandlerFocus} & widget gets keyboard focus\\
    \code{addHandlerBlur} & widget loses keyboard focus\\
    \code{addHandlerKeystroke} & text widget has keystroke \\
    \code{addHandler} & add callback for toolkit signal\\
  \end{tabular}
  \caption{Methods to bind callbacks to events in \pkg{gWidgets2}}
  \label{tab:event-methods}
\end{table}


The \code{addHandlerXXX} methods return an ID that can be used to
disconnect the callback or temporarily block the callback. See the
help pages for \code{removeHandler}, \code{blockHandler}, and
\code{unblockHandler}. All events can be removed or temporarily
blocked through \code{removeHandlers}, \code{blockHandlers}, and
\code{unblockHandlers}.



A simple example of using a handler might be to have the sensitivity of a
button depend on whether a user has made a selection:

<<pick_your_race, results="hide">>=
win <- gwindow("handler example", visible=FALSE)
g <- gvbox(container=win)
f <- gframe("Ethnicity", container=g)
cb <- gcheckboxgroup(c("White", 
                  "American Indian and Alaska Native", 
                  "Asian", 
                  "Black or African American", 
                  "Native Hawaiian and Other Pacific Islander"),
                container=f)
bg <- ggroup(cont=g); addSpring(bg)
b <- gbutton("Go", container=bg)
enabled(b) <- FALSE
##
addHandlerChanged(cb, handler=function(h,...) {
  enabled(b) <- length(svalue(h$obj)) > 0
})
##
visible(win) <- TRUE
@ 
%%

\subsection{Dialogs}
\label{sec:dialogs}

The package provides a few modal dialogs: useful and familiar means to
display or collect information. These include:
\begin{description}
\item[gmessage] present a modal message
\item[galert] present a non-modal, transient message
\item[gconfirm] allows user to confirm an action to be taken
\item[ginput] collect single line of text input from user
\item[gbasicdialog] container to hold modal dialog
\item[gfile] Select a file 
\end{description}

Modal dialogs disrupt the flow of a user's interaction through a GUI,
so are used sparingly. This also prevents them from returning a
meaningful object to manipulate, as this can only happen after the
dialog is closed. As such, they return values, such as a Boolean for
\code{gconfirm} and the text value for \code{ginput}.


This example asks for confirmation before removing an object:

<<remove, eval=FALSE>>=
if(gconfirm(c("Remove x", "this can't be undone")))
  rm("x")
@ 
%%


\section{Some more examples}
\label{sec:some-more-examples}


\subsection{Selecting packages to load/unload}
\label{sec:select-pack-load}


This example creates a GUI to load or unload a package. The main
interface uses \code{gcheckboxgroup} for the selection of none, one or more
from many. The argument \code{use.table=TRUE} is specified to use a
layout with checkboxes, as otherwise scrollbars will not be provided
and long lists need a lot of vertical or horizontal screen space.

We begin with some text to explain the GUI.
<<about>>=
about <- "
A simple GUI to simplify the loading and unloading of packages.
This GUI uses `gcheckboxgroup`, with its `use.table` argument, to
present the user with familiar checkboxes to indicate selection.
Some indexing jujitsu is needed to pull out which value is checked to
trigger the event.
"
@ 


The function \code{installed.packages} will search a users
installation for all installed packages. This call can be slow, so we
store the results here as a global variable. In a more complicated
setup, one would use a property, say, of a reference class to avoid
name collision.

<<installed>>=
installed <- installed.packages() ## matrix
installed_packages <- installed[, "Package"]
@ 
%%

This helper function checks the loaded namespaces against the installed
packages to determine what is loaded.
<<>>=
package_status <- function() {
  ## Return if package is loaded
  installed_packages %in% loadedNamespaces()
}
@ 

We begin with our main layout. Here is a common idiom -- creating a
top-level window with a box container to hold child components. The
\code{set\_borderwidth} reference method is used to give a little
breathing room.
<<>>=
w <- gwindow("package manager", visible=FALSE)
g <- gvbox(cont=w)
g$set_borderwidth(10L)
@ 
%

We use the checkbox group to show the data. The items to select
from are specified first, then the \code{checked} argument is fed a
logical variable to indicate what should be initially checked. We use
the \code{expand=TRUE} argument here tso that the widget gets the
maximum space possible, should the window be resized.
<<>>=
a <- package_status()
tbl <- gcheckboxgroup(installed_packages, checked=package_status(),
                      use.table=TRUE,
                      expand=TRUE, container=g)
@ 
%%

The following is a standard idiom to create a button group. This
button simply shows the information defined above in \code{about}. The
specification of \code{parent=w} below makes the window \code{w1}
transient for the toplevel window \code{w}. That means, should
\code{w} be closed first, \code{w1} will also close and further, the
initial positioning of \code{w1} depends on that of \code{w}.
<<>>=
bg <- ggroup(cont=g)
addSpring(bg)
gbutton("About", container=bg, handler=function(...) {
  w1 <- gwindow("About", parent=w, visible=FALSE)
  g <- gvbox(container=w1); g$set_borderwidth(10)
  glabel(about, container=g, expand=TRUE)
  gseparator(container=g)
  bg <- ggroup(cont=g)
  addSpring(bg)
  gbutton("dismiss", cont=bg, handler=function(h,...) {
    dispose(w1)
  })
  visible(w1) <- TRUE
})
@ 
%%
Finally, we make the toplevel window visible:
<<>>=
visible(w) <- TRUE
@ 

To add interactivity to our GUI we need some means to synchronize the
display of the table with the state of the loaded packages. Below, we
block all handlers before updating the selected values, as otherwise
this may trigger the change handler to be called.
<<>>=
update_tbl <- function(...) {
  blockHandlers(tbl)
  on.exit(unblockHandlers(tbl))
  
  svalue(tbl, index=TRUE) <- package_status()
}
@ 
%%

Finally, we add the handler that is called when the selected values
change. There is no means to get what checkbox actually triggered the
change, so we compute that from the selected values and the actual
installed packages. The \code{setdiff} function comes in handy
here. The basic flow of this handler is clear: check which value
changed. If it was a deletion, detach the package, otherwise load the
package. Afterwards, update the table.

<<>>=
addHandlerChanged(tbl, handler=function(h, ...) {
  ind <- svalue(h$obj, index=TRUE)
  old_ind <- which(package_status())

  if(length(x <- setdiff(old_ind, ind))) {
    message("detach ", installed_packages[x])
    pkg <- sprintf("package:%s", installed_packages[x])
    detach(pkg, unload=TRUE, character.only=TRUE)
  } else if (length(x <- setdiff(ind, old_ind))) {
    require(installed_packages[x], character.only=TRUE)
  }
  update_tbl()
})
@   
%%

One last comment, this GUI is similar to one in RStudio, but is not
nearly as nice as that. There, more information per line (a package
description and an ``uninstall package'' icon) is included. Though one
could add in a description here, say by pasting together different
text to display in the checkbox labels, it wouldn't be possible to
also add the uninstall feature. The package isn't as powerful as the
underlying toolkits, though as you can see the creation of this table
along with the interaction to retrieve and set its selected values is
really quite simple, especially when compared to what this takes with
some of the underlying toolkits.


\subsection{Using a table to display information}
\label{sec:using-table-display}

A basic feature of many GUIs is the use of tables to display
information. The \code{gtable} constructor creates an object that has
data frame methods that can be used to manipulate the object. For
example, \code{length}, \code{dim}, and \code{[}. As well, in this
example we see how the \code{visible} method can be used to assign
which rows are visible.

We begin by describing the GUI.
<<>>=
about <- "GUI to upgrade installed packages"
@ 

<<setCRAN>>=

@ 

The data to be displayed here is returned by \code{old.packages}, of
which we wish just 3 columns. Before calling that function, we
programmatically set a mirror. This bit can be skipped.
<<>>=
repos <- getOption("repos")
repos["CRAN"] <- "http://streaming.stat.iastate.edu/CRAN/"
options(repos = repos)
#
pkg <- old.packages()[,c("Package", "Installed", "ReposVer")]
@ 
%%

How we begin our basic GUI. First a top-level window:
<<>>=
w <- gwindow("Upgrade installed packages", visible=FALSE)
g <- gvbox(container=w)
g$set_borderwidth(10)
@ 

Our main interface consists of a \code{gedit} instance for the user to
filter the table by, and a \code{gtable} widget to dispaly our tabular data.
<<>>=

fg <- ggroup(container=g)
glabel("Filter by:", container=fg)
fltr <- gedit("", initial.msg="Filter by regexp", 
              container=fg)
tbl <- gtable(pkg, chosen.col=1, multiple=TRUE, 
              container=g, expand=TRUE)
@ 

Our button group is fairly standard. 
<<>>=
bg <- ggroup(container=g); addSpring(bg)
gbutton("About", container=bg, handler=function(h,...) {
  w1 <- gwindow("About", parent=w, visible=FALSE)
  g <- gvbox(container=w1); g$set_borderwidth(10)
  glabel(about, container=g, expand=TRUE)
  bg <- ggroup(container=g); addSpring(bg)
  gbutton("dismiss", container=bg, 
          handler=function(h,...) dispose(w1))
  visible(w1) <- TRUE
})
@ 


Our update button will only be enabled if the user has a selection,
hence we set it intially to be disabled. The handler below simply
installs the selected packages, then updates the display.
<<>>=
update_btn <- gbutton("Update selected", container=bg, 
                      handler=function(h,...) {
  pkgs <- svalue(tbl)
  if(length(pkgs) == 0) return()
  
  sapply(pkgs, install.packages)
  ## update pkg, update table, clear filter
  tbl[] <- pkg <<-  
    old.packages()[,c("Package", "Installed", "ReposVer")]
  svalue(fltr) <- ""
})
enabled(update_btn) <- FALSE
#
visible(w) <- TRUE
@ 

To enable filtering through the \code{gedit} widget, we connect to its
keystroke event a handler that uses \code{grepl} to see which packages
the user wishes to be displayed. The \code{visible} assignment method
makes this very easy to do.
<<>>=
addHandlerKeystroke(fltr, handler=function(h,...) {
  regexp <- svalue(h$obj)
  if(nchar(regexp) > 0 && regexp != "") {
    ind <- grepl(regexp, pkg[, 'Package'])
    visible(tbl) <- ind
  } else {
    visible(tbl) <- rep(TRUE, nrow(pkg))
  }
})
@ 

Finally, we adjust the update button to be enabled when there is a
selection. The \code{addHandlerSelectionChanged} method makes
listening for changes to the selection easy. The table widget also has
an \code{addHandlerChanged} method, which listens for when a use
activates an item, typically by double clicking or through the
\kbd{return} key.
<<>>=
addHandlerSelectionChanged(tbl, handler=function(h,...) {
  enabled(update_btn) <- length(svalue(h$obj))
})
@                   




\end{document}
