True Grid
Copyright © 1994-1995 by Apple Computer, Inc.  All rights reserved.
written by Bob Ebert

This sample illustrates 3 different techniques for drawing a "grid" or
table using your own code.  (No table protos are used.)  For each technique,
a "cached" version is also implemented.  The cached version creates visible
elements for each soup entry when the view is opened, so scrolling will
(presumably) be faster.  The uncached version creates only enough elements
to fill the screen, so opening will (presumably) be faster.

The parent view, True Grid, contains some scaffolding to call the
appropriate methods on each flavor of child, choose the flavor being tested,
and add and remove soup entries.  For each operation (opening, updating,
scrolling up/down) performance in two parts is measured, part 1 being time
to update, part 2 being time to draw on the screen.  Memory used is also
tracked.

The techniques are:  Columns, Drawn Rows, and so-called Simple rows.

SIMPLE ROWS:
This is the same technique as used in the checkbook.  A "row" consists of an
enclosing clView with one child clParagraphView for each column in the grid.

DRAWN ROWS:
Each row consistes of a single clView with graphics objects (shapes) used to
display the columns.

COLUMNS:
Each column is a single clParagraphView, the contents of which is a string
with carriage returns to place each element at the appropriate row.

Assumptions and rules (for all grid views):
     •	Grid views will not modify the main soup cursor.
     •	Grid views will not cause soup entries to stay in memory.
     •	Grid views will call inherited method :EntrySelected() with
     	soup entry that was tapped on.  Selection is implemented as in
     	:TrackHilite().  The entry will not be unhilited until after the
     	:EntrySelected() method has returned.
     •	Keys in the soup are unique.  (grid views can keep keys.)
     •	Grid views scroll in slightly less than 1 screenfull increments.
     	(The last entirely visible view will be at the top/bottom after
     	scrolling.)
     •	There will be at least 1 fully visible empty row at the end of each
     	grid view.  (If fewer than 1 screen of entries, entire screen must be
     	full of empty views.)
     •	Grid views respond to :SoupChanged() method.
     •	Grid views clean up any slots in them when they close.  (This is not
     	strictly necessary for this app, since the grid views are not
     	children, but it illustrates a clean programming style.)
     •	Grid views will look as similar as possible.  Dotted lines between
     	lines, and also between columns.
     •	Strings are left justified, integers are right justified, and dates
     	are cented justified.
     •  Maximize performance, minimize memory used.

Note, scrolling does not work correctly for all of the methods. The problem lies
in detecting how many items are left to show. A future version will address
this.
