Tuesday, June 3, 2014

CPTableView: A Practical Review of Concept, Not a Step-by-Step Tutorial

I have tried many resources to CPTableView.  It was not until I saw Connor Denman's work and his accompanied YouTube video that I really got started with this object.  Sadly, even Connor's review, while it got me started, left me wanting for something more.  Hopefully, here, we can provide a comprehensive review of tables that will get you and your project off the ground running.

Here, we will go over the concepts, and in a later article, I will take you through the table views again with a step-by-step exercise and tutorial.

Using Table View Without a Container

CPTableView can be used without a CPScrollView or CPClipView container.  However, I have not found a way to display the column headings by this method.  The result is a flat image in your web layout that appears out of place.  If, at a future point, I figure out how to get column headers to display, I will revise this section.  But until then, we will use a CPScrollView object as a container.

Important Differences from NSTableView

Apple, Inc. provides an excellent review of NSTableView.  However, the review has two big problems.  The first problem is that the review is heavily dependent on using XCode to build the graphic elements, and in this blog, we need a deeper understanding of how to build views manually.  Secondly, there are some major differences between the structure and behavior of NSTableView and the CPTableView corollary.

Visual aid provided by Apple, Inc. in NSTableView overview.
In the graphic provided by Apple, we see that the NSTableView object contains within it NSTableViewRow objects, and within those row objects are NSTableCellView objects, which define the individual cells.  Cappuccino has no CPTableViewRow object.  This in and of itself breaks down the relationship between what one can learn in the Objective-C documentation, which is our backup documentation when Cappuccino documentation is lacking.

The Structure of CPTableView as Displayed in a CPScrollView

For our review of CPTableView structure, we will consider it from the viewpoint of CPScrollView as our frame of reference, because CPScrollView and CPClipView each have internal methods which make the display of column headers much easier.

Loose conceptual view of the structure
Above is a rudimentary graphic showing a "loose" conceptual view of the CPTableView hierarchy. I note that it is "loose" because it does not include all view objects.  For example, the horizontal and vertical scroll bars of CPScrollView, which are placed next to the CPClipView that holds the CPScrollView's client.  I coin it a "conceptual" view, because the CPTableViewColumn is not actually displayed as a consistant and full view; it is broken between the header and the dataView cells.

We create our table view by nesting the table view in a scroll view.  The scroll view creates the clip view automatically and sets the table view into the clip view as a Subview.  In my early trials, I could not figure out why the table was offset from the header, as it turns out, I created my table view with an origin of (20, 20), which it was measuring from the top left corner of the clip view.  Once I cleared the origin and defined it as (0,0), everything lined back up again.

To the table view, we assign a data source, and a series of columns with unique identifiers. The table view calls a method of the data source and asks: "For this column and this row number, which data object should I display?".  The table also asks the column for a dataView object and a header, it places the header in the corresponding location in the header view, and creates a new instance of the dataView, to which it adds the object from the dataSource.

Interaction Diagram prepared with MagicDraw PE
The resolution is grainy, but the general process is described in the interaction diagram above.  The table view queries the column, the data source and the data view in regular succession as it places each and every cell within the table.  The table view calculates where to place each cell.  The column provides either a default or your custom view for displaying the value, the data source provides the data object for that specific column and row, and the table then inserts that object into the provided data view while setting the cells location on the page.  The scroll view and clip views which contain this table then handle any clipping that is necessary in order to make the content fit on the page and enabling scroll bars as necessary to move the scroll's view over the clipped content area.

Requirements of Custom Objects

Once we understand how the view constructs each of the elements, it becomes much simpler to start constructing our own custom views and customized dataSource elements as well as dataView elements.  We will cover this in detail in the tutorial that follows.

In summary, it is essential that every data source be able to respond to at least two functions, at a minimum.  Those functions are:
 -(int)numberOfRowsInTableView:(CPTableView)aTable
 -(id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)rowIndex

Similarly, it is essential that every custom cell (dataView) be able to respond to just one function:
-(void)setObjectValue:(id)aValue

If your dataView is able to handle that function, and it is a subclass of CPView, using it is as simple as passing an instance of that view to the column that will use it as a display by calling -(void)setDisplayView:(CPView)aView on the CPTableViewColumn instance.  CPTableViewColumn then does the work of generalizing the view so that it new instances can be created on demand when requested by the tableView.

Tutorial

In the upcoming days, I will post a tutorial which allows us to play with the CPTableView and its various components.  We will use a default dataView to display a simple array of strings as Connor Denman had done in his example.  Then we will go beyond that rudimentary example and play with customized dataViews and dataElements that are more complex objects.  All-in-all, I hope to provide a sufficient foundation to launch you forward in your Cappuccino development and your understanding of the visual structure of this beautiful system.

No comments:

Post a Comment