\documentclass{article}
\usepackage{times}

  \usepackage{rcs} \RCS $Revision: 1.1 $
%  \usepackage[dvips]{graphics}
%  \usepackage{url}
%  \newcommand{\draft}{\textsf{Draft \RCSRevision}}

\usepackage{amsthm}
\usepackage{url}
\usepackage{float}
\usepackage[pdftex]{graphicx}
\usepackage{palatino,epsfig,amsmath,amssymb,dcolumn}

\newenvironment{syntax}
{\list{Syntax:}{\topsep=6pt \itemindent-\leftmargin
\let\makelabel\descriptionlabel}\leftskip=2.25pc
\itemindent=-1.25pc\item}
{\endlist}

\graphicspath{{./images/}}   
\def\ci{\ttfamily\itshape}

\begin{document}
\pagestyle{empty}
\thispagestyle{empty}

\title{{\tt editTable}A Generic Display and Edit Widget for Database Applications}
\author{Clif Flynt\\
  Noumena Corporation,\\
  8888 Black Pine Ln,\\
  Whitmore Lake, MI 48189,\\
  \texttt{http://www.noucorp.com}\\
  \texttt{clif at noucorp dot com}}
\date{\today}
\maketitle
\pagestyle{empty}
\thispagestyle{empty}

\begin{abstract}
An application that includes a database always requires a set
of pages to edit the contents of the database.

The bulk of the edit pages are simple and easy to write.
Even with Tk's ease in constructing simple data-entry pagespages,
writing a dozen procedures takes time that could be spent on
the more interesting parts of a project.

The goal of the {\tt EditTables} package is to provide 
a set of good enough pages with no effort on the part of the
programmer, better pages with a bit of effort, and a framework
for building the fully featured pages an end user will demand.

The implementation uses TclOO for a base class with mixins to
provide customized behavior for particular database engines.  The
test engines are sqlite3 and TDBC.
\end{abstract}
			

\section{Introduction}

One application of the 80/20 rule is that 80 percent of an application is
the code that's boring to write, and 20 percent will be fun.  In a database
application with many data entry screens this ratio could push 95-5.

It would be nice if the 95 percent part of a database application could be 
generated without requiring 95 percent of the programmer's time.

It turns out that this can be done.

There is enough information in an SQL schema to create a simple entry
screen.  The following schema can be used to generate an
adequate GUI:
\newpage

\begin{verbatim}
    table create phoneList {
      id integer unique,
      name text,  -- person
      phone text, -- phone number
      type text -- home, work, mobile
    }
\end{verbatim}

The GUI would resemble:

\begin{figure}[H]
{\includegraphics[scale=0.7]{im1.png}}
\caption{Simple, uninstrumented GUI}
\end{figure}

By adding some extra information about the fields, the GUI can
be improved to resemble the following image:

\begin{figure}[H]
{\includegraphics{im2.png}}
\caption{Simple, instrumented GUI}
\end{figure}

To paraphrase many lolcats, {\it Simple tables are Simple}.  In order to be
useful, the {\tt EditTables} package needed handle one-to-one mapping
schemas, such those containing references to other tables.

\begin{verbatim}
  table create phoneList {
    id integer unique,
    name text,  
    num  text, 
    typeid integer references types 
  }
\end{verbatim}

\begin{figure}[H]
{\includegraphics{im3.png}}
\caption{Reference, instrumented GUI}
\end{figure}

The package also needs to handle many-to-one mapping, perhaps
a fixed number of fields as shown below:

\begin{verbatim}
table create person {
      id integer unique,
      name text,    
      address text, 
    }
  }
table create phone {
      id integer unique,
      num  text,
      personid integer references person,
      typeid integer references types
    }
\end{verbatim}

\begin{figure}[H]
{\includegraphics{im4.png}}
\caption{Reference to table, instrumented GUI}
\end{figure}

The trick to generating these sorts of GUI's instead of just a 
simple GUI from the pure schema requires adding some layout instructions.

The next requirement is to validate inputs.  This may need to be done on
a per-field basis, or when the user submits a page.  Both of these options
are supported in this package.

Finally, a useful package needs to work with multiple database back
ends.  It would be nice to only support TDBC, but in the real world, TDBC
doesn't have enough penetration (yet).

There are features in Tcl 8.6 that allow all of the requirements to be met.

The package is written using TclOO.  The base package understands
Tk and how an SQL schema is laid out.  It provides some primitives 
that the other classes can use to find a primary field, find references,
etc.  

If the project starts using the {\tt EditTable} package,  the layout
instructions can be embedded into the SQL schema and  extracted as
needed.  If {\tt EditTable} is being shoe-horned onto an existing
database, or if you find the idea of mixing layout commands and data
definitions distasteful, the instrumentation can be provided by 
modifying the method that acquires the layout commands in the Tcl 
object.

Validation is accomplished by adding flags to fields with some
common validation routines available in the main class, and the
capability of adding custom validation if an application requires it.

Finally, support for multiple database backends is accomplished using
TclOO's {\tt mixin} feature.

The current version of {\tt editTable} is the fourth or fifth iteration
of ideas.  It's being used in a commercial product.  It's also likely 
to see a number of modifications before it gets used in another
product.

\section{Using {\tt EditTable} package}
\subsection {Creation}

The {\tt EditTable} package is constructed using the TclOO 
megawidget design pattern described by Donal Fellows (Tcl/Tk Proceedings
2009) and in my book ({\tt Tcl/Tk: A Developer's Guide}, Chapter 11).  This
pattern emulates a standard Tcl widget, allowing the new {\tt editTable}
object to be created like any other Tk widget.

\begin{syntax}
{\tt editTable} {\ci widgetName mixin dbEngine args} \\
{\begin{tabular} {ll}\\
  {\ci widgetName} & {Name of the widget, normal Tk style} \\
  {\ci mixin} & {Name of the db engine mixin} \\
  {\ci dbEngine} & {Name of the db engine to use} \\
  {\ci args} & {Optional arguments for opening the db engine} \\
\end{tabular}}
\end{syntax}

Creating an {\tt editTable} connected to an SQLite database named
{\tt test.db} would resemble:

\begin{verbatim}
set obj [editTable .t1 SQLITE3_support sqlite3 -dbArgs test.db]
\end{verbatim}

Doing the same with a TDBC engine that's connected to the SQLite
database would resemble:

\begin{verbatim}
set obj [editTable .t1 TDBC_support sqlite3 test.db]
\end{verbatim}

Once an {\tt editTable} object has been created, it can be used to
query various parameters using the {\tt config} or {\tt configure}
commands (both map to the same underlying code.)

Like Tk, the {\tt configure} command will accept no arguments to
return all configuration options and values, a single argument
to report the value of an option, or a pair of arguments to set a 
value.

One of the options that can be extracted is the underlying
database pointer.  Extracting this allows an application to interact
directely with the database object opened by {\tt editTable}.  This
end-run functionality allows applications to easily extend the behavior
of the {\tt editTable} class.

The next snippet shows creating an {\tt editTable} object, extracting
the TDBC database object and using that to create a table in the
underlying sqlite3 database.

\begin{verbatim}
set obj [editTable .t1 TDBC_support sqlite3 test.db]
set db [$obj config db]
$db allrows {
  CREATE TABLE person (
    id integer unique primary key,
    loginid text, -- loginID 
    fname text, -- First name 
    lname text, -- Last name 
    addrRef integer references addr 
    );
}
\end{verbatim}

There are several methods defined for the {\tt editTable} object.  The 
most commonly used are:

\begin{itemize}
  \item {\ci editObj} {\tt config}
  \item {\ci editObj} {\tt getSchema}
  \item {\ci editObj} {\tt makeGUI}
  \item {\ci editObj} {\tt populateBySearch}
\end{itemize}

The config command will let the application query or set configuration
options.  If it is called with no key, it will return a list of 
all currently defined keys and values.
\begin{syntax}
{\tt editObj} {\ci config ?key? ?value?} \\
{\begin{tabular} {ll}\\
  {\ci editObj} & {A widget created with {\tt editTable} command} \\
  {\ci config} & {Query or set a config option } \\
  {\ci key} & {Name of the config option or blank} \\
  {\ci ?value?} & {Optional value to define an option} \\
\end{tabular}}
\end{syntax}

The {\tt getSchema} method will retrieve a schema for a 
table from the database, or optional schema retrieval process.  The
default behavior is to query the database.  This is used internally
to build GUIs for tables containing relations.

\begin{syntax}
{\tt editObj} {\ci getSchema tableName} \\
{\begin{tabular} {ll}\\
  {\ci editObj} & {A widget created with {\tt editTable} command} \\
  {\ci getSchema} & {Return the schema for a table} \\
  {\ci tableName} & {Name of the table to return Schema for} \\
\end{tabular}}
\end{syntax}

The {\tt makeGUI} method is the workhorse that builds a GUI within
the {\tt editTable} frame.  It can build a GUI for any table defined
within the database.  The {\tt editTable} object can rebuild itself
to display a different table as necessary.  The default GUI includes
buttons to perform simple searches, and add, delete or modify a record.

\begin{syntax}
{\tt editObj} {\ci makeGUI schema} \\
{\begin{tabular} {ll}\\
  {\ci editObj} & {A widget created with {\tt editTable} command} \\
  {\ci makeGUI} & {Construct a GUI within the editTable object frame.} \\
  {\ci schema} & {a Schema - may be return from {\tt getSchema}} \\
\end{tabular}}
\end{syntax}

The {\tt populateBySearch} method will load values into the fields
of a GUI.  The query can be any valid query suitable for an
SQL {\tt SELECT} on the currently active table.

\begin{syntax}
{\tt editObj} {\ci populateBySearch query} \\
{\begin{tabular} {ll}\\
  {\ci editObj} & {A widget created with {\tt editTable} command} \\
  {\ci populateBySearch} & {Populates the values in a GUI} \\
  {\ci query} & {An SQL query} \\
\end{tabular}}
\end{syntax}

The next example shows initializing a sample database and creating a
simple GUI for a table.

\begin{verbatim}
toplevel .tt
set obj [editTable .tt.t1 TDBC_support sqlite3 -dbArgs test2.db]
set db [$obj config db]

$db allrows {
  CREATE TABLE person (
    id integer unique primary key,
    loginid text, -- loginID
    fname text, -- First name
    lname text, -- Last name 
    addrRef integer references addr
    );
    CREATE TABLE addr (
    id integer unique primary key,
    street text, -- Address
    city text, -- Address  
    state text -- Address  
  )
}  
   
$db allrows {INSERT INTO addr VALUES (1, '123 St', 'Acity', 'AA')}
$db allrows {INSERT INTO addr VALUES (2, '234 St', 'Bcity', 'BB')}
$db allrows {INSERT INTO person VALUES (1, 'aaa', 'Alpha', 'Adam', 1)}
$db allrows {INSERT INTO person VALUES (2, 'bbb', 'Beta', 'Blocker', 2)}
$db allrows {INSERT INTO person VALUES (3, 'aa2', 'Abel', 'Adam', 2)}   
$db allrows {INSERT INTO person VALUES (4, 'aa3', 'Aard', 'Adam', 2)}   

$obj makeGUI [$obj getSchema person]
$obj config -table person
$obj populateBySearch "loginid = 'aaa'"

pack .tt.t1
\end{verbatim}

The generated GUI resembles this:

\begin{figure}[H]
{\includegraphics[scale=0.6]{im5.png}}
\caption{default GUI}
\end{figure}

\subsection {Layout Information}

Because we are polite and civilized, we will not call the previous
example butt-ugly.

But it is.

An SQL schema is designed to convey the logical date relationships
between fields and tables.  It is not designed to convey any
information about aesthetics.

The aesthetic information is conveyed as a six element list attached
to each field that is to be displayed.  The elements are shown in the
following list.  The first 2 are required, the others have default values
that may be adequate.

{\begin{tabular} {lp{20em}}\\
  {\tt help} & {A message to display in a popup help balloon} \\
  {\tt label} & {The label to display with this field} \\
  {\tt reference} & {If this field references another table, this element will contain the {\tt table.field} name of the referenced table.  If this field contains non-referential data, this element is blank.} \\
  {\tt widget arguments} & {arguments for the entry or combobox widget that will be created.  These might include {\tt -width} or {\tt -background} arguments.} \\
  {\tt row column} & {A list of the row and column where this field is to be displayed.} \\
  {\tt grid options} & {Arguments to be attached to a grid command for this field.  These might include {\tt -columnspan} for example.} \\
\end{tabular}}

This technique for conveying layout info is sub-optimal.  The
requirements grew as the complexity of the application grew.

But it works.

The layout information is included in a Schema by adopting a 
modification of the standard SQL comment.  

An instrumented schema has the layout string appended to a 
field definition with a triple-dash comment.

A simple GUI can be created like this:

\begin{verbatim}
set obj [editTable .t1 "" "" -table phoneList]

$obj makeGUI {
 table create phoneList (
 id integer unique,
 name text,  --- {First Last} {Name} {} {-width 40} {1 1} {-columnspan 2}
 num  text, --- {Number with area code} {Phone Number} {} {} {2 1}
 type text  --- {Type of phone} {Type} {} {} {2 2}
 );
}

grid .t1
\end{verbatim}

\begin{figure}[H]
{\includegraphics{im6.png}}
\caption{simple GUI with layout info}
\end{figure}

The {\tt editTable} widget requires that the SQL schema follow
strict rules and a field which references another table must include
a {\ci references} clause.  

The presence or absense of the {\ci references} clause determines how
the third field - the {\tt reference} element is to be treated.

If a {\ci references} clause is present, then the {\tt reference}
element contains the database field name, or list of field names, to
display in each element of a combobox.  The fields to display must be
named as {\tt tableName.fieldName}.

One pattern used with references is for a table to reference one of
several options.  The next example is a database in which the book table
has a string for title and a reference for author.  The author table
has separate fields for first and last name.  The combination of first
and last is displayed in the combobox for selecting an author.

\begin{verbatim}
set obj [editTable .book SQLITE3_support sqlite3 -dbArgs test4.db]
set db [$obj config db]

$db eval {
 CREATE TABLE book (
 id integer unique primary key,
 title text, --- {} {Title} {} {-width 40} {1 1} {-columnspan 2}
 authorid integer references author 
     --- {} {Author} {author.first author.last} {} {2 1}
 );

 CREATE TABLE author (
 id integer unique primary key,
 first text, --- {First Name} {First} {} 
 last text  --- {Last Name} {Last} {} 
 );
}

$db eval "INSERT INTO author VALUES (1, 'Clif', 'Flynt')"
$db eval "INSERT INTO author VALUES (2, 'Mark', 'Twain')"
$db eval "INSERT INTO book VALUES (1,'Tcl/Tk: A Developer''s Guide', 1)"
$db eval "INSERT INTO book VALUES (2,'Tom Sawyer', 2)"
$db eval "INSERT INTO book VALUES (3,'Huckleberry Finn', 2)"

$obj makeGUI [$obj getSchema book]
$obj config -table book
$obj populateBySearch "title like '%Tcl%'"
grid .book
\end{verbatim}

The GUI generated from this code looks like this:

\begin{figure}[H]
{\includegraphics{im7.png}}
\caption{Schema with reference and layout info}
\end{figure}

Another common pattern is the many-to-one mapping implemented
by having a field in one table point back to another table.  In
a book database, there are an undefined number of keywords that might
be attached to a book.

The schema for this pattern would resemble:

\begin{verbatim}
 CREATE TABLE book (
   id integer unique primary key,
   title text, 
 );
 CREATE TABLE keyword (
   id integer unique primary key,
   key text, 
   bookid integer references book 
 );
\end{verbatim}

To generate a GUI for this database pattern, the {\tt reference} 
element in the layout field in the {\tt keyword} table is used
to hold the name of a table.  When a GUI is generated for a
table listed in the {\tt reference} element, an {\ci Associated values}
section is created in the GUI.

Expanding the previous example to include a reference table, the
new table resembles this

\begin{verbatim}
 CREATE TABLE keyword (
   id integer unique primary key,
   key text, --- {Keyword} {Category} {book} {} {}
   bookid integer references book --- {book} {Title} {book.title} {} {}
 );
\end{verbatim}

Which creates the following GUI:

\begin{figure}[H]
{\includegraphics{im8.png}}
\caption{Schema with reference and layout info}
\end{figure}

The {\tt E} button in the previous image opens a new toplevel to
edit a keyword which will be associated with this table row.

\subsection {Customization}

The {\tt editTable} widget follows the Tk dictum of being
adequate with no tweaking, and open for customization if the
application isn't suited to the base GUI.

Various degrees of customization are supported.  These techniques
include:
\begin{itemize}
  \item using the layout elements 
  \item configuring options for screen or field validation
  \item building a separate mix-in or inherited class 
  \item tweaking the GUI before using it 
\end{itemize}

  Using layout elements to modify the appearance of the
GUI works as described.  

  By default, a {\tt editTable} GUI has no validation.  Per-Field
validation can be enabled by configuring the {\tt validate,}{\ci fieldName}
attributes for a GUI.  The validation attributes accept a script to
evaluate when focus leaves that field.  The widget name (entry or
combobox) and field name are appended to the script when it's invoked.

  The {\tt editTable} class includes some trivial validation methods
including {\tt validatePhone} and {\tt validateNumeric}.

\subsection {Extending the class}

The current implementation of {\tt editTable} has mixins for
Sqlite3 and TDBC.  A programmer can add a new mixin to support 
another database engine by coding the engine-specific methods:

{\begin{tabular} {lp{22em}}\\
  {\tt init } & {Initialize a connection to the database.} \\
  {\tt getSchema } & {Retrieve the schema for a given table.  Setting {\tt save} sets this to be the active table.)} \\
  {\tt doSQL } & {Execute an SQL command and return whatever the command returns.  This provides a generic access to the underlying database.} \\
  {\tt getTables} & {Return a list of the tables defined by this database.} \\
  {\tt getPrimary } & {Retrieve the name of the primary key.} \\
  {\tt doReplace} & {Update the DB row based on the contents of the GUI.} \\
  {\tt doNew} & {Create a new row in the DB based on the contents of the GUI.} \\
  {\tt populateBySearch } & {Populate the GUI based on an SQL  query.} \\
  {\tt getValues } & {Return a set of values based on a list of {\ci tableName.fieldName} values} \\
  {\tt getValueByRef } & {Returns a value from table 
    {\ci \$tbl} for field {\ci \$fld} where the primary is {\ci \$value}} \\
  {\tt populateWithFwdRef } & {Populate a GUI that includes forward references based on an SQL query} \\
  {\tt closeDB} & {Close the connection to the DB} \\
\end{tabular}}

\subsubsection {GUI Modification}

Since the GUI follows a fixed pattern, it can be modified post-{\tt makeGUI}
and before display.

For example, if users are only allowed to view and edit fields, 
the the delete button can be removed with a command like:

\begin{verbatim}
  $obj makeGUI $specialSchema noClose
  $obj configure -table book
\end{verbatim}

Getting more aggressive, rather than showing the {\ci Associated values} for
a row, as they are displayed by default, an application can define a fixed
quantity of associated values and a custom display procedure while taking
advantage of the bulk of the {\tt editTables} widget.

The next example demonstrates a book database that emulates a card
catalog via a slider on the side to select books, and a simplified
display of keywords.

It does this by with a special procedure to construct the GUI  and a
new procedure to extend the normal {\tt editTable} population methods.
The new procedure for creating the GUI ({\tt bldBookGUI}) defines a
modified schema with a couple extra fields to hold the keywords.  The
{\tt showItem} procedure uses the {\tt populateBySearch} method to
populate the fields that are defined in the {\tt book} schema, and
has extra code to populate the extra fields.

\begin{figure}[H]
{\includegraphics{im9.png}}
\caption{Schema with reference and layout info}
\end{figure}

\begin{verbatim}

toplevel .t3

set obj [editTable .t3.t2 SQLITE3_support sqlite3 -dbArgs test3.db]

proc bldBookGUI {obj} {
  set specialSchema {  
 CREATE TABLE book (   
   id integer unique primary key,
   title text, --- {Title} {Title} {} {-width 40} {1 1} {-columnspan 2}
   authorid integer references author, --- {Author} {Author} {author.first author.last} {} {2 1}
   keyword1 text --- {Keyword} {Keyword 1} {keyword.key} {} {3 1}
   keyword2 text --- {Keyword} {Keyword 2} {keyword.key} {} {3 2}
 );
  }
   
  $obj makeGUI $specialSchema noClose
  $obj configure -table book
  destroy $obj.buttons.b_Delete
  
  set prim [$obj getPrimary book]
  set count [$obj doSQL "SELECT count($prim) FROM book"]
  
  set scale [scale .t3.sc -from 0 -to $count \
      -command [list showItem $obj $specialSchema .t3.sc ]]
  grid $obj $scale
}
 
proc showItem {obj schema scale num} {
  $obj populateBySearch "id=$num"
  
  set pos 0
  foreach l [split $schema \n] {
    lassign [$obj splitSchemaLine $l] def layout
    lassign $layout help label ref args rowcol gridO
    if {($ref ne "") && ([string first "references" $l] < 0)} {
      set dfld [lindex $l 0]
      lassign [split $ref .] tbl fld
      set lst [$obj doSQL "SELECT $fld FROM $tbl WHERE bookid=$num"]
      set item [lindex $lst $pos]
      incr pos
      $obj configure -value,$dfld $item
      
    } 
     
  }  
}  
bldBookGUI $obj

\end{verbatim}

\section{Implementation}
  The {\tt editTable} widget is implemented as a TclOO Megawidget
with mixins to provide database engine customization.  

Another standard pattern would have been to make each database engine a
class that inherited the base functions from {\tt editTable}.  I
considered and discarded this pattern in order to have a single 
widget class ({\tt editTable}) rather than multiple classes ({\tt editSQLite},
{\tt editTDBC}, etc.).

The {\tt editTable} class uses the technique for creating a megawidget
described by Donal Fellows in his 2009 paper, and also described
in my book ({\tt Tcl/Tk: A Developer's Guide}, Chapter 11) (Shameless plug).

This technique uses a {\tt classmethod} call to create an {\tt unknown}
method that checks to see if the first argument is a window name, and if
so proceeds to create the new widget.

\begin{verbatim}
# Create a class method
# Avoid redefining classmethod if it already exists.
if {[info proc ::oo::define::classmethod] eq ""} {
proc ::oo::define::classmethod {name {args ""} {body ""}} {
   # Create the method on the class if the caller gave
   # arguments and body
   if {[llength [info level 0]] == 4} {
        uplevel 1 [list self method $name $args $body]
   }
   # Get the name of the class being defined
   set cls [lindex [info level -1] 1]
   # Make connection to private class "my" command by
   # forwarding
   uplevel forward $name [info object namespace $cls]::my $name
}
}

oo::class create editTable {
  classmethod unknown {w args} {
# puts "UNKL: $w -- $args"
    if {[string match .* $w]} {
      [self] new $w {*}$args
      return $w
    }
    next $w {*}$args
  }
...
}
\end{verbatim}

When a new instance is created, one of the arguments describes
the mixin to be added.  Since mixins don't have constructors, the
{\tt editTable} constructor calls a {\tt init} method defined within 
the mixin to perform special initializations.

The {\tt editTable} class can create objects that have lives of their
own.  These includes GUI widgets, open database connections and may
include slaved {\tt editTable} GUIs.  Because of these additional
elements to the {\tt editTable} class, the {\tt editTable} class
requires a destructor.

Each {\tt editTable} object contains a list of cloned and referenced
objects.  The {\tt desstructor} descends upon these like a wolf upon
the fold destroying them in gay abandon.

While the {\tt editTable} class is happy to have multiple channels to
databases, many database engines are less happy with this.  The {\tt init}
method in the mixins avoids opening multiple channels.  The {\tt editTable}
class must also avoid closing a database channel until all users have been
destroyed.

A class variable is used to keep track of the number of open database
connections.  Again, this code was stolen from Donal Fellows' 2009
talk and my book.

\begin{verbatim}
if {[info proc ::oo::Helpers::classvar] eq ""} {
proc ::oo::Helpers::classvar {args} {
    # Get reference to class’s namespace
    set ns [info object namespace [uplevel 1 {self class}]]
    # Double up the list of varnames
    foreach v $args {
      uplevel 1 namespace upvar $ns $v $v
    }
}
}  
\end{verbatim}

\section{Future}

The method of conveying the layout information, and what information
is required has been evolutionary.  It is subject to a rework before
the this package gets used in another application.

The schema parsing is a quick and dirty approach that assumes each
field definition is contained on a single line.  The schema parsing
will be enhanced as a method of the base {\tt editTable} class.

It may be possible to reduce the number of methods in the {\tt mixin}
classes by better use of the basic methods in the {\tt editTables} class.

\section{Summary} The current status of the {\tt editTable} class is
{\ci functional}.  It's in use in a commercial product and is scheduled
for a several other in-house and out-house projects.

What started as a simple way to generate a {\it good enough} GUI that
reflected the underlying database schema has expanded into a package
that can generate a commercial-grade GUI with capability of hiding the
schema and providing a simple interface to a user.

The underlying simple display has been retained with potential tweaks
to extend the behavior beyond simple.

As the class is force-fed to other applications I expect to discover
more things it {\it should} do, and streamline the current feature set.

The current escape is available at {\tt http://www.noucorp.com}.
\end{document}  %End of document.

