JClass HIGrid

PreviousNextIndex

1

JClass HiGrid Overview

Introduction  JClass HiGrid's Major Classes and Interfaces  Operations on Cells

The Data Model for JClass HiGrid  Internationalization


1.1 Introduction

JClass HiGrid provides your users with an intuitive structured visual representation of information retrieved from one or more databases. While a form with data bound fields is a one-record-at-a-time approach, JClass HiGrid lets you present your users with a hierarchically organized grid. The visibility of sub-levels is under the user's control, but it can be under programmatic control as well. Your design can include many sub-levels, resulting in an efficient concentration of information for tasks that require users to have many levels of detail available. Since you choose the detail records to be made available at every level, your design can be quite flexible and it can encompass many differing data retrieval needs. Not only can your users view the information, they can update it, add and delete rows-whatever you choose to permit.

Transaction processing is supported. If your application demands that some operations must be treated as a logical unit of work, the data source part of JClass HiGrid can (with your assistance, of course) execute the sequence as one atomic operation. If any one of the internal units fails to commit, all updates are rolled back and the database is left in its original state. Note that this is not an automatic recovery mechanism using log files, such as would be triggered by some type of system failure.

JClass HiGrid works with JDK 1.3.1 or later. It can contain hierarchical levels of information whose sub-tables the end-user can choose to show or hide dynamically at run time. The HiGrid can be contained in a resizable window, so the user has control over the size of the main level, and whether or not an individual detail level is showing.

1.1.1 The Relationship between JClass HiGrid and JClass DataSource

We'll take the simplest possible master-detail scenario to illustrate the way that the two products cooperate to present information extracted from a data source. We assume the existence of a database that contains a table called Orders. It contains the most frequently needed information about all the outstanding orders placed by every customer. Another table, called OrderDetails, contains additional information about these orders.

The entity-relationship diagram for this situation is shown below.

Figure 1 :  Entity-relationship diagram for a simple master-detail relationship.

In a master-detail scenario, one or more records of detailed information are displayed for each master record. In our example, the master records comes from the Orders table, while the detail records comes from the OrderDetails table. The database designer has already determined what type of information each of the tables contains, so you simply extract the pieces that you need in your application.

Meta Data

At this stage, you are working with the database's meta data. The meta data contains descriptive information about the tables, including the names of the data fields within each table and the SQL data types of each field. Each node in the entity-relationship diagram stores the MetaData of a given table in a simple tree-like structure called the MetaDataTree. The diagram shows that an OrderDetails sub-table will be created for each row of the Orders table, in order to show more detailed information about the specified order.

SQL Query

The exact contents of both the Orders and OrderDetails tables as displayed are determined by the SQL query used to retrieve the rows. A simple SQL query names the data fields of interest for a given table. A more complex SQL query adds a "WHERE" clause to restrict the number of records returned by the database. The SQL statement needed to construct an OrderDetails sub-table requires a WHERE clause that is able to select only the subset of records from the OrderDetails table within the database that is related to the master Orders record. This selection process is called a database "join." The join is usually accomplished by matching common fields within each table to each other. In this example, a field called OrderID will be used to construct an OrderDetails sub-table by selecting rows from the database's OrderDetails table where its OrderID field is the same as the OrderID field in the master Orders record.

At startup, the grid by default displays a single table called the root DataTable. The root DataTable is created by executing the SQL query associated with the MetaData node at the root of the MetaDataTree. In our example, the root DataTable will display the contents of the Orders table as the master records. Detail records, in the form of OrderDetails DataTables are exposed at run time by clicking on an expander icon, also called a folder icon, used for that purpose. As the user clicks on more expander icons, more DataTables are created. Thus, at run time, another tree-like structure called the DataTableTree is constructed, and it is composed of DataTables.

While there is a 1:1 relationship between Orders and OrderDetails in the meta data diagram, there is a 1:N relationship between the Orders DataTable and the OrderDetails DataTables associated with each row of the parent Orders. This occurs because any single order may consist of a number of items, each being described by an OrderDetails record. Both the grid and its underlying data source must be able to deal with structures of this type, and the more general type where the master-detail relationship forms an N-way tree.

Result Sets

Once the structure has been defined, and the SQL query has been formulated, the database can return data, called result sets, for the root-level table and for every one of the sub-tables. The queries that return sub-table result sets are performed as needed, when the grid needs to display them. It is the DataTable's job to store the result sets for later retrieval.

Visual Aspects of the Grid

Now that you can retrieve data in a hierarchical fashion, you may wish to control the visual aspects of the fields within the grid. For instance, you may want to adjust the size, color, or other visual property of the data fields. The following list illustrates those items that present information about the state of the grid and those that are under a user's control.

These are:

Clip Indicators

These small icons are present when the size of a cell is too small to display all of the text in it.

Column Moving

The initial position of a column is the same as the order in which they are mentioned in the database SELECT statement. End users can rearrange the order to suit themselves by dragging a column to a new position on the row.

Column Resizing

Columns may be resized by dragging on the right-hand border. The resizing operation affects all columns of the same type.

If you place a grid in an Applet, or flush in a frame, the right-hand column lies very close to the frame's border. This might make it difficult for end-users to position the mouse pointer on the column's resizing border. The setExtraWidth() method in HiGrid lets you set more space between the rightmost column's border and the frame's border.

Dynamic Headers

The header row disappears off the top of the viewing area when an end-user scrolls down a large table. A method in HiGrid, called setHeaderTipVisible(), lets you control the visibility of a special "tool tip" that exactly replicates the header row and places it in the row above the mouse pointer.

Edit Status Column

The Edit Status Column presents a visual indication that marks the current row, and a pencil icon marks rows that end users have changed by editing one or more cells.

 

You can control whether the edit status column appears. See the API documentation for EditStatusCellFormat.setShowing().

 

EditStatus is now a potentially replaceable public class. So is NodeRenderer, the class that draws the cell. To replace it, you need to extend JCImageCellRenderer and implement HiGridNodeRenderer. See Displaying and Editing Cells, in Chapter 4 for more details on JClass HiGrid's cell renderers.

Folder Icons

These icons present visual clues about the hierarchy of the data.

Indenting Subtables

Levels are indented by a fixed amount, if at all. Indentation is turned on or off using the setLevelIndent() method in HiGrid.

Popup Menu

A configurable popup menu gives end users access to frequently used commands. Popup commands are exposed, allowing you to invoke menu commands from your code.

Row-based copy and paste

Row-based copy and paste operations are available.

Row Resizing

Rows are resized by dragging on the horizontal boundaries of any Edit Status cell. The resizing operation affects all the rows in the corresponding table, not just the one that was dragged.

Sort Indicators

These indicators appear when an end user clicks on a column header. Since bidirectional sorting is implemented, the icon shows whether the sort is in ascending or descending order.

Figure 2 :  Active elements on HiGrid's graphical user interface.

Information about how a given DataTable is to be rendered is stored within a FormatNode. For each field in a MetaData node, there exists a corresponding field within a FormatNode that describes all visual aspects of that data field. FormatNodes are created at design-time and are stored within a FormatTree. There is one FormatNode stored in the FormatTree for each MetaData node, so the FormatTree bears a 1:1 relationship to the MetaDataTree on a node-by-node basis.

A RowTree is created to visually depict the contents of the DataTableTree at run-time. It is able to selectively display the contents of the entire DataTableTree. However, the RowTree is a logical superset of the DataTableTree because it contains rows that are not retrieved from the data source. These are the header, footer, before details, and after details rows which provide places for such things as column headings and summary information. The RowTree contains only the essential amount of information needed to reference the data in the DataTableTree and the formatting information in the FormatTree. It uses this information to manage the display of the grid.

Cells

The rows of the RowTree are comprised of cells. This is the basic unit of information in the grid. The source of a cell's value is a database field. Thus, within the context of this manual, the words field, cell, and column are used almost interchangeably1. JClass DataSource maintains the values for all these cells within DataTables - the grid does not maintain separate copies. Thus, for any row, the DataTableTree contains the actual data while the formatting information is drawn from the corresponding node in the FormatTree.

Besides specifying simple visual information such as color and font, each FormatNode also defines objects to display and edit a given cell. Each cell is drawn by an object called a Cell Renderer and edited by an object called a Cell Editor. This allows tremendous flexibility in terms of displaying and modifying data, since the modification of a cell's value is not tied to its display. For ease of use, a Cell Renderer and Cell Editor are automatically chosen for each field based on the cell's data type (although these choices can be overridden).

1.1.2 JClass HiGrid and the Model-View-Controller Paradigm

The design of JClass HiGrid conforms to the Model View Controller (MVC) paradigm, a technique for managing graphical user interfaces. MVC is a popular object oriented pattern that separates the application object (Model) from the way it is represented to the user (View), and from the way in which the user controls it (Controller). In the case of the JClass data binding products, the separation between the model and the view is achieved by providing two distinct packages. The data model is contained in JClass DataSource (the jclass.datasource package), and functions as the Model, and JClass HiGrid (the com.klg.jclass.higrid package) comprises the View and the Controller. Further separation of function is achieved by having a separate Controller class within JClass HiGrid to manage user interactions.

The Controller class is subclassable and replaceable.

The Model part of MVC keeps all the information about the organization and the state of the data. It also implements all the operations that can be used to manipulate the data. It has no responsibility for displaying the data, nor for the GUI actions that are used to manipulate the data. The Model's methods know how to access and modify data; the View methods manage the display of that data. The View object communicates with the Model. It uses the query methods of the Model to obtain data from the underlying database and then displays the information.

Because the View is separate from the Model, multiple views, even different kinds of views, can all draw their data from the same model. This makes it possible to have a form containing JClass Field components, a JClass LiveTable, and a JClass Chart all presenting data from a connection managed by JClass DataSource. Selecting a different cell in any one of the views and modifying its contents there causes all the corresponding cells in the other views to update themselves, thereby maintaining a consistent view of the data everywhere.

In the MVC paradigm, the Model is the object that manipulates the data. The View code relies on a public interface to the data. It does not need to know anything about implementation details. When the data model changes due to an update, it fires an event that is passed on to the View so that the information on the screen can be updated. The View has no memory, except for the layout structure. It refers to the data source whenever it needs to redisplay the data in cells.

The Controller object receives mouse events and keyboard inputs and translates them into commands for the model or the view. For example, a mouse click on a cell selects it and launches its editor, or a mouse click on the folder (expander) icon exposes dependent rows in a hierarchical grid. In some situations the Controller may interact directly with the View without needing to communicate with the Model. For example, the view may consist of a group of rows. Upon receiving a mouse-click on an editable cell in one of these rows, the Controller can request that the View should indicate that the selected cell is being edited, and launch the appropriate editor. The exchange of a cell renderer for a cell editor does not require that the data be updated in the Model. After a successful edit, the Model is informed to update the data source.

HiGrid's View and its Controller work together, but the Controller is also responsible for communicating data access operations back to the data source.

1.1.3 Types of Data Sources Supported

The grid may be bound to any of the common sources of data. Naturally, a JDBC data source is supported, as is any source that can be accessed through a JDBC-ODBC bridge. Unbound data can be presented as well, although you are responsible for adding the necessary code. In-memory data arrays or vectors, where the data has been generated as the program runs, may be used as the data source. The example called VectorData.java sketches one approach that can be taken.


1.2 JClass HiGrid's Major Classes and Interfaces

The diagrams in this and the following two sections show a simplified inheritance hierarchy for the three major groups in the HiGrid family. The inheritance chain is not followed back to the ultimate ancestor; instead, the hierarchy within the packages is shown.

Among the many classes in the JClass HiGrid package, the main one is the HiGrid object itself. It delegates to another class, normally the DefaultDataModelListener class, in the JClass DataSource package, which is for objects that are interested in receiving DataModelEvents. The DataModelEvent, through the parameter it passes, describes changes to the data source. Interested listeners can then query this data source to reflect the changes in their display. HiGrid implements three other interfaces, ComponentListener, and JCValidateListener. The first two are recognizable as standard java.awt.event and java.awt interfaces respectively, and JCValidateListener, part of the com.klg.jclass.cell package, is for receiving value change events from a cell editor.

Figure 3 :  Major classes and interfaces for HiGrid.

GridArea passes mouse and keyboard events to the Controller class where they are handled. This class also positions the cell editors.

Class CellFormat implements the JCCellInfo interface, which lists the methods that must be defined to return information about the cell. CellFormat renders a given cell by implementing these methods. RowFormat sets the height of the row, its indent and grid style, and sets up the formats for the row.

GridScrollbar manages the interaction with the actual scrollbar. The position of the vertical scrollbar can be on either side of the grid, and the position of the horizontal scrollbar can be at the top or the bottom of the grid. See HiGrid's API for setHorizontalScrollbarConstraints() and setVerticalScrollbarConstraints().

RowTree is based on Tree, which implements TreeModel, a generic interface for a Tree hierarchy. This tree interface is used for organizing the meta data and the actual data for the HiGrid.

For more information on the JClass HiGrid API, see the entries under com.klg.jclass.higrid in the Javadoc API for this product.

1.2.1 A Closer Look at JClass HiGrid

JClass HiGrid consists of one single GUI Component, with sub-tables rendered as necessary. The grid is bound to a database, although this is not strictly necessary, because the grid can be used in unbound mode. Either way, the grid is bound to some source of data. The grid is able to present any hierarchically organized (tree-like) data design. Normally, there will be a parent table (or joined parent tables) and one or more subsidiary tables. These subsidiary tables can themselves contain subsidiary tables, and so on. You can code your design or you can use JClass HiGrid's complete design-time customizer. See the discussion in JClass HiGrid Beans, in Chapter 3, for details on how to create a hierarchical data design using this design aid, the HiGridBeanCustomizer.

Figure 4 :  The general appearance of a grid, showing folder icon and edit status columns. A row tip appears while there is a mouse-down event on the scrollbar thumb.

The grid itself is the visual component for displaying the data model. It is expandable and collapsible through user interaction. The user can choose to expose dependent rows, and, if these rows also contain dependent rows, they too can be exposed. Changes to cells are effected by clicking on a cell to activate its editor. The changes are committed according to three selectable commit policies, ranging from manual to two types of deferred commit. Transaction processing is supported as a special case of the commit policy.

The appearance of a level in the structure can be individually specified. The Customizer can be employed to specify the appearance of a level.

One scrollbar controls the view of the top-level data. One way that end-users locate a row is by scrolling. They click on the scrollbar thumb and a "row tip" appears. The row tip's label is customizable, but by default it displays the contents of the first data column for the row that it is on. Note that there are two columns to the left of the first data column. The first is where the Folder Icons reside and the column to its right, containing initially blank squares, is the Edit Status column. The Folder Icons column shows the grid hierarchy in outline form, while the Edit Status column uses icons to indicate the various ways that a row may have been edited. The various icons are shown in the grid symbols table under Grid Symbols. Scrollbars are not available for sub-tables.

The grid area of the HiGrid is always double buffered. The result is faster updates and flicker-free operation.

1.2.2 Resizing the Grid

Since JClass HiGrid is subclassed from java.awt.Component, the grid's overall proportions are resized like any other window.

Users may resize any column horizontally by placing the mouse pointer at its right hand boundary where it becomes a double-ended arrow, then dragging to the new size. Resizing a column or row affects all columns/rows for that level of the table. Individual cells are selected by clicking on them, or by traversing to them using the arrow keys (unless the cell is in edit mode, in which case the right and left arrow keys position the I-beam in the field). Resize vertically by placing the mouse pointer at the bottom of one of the Edit Status column cells, then holding the left mouse button down and dragging to the new height. You can resize the width of a column no matter what row you are currently on. Drag the cell's left border to resize all cells in that column. By default, vertical resizing is invoked only on cells in the Edit Status Column, but there is a property that allows you to set vertical resizing on any cell if you wish. Once selected, a cell's contents may be modified, assuming that the proper update policy is in effect. Since cells may contain different data types, different cell editors will be invoked to effect the edits.

Jump scrolling is used in the vertical direction. A row is either visible or it is not; there are no half measures except for the last row, and only if the height of the view rectangle is incommensurable with an integral number of rows. On the other hand, horizontal scrolling by dragging the scrollbar is on a pixel-by-pixel basis, resulting in smoother scrolling in that direction. (Clicking on the scrollbar arrows results in jump scrolling by a few pixels at a time.)

1.2.3 The ActionInitiator Interface

JClass HiGrid uses the ActionInitiator interface as a way of interpreting user input. There is a default mapping between user actions (keystrokes and mouse clicks) and JClass HiGrid responses. Since not all user input is meaningful to JClass HiGrid, some user input is ignored, while other input is associated with a specific command, such as navigating to some specific cell. This section gives an overview of the mechanism used to manage the mapping, starting with the ActionInitiator interface, whose job is to determine whether a match has been found between the AWTEvent resulting from a keystroke or mouse click and a defined mapping currently in effect for the grid.


Figure 5 :  Classes and Interfaces relating to navigation through the grid.

The two classes that implement ActionInitiator are KeyActionInitiator and MouseActionInitiator. The two classes allow for distinguishing between keyboard actions and mouse actions. They have their own implementations of isMatch(), which determines whether a user input corresponds to one of the actions meaningful to the grid. Action handling code is contained in the Controller, which defines a list of default mappings using the constants found in HiGridAction that the grid uses to allow navigation through the grid. By default, keystrokes are interpreted as navigation commands, whereas a left-clicking on a cell launches the cell's editor, or right-clicking on a cell whose editor is inactive invokes a popup menu that contains database commands as well as navigation and print commands.

The various actions possible in JClass HiGrid are discussed in the following sections.


1.3 Operations on Cells

Once a cell is highlighted by left-clicking, an editor appropriate for the cell's data type is displayed. In this manual, it is referred to as the current cell.

There are the usual cell editors for String and numeric types, and a number of custom editors are employed as well, such as calendar popups for editing dates, and editors that perform data validation functions.

If you are a user of JClass LiveTable, it is useful for you to know that the cell editors for JClass HiGrid work in the same manner. They are single instance embeddable components.

Because only one editor at a time is allowed, there is no problem in basing the cell renderer on the data type. There are cell renderers for each different column in a table. Also, programmers can write their own cell renderers if they need to accommodate novel data types. See Displaying and Editing Cells, in Chapter 4, for details.

In a Microsoft Windows environment, the end-user modifies the cell's data with the help of an edit popup menu which is accessed by right-clicking on any cell while it is in edit mode.

The EditPopupMenu class defines a large number of enums for the possible items that can be chosen to appear in the edit popup menu. You can choose to place any of these in a customized version of the edit popup menu. A new set of popup menu items presents frames that contain instructions on using the mouse and keyboard shortcuts in JClass HiGrid.

Figure 6 :  The Edit Popup menu in Windows.

All the standard editing operations are available on the popup.

1.3.1 Cursor Tracking

A new method, called setTrackCursor, allows you to set a Boolean flag that controls whether you wish to be informed about the position of the cursor. You can then change the default cursor under program control.

1.3.2 Cell Traversal Via the Popup Menu

JClass HiGrid has its own popup menu, quite distinct from the edit popup menu in Windows. Right-clicking on any cell except the one with an active editor activates this HiGrid-specific object. The Popup Menu commands for moving from one cell to another are described in this section and shown in Figure 18, Section 2.5.6. Some of the Popup Menu items contain sub-choices, in which case they are shown in brackets following the main item.

Edit Operation

Operations on Rows

The defined operations for rows are (bracketed items are the sub-choices):

1.3.3 Operations on Columns

1.3.4 Displaying Images in Cells

Because all standard data types, including byte arrays, are supported, it is possible to display images in cells. In addition, it is possible to display a scaled image in a cell. See Displaying and Editing Cells, in Chapter 4, for details.

1.3.5 Cell Borders

All cells have a border around them. You can choose custom borders for cells, with variable styles and widths. There are ten different border styles to choose from, including a "no border" option.

JClass HiGrid's CellFormat class contains the methods that let you choose among the various styles of cell borders.

1.3.6 Keyboard Shortcuts for Grid Navigation

The HiGridAction class lets you define a mapping from a user event to an action performed on JClass HiGrid. For example, HiGridAction can be used to map Control + Left Click to a selection event.

These keystrokes control cell traversal:

1.3.7 Mouse Actions

HiGrid supports most of the standard mouse actions. The following list describes mouse actions in the Windows environment.

1.3.8 Grid Symbols

Graphic

Meaning

Current Row Icon

Icon Column:

This is the selected row.

Row Edited Icon

Icon Column:

This row has been edited.

Marked for Deletion Icon

Icon Column:

This row has been marked for deletion.

Expand Icon

Folder Column:

The expander button indicates that there are sub-tables associated with this row.

Note: Other icons are available. See Section 1.3.16, Folder Icon Styles.

Collapse Icon

Folder Column:

The appearance of the expander button when the row has actually been expanded

Truncated String Icon

Anywhere on a cell's edge:

This icon appears near the border of a cell when its size is too small to hold all the data.

Sort Icons

Header Column:

One of these icons appears after a left-click to indicate that the column has been sorted.

1.3.9 Bookmarks

The data source needs a mechanism for keeping track of all open rows. This is accomplished by assigning a row identifier, called a bookmark, to every row. Using this scheme, each cell is uniquely identified by its bookmark and by a column identifier which names the column within that row. The assignment of a bookmark to a row is dynamic because rows themselves are dynamic. A row's bookmark may change as a result of requery operations. In fact, selecting the Requery, All option from the popup menu replaces all bookmarks with new ones. Other requery operations cause the replacement of the bookmarks of the affected rows.

1.3.10 A Note on Public Methods in HiGrid

There are a number of public methods in HiGrid that are not intended for use by the application programmer. They must be public so that they can be used by Bean editors and the like. As a general rule of thumb, consult the API documentation.

1.3.11 Editing Cells

Once a cell is highlighted, an editor appropriate for the cell's data type is instantiated. There are the usual cell editors for String and numeric types, and you can employ a number of custom editors, such as calendar popups for editing dates and editors that perform data validation functions.

1.3.12 Changing the Grid's Appearance

You can customize the grid's appearance by changing fonts, border styles, and colors. You can select from a set of predefined folder icons - the symbols that indicate whether a level is expanded - or you can design your own, and you can change the color and thickness of the connecting lines. These changes can be made programmatically, or they can be done in an IDE using the HiGridBeanCustomizer, which includes functionality for setting these properties one level at a time.

1.3.13 Adding Headers and Footers

Another way of customizing your grid's appearance is by adding header, footer, and detail rows. These rows can contain items that are not drawn directly from the data source yet are related to it, such as text fields that introduce summary columns, and computed results that the database itself does not supply.

1.3.14 Displaying More of the Grid

Imagine an idealized monitor so large that it is capable of accommodating a window of any size. It is useful to define the "visible" grid as that which would be seen in a virtual monitor's window spacious enough to hold all of its open tables. Any real monitor's window containing a grid can be thought of as one through which you can view a portion of the virtual screen that holds the entire grid. The concept of a visible grid is essential for understanding how the aggregate classes work. This topic is discussed in a later section. Also, the visible grid determines how much data must be retrieved from the data source. The grid requires all the data necessary to display the visible grid, not the collapsed layers. Thus, if the root-level table contains ten thousand rows, the data for all those rows must be retrieved because the root level is always visible.

The implication for displaying more of the grid is that simply resizing the view area causes the grid to be repainted with cached data. On the other hand, exposing sub-tables requires that a query be sent to the database, which is potentially more time-consuming.

1.3.15 The HiGrid Class

This central class in the package defines the overall look of the data grid. It sets up various parameters and controls such things as whether pop-up menus, row selection, and sorting are allowed. It sets colors, border sizes and styles, indents, spacing, and initializes print parameters. It manages the look of the GUI as levels are opened and closed, and as edits are made on cells, rows, or a group of rows. Instantiate this class to create a visible grid. Its signature is

  public class HiGrid extends JComponent
    implements java.awt.event.ComponentListener, JCValidateListener

Because it is a subclass of javax.swing.JComponent, it inherits properties from the Container and Component classes as well. Naturally, it responds to window resizing and closing events. Among the methods contained in HiGrid are the following:

1.3.16 Folder Icon Styles

HiGrid has seven predefined folder icon styles. These are:

The icons are shown in Figure 7.

Figure 7 :  The seven pre-defined image icon choices.

You specify the folder icon style through the call:

HiGrid.setFolderIconStyleIndex(style);

where style is one of the aforementioned constants. You have the option of using your own icons. In this case, you use the setFolderIcon method:

public void setFolderIcon(Image icon, int type)

where you supply an icon and a type.

1.3.17 The Aggregate Classes

These classes are designed as a convenient way to calculate the information that is often required in summary records. The main class, called AggregateAll, implements the Aggregate interface. It contains methods common to all the different types of calculations that the "Aggregate" specialty subclasses define. The SummaryColumn class, through its parameters identifier (sets the column identifier), columnType (one of COLUMN_TYPE_UNKNOWN, COLUMN_TYPE_LABEL, COLUMN_TYPE_DATASOURCE, COLUMN_TYPE_AGGREGATE, COLUMN_TYPE_UNBOUND), and aggregateType (one of AGGREGATE_TYPE_NONE, AGGREGATE_TYPE_COUNT, AGGREGATE_TYPE_SUM, AGGREGATE_TYPE_AVERAGE, AGGREGATE_TYPE_MIN, AGGREGATE_TYPE_MAX, AGGREGATE_TYPE_FIRST, AGGREGATE_TYPE_LAST), sets up the column object for the summary record types. The individual Aggregate classes compute results. For instance, AggregateAverage computes the average value of a given column.

These classes are not used directly. Instead, you set up the meta data for footer rows as a list (Vector) of summary columns using the columnType enums (class constants). Here are some examples:

Setup:

MetaDataModel orderDetailMetaData = null;
  RowFormat orderDetailFooterFormat = null;
  SummaryMetaData orderDetailFooterMetaData = null;
  RowFormat orderDetailBeforeDetailsFormat = null;
  SummaryMetaData orderDetailBeforeDetailsMetaData = null;

  TreeIterator ti = node.getIterator();
  if (ti.hasMoreElements()) {
    node = (FormatNode) ti.get();
    node.setDefaultSortData(new SortData("prod_id",
      SortGrid.DESCENDING));
    orderDetailMetaData = (MetaDataModel)
      node.getRecordFormat().getMetaData();
    orderDetailFooterFormat = (RowFormat) node.getFooterFormat();
    orderDetailFooterMetaData = (SummaryMetaData)
      orderDetailFooterFormat.getMetaData();
    orderDetailBeforeDetailsFormat = (RowFormat)
      node.getBeforeDetailsFormat();
    orderDetailBeforeDetailsMetaData = (SummaryMetaData)
      orderDetailBeforeDetailsFormat.getMetaData();
  }

Label:

SummaryColumn column = new SummaryColumn("Total Quantity: ");
orderDetailFooterMetaData.appendColumn(column);

Aggregate:

SummaryColumn column = new SummaryColumn(orderDetailMetaData,
    "LineTotal",
    SummaryColumn.COLUMN_TYPE_AGGREGATE,
    SummaryColumn.AGGREGATE_TYPE_SUM);
  orderDetailFooterMetaData.appendColumn(column);

Data Source:

SummaryColumn column = new SummaryColumn(orderDetailMetaData,
    "ProductID",
    SummaryColumn.COLUMN_TYPE_DATASOURCE);
  orderDetailBeforeDetailsMetaData.appendColumn(column);

1.3.18 Virtual Columns

A Virtual Column performs an analogous aggregation operation by using row data to produce a derived value. In the case of a virtual column, mathematical operations are defined on the cells of a row, such as applying a sales tax calculation to a cell containing the purchase price of an item. The computed total price with the sales tax added on is displayed in a newly defined cell. When all rows of the table are taken into account, these cells form a column that we are calling a virtual column. The virtual column may be computed from the values of two or more cells in the row. In turn, its value may be aggregated by the methods described in this section to produce a footer detail.

Note: Please see Virtual Columns, in Chapter 6, for an extended discussion of the use of virtual columns.


1.4 The Data Model for JClass HiGrid

JClass HiGrid is capable of displaying hierarchical data structures because its underlying data model is also capable of maintaining actual data tables that imitate the structure of a hierarchical design. The relationship that one table bears to another is called meta data to distinguish it from the actual data that the grid displays. To be specific, we present a design for a sales order system shown diagrammatically in Figure 8. The root data table is extracted from a database table called Orders. Each row consists of the fields OrderID, CustomerID, EmployeeID, OrderDate, PurchaseOrderNumber, and RequiredDate. Sales orders are more fully described in two separate sub-tables, Customers and OrderDetails. The Customers table is linked to its parent by matching the CustomerID fields in each. The field OrderID in the OrderDetails table is the same as OrderID in the Orders table so a join on these two fields properly associates an Orders row with OrderDetails. Additional information about an OrderDetails row is obtained by a detail row called Products-Categories consisting of product information and the category this product falls into.

Figure 8 :  The meta data design of a sales order tracking system.

This structure can be captured in the data model and displayed using JClass HiGrid. The programming example based on this model is called DemoData, in jclass.datasource.examples.

Running the program produces output similar to this:

Figure 9 :  JClass HiGrid retrieves and displays the root table called Orders.

Clicking on any one of the folder icons marked "+" exposes the related tree-structured data. This example has three levels in its meta data. The second sub-level is accessed in the same way as the first, by clicking on the "+" expander button at the left hand side of the row.

When these levels are opened, the grid looks like this:

Figure 10 :  The expanded view of the sales orders tracking system with all levels of the first two rows opened.

The example shows that JClass HiGrid gives your application the ability to present a multi-layered view of the tables in your corporate databases. Compared to a design based on forms, the hierarchical grid allows you to present considerable data in a relatively small space, while also providing the organization that makes it easy for end-users to navigate to detail levels.

1.4.1 A Closer Look at the Data Model

There are two main areas in the design of the data model, the design-time meta data and the run-time data tables. Of these, the most apparent to the end-user is the data table mechanism that stores the data for subsequent display by a grid component, like JClass HiGrid, or on a form using data bound components like those provided by JClass Chart, JClass Field, JClass LiveTable, or JClass DataSource. Since JClass HiGrid defines a mechanism for describing data relationships in a hierarchical way, a parallel structure is needed to describe the way that various tables relate to each other. This is accomplished by using Swing's interface called TreeNode which describes the nodes of a TreeModel, a generic interface for a Tree hierarchy. This tree interface is used for organizing the meta data and the actual data for the JClass HiGrid. (Note: TreeModel contains TreeNodeModel, and Tree is a container for tree nodes.) The DataSourceTreeNode class, combined with the MetaDataModel interface, helps to define abstract class BaseMetaData, and then the concrete class MetaData. It is only this last one that is source data format dependent. This forms the meta data definition mechanism.

On the data side, we also subclass from DataSourceTreeNode, but the DataTableModel interface is used to define BaseDataTable. DataTableModel is the interface for data storage for the JClass HiGrid data model. The data model will request data from instances of BaseDataTable and will manipulate that data through the DataTableModel interface. That is, rows can then be added, deleted or updated through this DataTable. BaseDataTable is a default implementation of the methods and properties common to various implementations of the DataTableModel. This class must be extended to concretely implement those methods not implemented in it. The class that accomplishes this is in the DataTable category, and is one of a number of specially constructed classes specifically tailored to the source data format. A copy of the data returned in a JDBC result table will be copied into one of these result tables so the data can be cached. Rows can then be added, deleted or updated through this DataTable.


1.5 Internationalization

Internationalization is the process of making software that is ready for adaptation to various languages and regions without engineering changes. JClass products have been internationalized.

Localization is the process of making internationalized software run appropriately in a particular environment. All Strings used by JClass that need to be localized (that is, Strings that will be seen by a typical user) have been internationalized and are ready for localization. Thus, while localization stubs are in place for JClass, this step must be implemented by the developer of the localized software. These Strings are in resource bundles in every package that requires them. Therefore, the developer of the localized software who has purchased source code should augment all .java files within the /resources/ directory with the .java file specific for the relevant region; for example, for France, LocaleInfo.java becomes LocaleInfo_fr.java, and needs to contain the translated French versions of the Strings in the source LocaleInfo.java file. (Usually the file is called LocaleInfo.java, but can also have another name, such as LocaleBeanInfo.java or BeanLocaleInfo.java.)

Essentially, developers of the localized software create their own resource bundles for their own locale. Developers should check every package for a /resources/ directory; if one is found, then the .java files in it will need to be localized.

For more information on internationalization, go to: http://java.sun.com/j2se/1.4.2/docs/guide/intl/index.html.

1Field is used to emphasize the origin of the data (in a database field), cell is used when the emphasis is on the display, and column is used when referring to the group of cells in a DataTable that have the same field name.


PreviousNextIndex