ItemTable for the RhinoExampleCategory

How to write a Rhino ItemTable

Table of Contents



Introduction

This document is a reference for SGI software engineers who will be writing ItemTables for Rhino applications. An ItemTable in the Rhino Architecture is a UI Component that displays all the Items that exists in a particular Category (or Association). The ItemTable is not meant to display all of the information about each Item (that is the job of the ItemView). The ItemTable should show the information that the user is most likely to be interested in seeing, and is limited to displaying information that can fit into the cells of the table.

Overview of the ItemTable

The ItemTable is composed of a number of columns, each column representing one piece of information from the Item. Each Item is represented by a row of the table. Each column has a descriptive header. If the user clicks on the header, the table is sorted based on the associated column.

The first column of the ItemTable is reserved for the Icon that represents the Item. The Icon is not controlled by the ItemTable, but is generated by the ResourceBasedIconRenderer. See the tutorial on using ResourceBasedIconRenderer for details on how to control the Icon.


Before you begin

Before creating an ItemTable for a particular Category, it is necessary need to understand the names and terms that the Rhino infrastructure uses in relation to Categories. See the The names of Categories on the client and on the server documentation for more information.

Customizing the Columns of the ItemTable

No-Code ItemTables

No-Code Item Table While in the early stages of writing Categories, it may be desirable to show an ItemTable that shows all of the Items of a Category. The ItemTable supports this idea by means of a "no-code" ItemTable. This version of an ItemTable is not designed for use in a shipping Rhino application, but can be of great assistance while investigating the Rhino Infrastructure or for giving preliminary demos. No code or resource files need to be written to use the "no-code" ItemTable - it can be launched as soon the server side Categories have been written and the Rhino infrastructure has been installed on the client. An example of this "no-code" ItemTable is shown to the right. To launch a "no-code" ItemTable, follow the instructions in the section titled How to launch ItemTables. While this ItemTable shows a lot of information, it is not suitable for use in a shipping code. To turn this ItemTable into a shippable ItemTable, it is necessary to provide resources that describe the order in which the column will be displayed, suitable headers for the columns, and ways to internationalize the ItemTable. The rest of the document will describe how to accomplish this.

The column property

The manner in which the Items are displayed in the columns can be completely controlled by a resource file. The most important resource entries are the ones that name the columns that will be displayed. The names of the resources follow the form <Category name>.ItemTable.column<n>, where <Category name> is the name of the Category and <n> represents integers starting at 0 that represent order in which the columns should be displayed. (see the COLUMNS documentation for more details). For example, the resource file that controls the RhinoExampleCategory could contain the following lines (the letters in the first column are for reference purposes only):

A: com.sgi.rhexamp.category.rhexampRhinoExampleCategory.ItemTable.column0=name
B: com.sgi.rhexamp.category.rhexampRhinoExampleCategory.ItemTable.column1=type
C: com.sgi.rhexamp.category.rhexampRhinoExampleCategory.ItemTable.column2=mode

Because the first part of each line is identical, it is common to use macros to shorten the lines of the resource file and to make the file easier to read. An example of the same resources using macros is shown below.

A: RHINO_EXAMPLE_CATEGORY=com.sgi.rhexamp.category.rhexampRhinoExampleCategory
B: ITprefix=${RHINO_EXAMPLE_CATEGORY}.ItemTable
C:
D: ${ITprefix}.column0=name
E: ${ITprefix}.column1=type
F: ${ITprefix}.column2=mode
ItemTable with only columns property defined

The three "column" lines (D - F) describe both the names of the columns and the order in which the columns will be displayed in the ItemTable. The names will be used later in the resource file to associate resources with particular columns. In this example, the names of the columns correspond exactly with the names of the Attributes in the Item that will be displayed in the column. By naming the columns in this manner, the ItemTable can use default behavior and automatically associate the correct Attribute with the column. It is also possible to give the columns names that are not the same as the names of Attributes. In that case, it may be necessary to use the "basedOn" property (defined below) to tell the ItemTable which Attribute is associated with a column.

Running an ItemTable with only the 5 lines described above in the resource file will result in an ItemTable that is shown on the right. Notice that the order of the columns (from left to right) is "name", "type", and then "node", which was as specified in the resource file. ItemTable has used the names of the columns as the labels for the columns. Information about how to customize the labels is described below. The ItemTable is using the default "toString" method (methods are described below). This is the simplest method, and uses the results of calling Java's toString method on the value of the Attribute.

The basedOn property

In the example resource file shown above, the names of the columns were defined to be the same as the Item's Attributes that they represented. This allowed the ItemTable to automatically show the value of the Attribute in the columns. It is sometimes desirable to use different names for the columns than the Attributes that control them. This can be to make the resource file more readable or because there may not be a one to one correspondence between the Attributes in the Item and the columns that are displayed.

If a column is given a name that does not correspond to the name of an Attribute, the "basedOn" property is used to tell the ItemTable which Attribute the column represents. The "basedOn" resources are defined as: <Category name>.ItemTable.basedOn.<column>, where <Category name> is the name of the Category, and <column> is the name of a column. (See the BASED_ON documentation for more details).

The stringRenderer, richTextRenderer, and componentRenderer methods (as described below) do not require that the column be associated with a particular Attribute. When using these methods, it is not necessary to specify the "basedOn" property even if the name of the column does not correspond to an Attribute. All the other methods, including the default "toString" method, require that the column be associated with a particular Attribute of the Item.

For example, suppose that for some reason we wish to display the name Attribute twice, once as the first column, and once as the last column. A resource file as follows would do just that:

A: RHINO_EXAMPLE_CATEGORY=com.sgi.rhexamp.category.rhexampRhinoExampleCategory
B: ITprefix=${RHINO_EXAMPLE_CATEGORY}.ItemTable
C:
D: ${ITprefix}.column0=name1
E: ${ITprefix}.column1=type
F: ${ITprefix}.column2=mode
G: ${ITprefix}.column3=name2
H:
I: ${ITprefix}.basedOn.name1=name
J: ${ITprefix}.basedOn.name2=name
ItemTable with basedOn properties defined

This would result is the name being shown twice, as is seen to the right:

The label property

The next step is to define the strings that will be used as the headers for the columns. The "label" resource controls this, and is defined as: <Category name>.ItemTable.label.<column>. (See the LABEL documentation for more details). For example, to add labels to the columns in the ItemTable, the resource file would get three new resources:

A: RHINO_EXAMPLE_CATEGORY=com.sgi.rhexamp.category.rhexampRhinoExampleCategory
B: ITprefix=${RHINO_EXAMPLE_CATEGORY}.ItemTable
C:
D: ${ITprefix}.column0=name
E: ${ITprefix}.column1=type
F: ${ITprefix}.column2=mode
G:
H: ${ITprefix}.label.name=Name
I: ${ITprefix}.label.type=Type
J: ${ITprefix}.label.mode=Access
ItemTable with labels property defined

Displaying the ItemTable now shows that the correct labels are displayed.

The method property

The next step is to choose what method the ItemTable should use to display the column. (In this usage, "method" does not refer to a Java method, but rather to the typical English definition of the word.) The "method" resource controls this, and is defined as: <Category name>.ItemTable.method.<column>. (See the METHOD documentation for more details) There are seven methods available:

  1. toString

    The toString method is the default method, and is what the ItemTable implicitly uses to display the column if no method is specified in the properties file. The toString method calls Java's toString method on the value of the Attribute that is associated with the column (either by the "basedOn" property or the name of the column if no "basedOn" property is set). If this method is used, no additional resources are needed.
  2. lookup

    The lookup method uses the value of the Attribute that is associated with the column (either by the "basedOn" property or the name of the column if no "basedOn" property is set) as a key to lookup a string in a table of values. This is useful for cases when the value of the Attributes comes from a limited set of possible values, and there is a mapping from the Attribute to some more easily understandable string. This is also useful when there will be a need to localize the text that gets displayed in the column. If using the "lookup" method, also provide "lookup" resources, which are defined as <Category name>.ItemTable.lookup.<column>.<Attribute's value> (See the LOOKUP documentation for more details), for each of the possible values of the Attribute.

    For example, to specify that the "type" column should use the lookup method, and should display the type in Spanish instead of English, include the following in the resource file:

    A: ${ITprefix}.method.type=lookup
    B:
    C: ${ITprefix}.lookup.type.Printer=Impresora
    D: ${ITprefix}.lookup.type.Clock=Reloj
    E: ${ITprefix}.lookup.type.NetscapeExecutable=Netscape
    

    ItemTable with Spanish translations for the types In this case, the type of the Item will be displayed in it's Spanish equivalent:

  3. richText

    The richText method will display the string value of the Attribute just as the toString method does, but will display it as a link that launches an ItemView. This is generally used to show the relationship between an Item in one Category and an Item in another Category, or to provide a way to launch ItemViews of the Items in the ItemTable.

    When using the richText method for a column, there must be two additional resources defined for each column. The first is the "category" resource, which is defined as <Category name>.ItemTable.category.<column> (See the CATEGORY documentation for more details). The second resource is the "selector" resource, which is defined as <Category name>.ItemTable.selector.<column> (See the SELECTOR documentation for more details). The "category" resource is a string that gives the package-qualifed name of the Category that the ItemView will use, and the "selector" resource names the Attribute whose value will be used as the selector of the Item the ItemView will show.

    The example only has one Category, so to demonstrate the richText method, consider making the "name" column contain links to launch the appropriate ItemView. The following lines would be added the resource file:

    A: ${ITprefix}.method.name=richText
    B: 
    C: ${ITprefix}.category.name=${RHINO_EXAMPLE_CATEGORY}
    D: ${ITprefix}.selector.name=name
    

    ItemTable using richText method

  4. icon

    The icon method can be used to show the value of an Attribute as an icon. The value of the Attribute that is associated with the column (either by the "basedOn" property or the name of the column if no "basedOn" property is set) is turned into a string with the toString method, and that value is used to lookup the "icon" resource, which is defined as <Category name>.ItemTable.icon.<column>.<Attribute's value> (see the ICON documentation for more details). The "icon" resource should be the pathname of an icon to show in the table. If the "icon" resource is not found, then a default icon is used, which is defined as <Category name>.ItemTable.icon.<column> (See the DEFAULT_ICON documentation for more details). If neither the specific icon or the default icon icon is found, then no icon will be shown.

    For example, to show an Icon that represents the "mode" Attribute, the following should be used as the resource file:

    A: RHINO_EXAMPLE_CATEGORY=com.sgi.rhexamp.category.rhexampRhinoExampleCategory
    B: ITprefix=${RHINO_EXAMPLE_CATEGORY}.ItemTable
    C:
    D: ${ITprefix}.column0=name
    E: ${ITprefix}.column1=type
    F: ${ITprefix}.column2=mode-icon
    G: ${ITprefix}.column3=mode-text
    H:
    I: ${ITprefix}.basedOn.mode-icon=mode
    J: ${ITprefix}.basedOn.mode-text=mode
    K:
    L: ${ITprefix}.method.mode-icon=icon
    M: ${ITprefix}.icon.mode-icon.33188=/com/sgi/rhexamp/category/images/blue-ball.gif
    N: ${ITprefix}.icon.mode-icon.33060=/com/sgi/rhexamp/category/images/red-ball.gif
    O: ${ITprefix}.icon.mode-icon=/com/sgi/rhexamp/category/images/yellow-ball.gif
    

    ItemTable with Icons The example to the right shows the ItemTable that will result. Note that because the mode needed to be displayed in two columns, once as an icon and once as text, it was necessary to add a forth column to the ItemTable and provide new names for the third and forth columns. Also notice the "basedOn" properties that tell ItemTable that the mode Attribute of the Item controls both columns.

  5. stringRenderer

  6. richTextRenderer

  7. componentRenderer

    It is sometimes the case that none of the three ways presented so far are adequate to display the state of the Item. Such cases can result when: In any of these cases, use one of the renderer methods. These methods provide a chance to write a small piece of Java code that will control the display of the column. There are three types of renderers: These renderers all use the same instance of ItemTableColumnRenderer to render the column. The renderers differ only in the type of Object that the renderer returns. In the case of the RhinoExample Category, the "mode-text" column uses a string renderer to convert the "mode" attribute of the Item into a user-readable string. See the RhinoExampleCategoryRenderers file for the example. Also see the Writing an ItemTableColumnRenderer section below about how to write an ItemTableColumnRenderer. Adding the following lines to the resource file tells the ItemTable to use the stringRenderer method for the "mode-text" column, and to use the com.sgi.rhexamp.category.rhexampRhinoExampleCategoryRenderers class as the ItemTableColumnRenderer. Lines "D" and "E" are resources that the ItemTableColumnRenderer uses.
    A: ${ITprefix}.method.mode-text=stringRenderer
    B: ${ITprefix}.columnRenderer=${RHINO_EXAMPLE_CATEGORY}Renderers
    C:
    D: ${ITprefix}.modeStr.readWrite=Read/Write
    E: ${ITprefix}.modeStr.readOnly=Read Only
    

    ItemTable using the stringRenderer method After adding the resources to use the string renderer, the ItemTable looks like:

The width property

To set the width of a column (in points), use the "width" property, which is defined as: <Category name>.ItemTable.width.<column>. (See the WIDTH documentation for more details). For example, to set the widths of the columns in the ItemTable, the resource file would get four new resources:

A: ${ITprefix}.width.name=100
B: ${ITprefix}.width.type=100
C: ${ITprefix}.width.mode-icon=10
D: ${ITprefix}.width.mode-text=100

ItemTable with width properties set After setting the widths, the ItemTable is as shown:

The alignment property

To control the alignment (justification) of the columns in the ItemTable, use the "alignment" property, which is defined as <Category name>.ItemTable.alignment.<column>. (See the ALIGNMENT documentation for more details). For example, to set the alignment of the columns in the ItemTable, the resource file would get two new resources:

A: ${ITprefix}.alignment.type=right
B: ${ITprefix}.alignment.mode-text=left
ItemTable with Alignment properties set There are no alignment resources for the name or mode-icon columns because alignment is only available on columns using the toString, lookup, and stringRenderer methods.

After setting the alignment resources as shown above, the ItemTable looks like:

The sort property

To control the way the the ItemTable sorts a column, use the the "sort" property, which is defined as <Category name>.ItemTable.sort.<column>. (See the SORT documentation for more details). There are four sorting option available, and each of them work with particular methods: The "lexical" sort is a alphanumeric sort that uses the java.text.Collator.compare method to compare Attributes. The "numeric" sort turns the Attributes into instances of java.lang.Integer and then performs a numeric sort. The "none" sort specifies that there is no sort order for a column. The "sorter" sort specifies that the ItemTable should call the compareItemsForItemTable method of the ItemTableColumnRenderer to compare Items. See the Writing an ItemTableColumnRenderer section below about how to write a ItemTableColumnRenderer. For example, to set the sort method of the columns in the ItemTable, the resource file would get four new resources:

A: ${ITprefix}.sort.name=lexical
B: ${ITprefix}.sort.type=lexical
C: ${ITprefix}.sort.mode-icon=sorter
D: ${ITprefix}.sort.mode-text=lexical

The missing property

Depending on the way that the server-side Category is written, there may be cases where a particular Attribute is missing from an Item. For example, consider that the Item can optionally contain the "type" Attribute. If the Item contains that Attribute, then the column should display the name using the lookup method as described above. Otherwise, the column should display some other string, such as "(Unknown)". For this situation, you can use the "missing" resource (defined as <Category name>.ItemTable.missing.<column>). The "missing" resource allows you to specify a string that will be displayed if an Attribute is missing from an Item. The "missing" resource can be used with the toString, lookup, or richText methods.

For example, to use the string "(Desconocido)" (Spanish for "Unknown") if the "type" Attribute is missing from the Item, add the following resource:

A: ${ITprefix}.method.type=lookup
B:
C: ${ITprefix}.lookup.type.Printer=Impresora
D: ${ITprefix}.lookup.type.Clock=Reloj
E: ${ITprefix}.lookup.type.NetscapeExecutable=Netscape
F: ${ITprefix}.missing.type=(Desconocido)

Writing an ItemTableColumnRenderer

ItemTables use an instance of the ItemTableColumnRenderer interface to render columns that are using the stringRenderer, richTextRenderer, and componentRenderer methods. There is only one ItemTableColumnRenderer per ItemTable, so it must be able to handle all of the columns in the ItemTable that are using a renderer method. Write a class that implements the ItemTableColumnRenderer interface, and place it in the product's "category" package. (The file can actually be placed anywhere, but the "category" package is one logical place.) Tell the ItemTable how to find the class by naming it in the property file with the "columnRenderer" property, which is defined as <Category name>.ItemTable.columnRenderer (see the COLUMN_RENDERER documentation for more info). For example, the RhinoExampleCategory has a class com.sgi.rhexamp.category.rhexampRhinoExampleCategoryRenderers that implements the ItemTableColumnRenderer interface, and so the following line is included in the Category's resource file:
A: ${ITprefix}.columnRenderer=${RHINO_EXAMPLE_CATEGORY}Renderers
If a column uses a renderer method, but no ItemTableColumnRenderer is defined with the "columnRenderer" property, then the ItemTable will attempt to load a class with the name <Category Name>ColumnRenderer. For example, for the rhinoExampleCategory, it would attempt to load the class com.sgi.rhexamp.category.rhexampRhinoExampleCategoryColumnRenderer. If the "columnRenderer" resource is not specified and the <Category Name>ColumnRenderer class is not found, then ItemTable will throw an assertion.

The ItemTableColumnRenderer has four methods that must be implemented: See the documentation for ItemTableColumnRenderer about the specifics of each method.

When the ItemTable requires that a cell be rendered, it will call one of the get*ForCellOfItemTable methods, depending on the type of renderer being used.

For the stringRenderer method, the ItemTable will call the getStringForCellOfItemTable method, and the method should compute the String to display and return it.

For the richTextRenderer method, the ItemTable will call the getRichTextForCellOfItemTable method, and the method should compute the String of HTML to display in a RichTextComponent and return it. To construct a URL that will launch an ItemView, use the createURLToLaunch method of ItemView.

For the componentRendrer method, the ItemTable will call the getComponentForCellOfItemTable, and the method should return a Component that the ItemTable should display in the appropriate cell.

The compareItemsForItemTable method is used to sort the ItemTable based on a column that is using the "sorter" method of sorting. The ItemTable will pass two Items and the name of the column to the method, and the method should return an integer representing which of the Items should come first in the sorted list. See the ItemTableColumnRenderer documentation for more information about these methods.


Controlling the Icon displayed for an Item in the ItemTable

The ItemTable does not directly control the Icon that is displayed. The Icon is generated by the ResourceBasedIconRenderer. See the tutorial on using ResourceBasedIconRenderer for details on how to control the Icon.

Controlling the title of the ItemTable

The ItemTable does not directly control the title that is used (as displayed on the window's title bar). The Title is generated by the ResourceBasedNameRenderer. See the tutorial on using ResourceBasedNameRenderer for details on how to control the title.

How to launch ItemTables

To view an ItemTable from the command line, type:

%> java com.sgi.sysadm.manager.RunItemTable <Category Name>

For example, to launch an ItemTable for Category "BarCategory", where the ItemTable's resource file is in /com/sgi/myProduct/category (relative to classpath), type:

%> java com.sgi.sysadm.manager.RunItemTable com.sgi.myProduct.category.BarCategory

To launch a no-code ItemTable, omit the name of the package:

%> java com.sgi.sysadm.manager.RunItemTable BarCategory

To programmatically launch an ItemTable, use one of two methods: To launch an ItemTable in a new frame (called an ItemTableFrame), use the launchItemTableFrame method in ItemTableFrame. The launchItemTableFrame method takes a ItemTableLaunchRequestEvent, which encapsulates all the information about which ItemTable to launch. For example:

1:   ItemTableFrame.launchItemTableFrame(
2:       new ItemTableLaunchRequestEvent(this,
3:                                       "com.sgi.myProduct.category.BarCategory"),
4:       new UIContext());

To embed an ItemTable in another component, create an ItemTable with the createItemTable method of ItemTable, set Category to display with the setCategory method, then call getItemTablePanel on ItemTable to get a panel that contains the ItemTable. For example:
1:   ItemTable it = ItemTable.createItemTable(_hostContext,
2:                                            "com.sgi.myProduct.category.BarCategory");
3:   it.setCategory(_hostContext.getCategory("BarCategory"));
4:   _panel.add(it.getItemTablePanel());

Typical Resource File for an ItemTable

ItemTable for the RhinoExampleCategory

A:  # Set up some macros to use in this resource file.  See the
B:  # ResourceStack documentation for more about macros.
C:  RHINO_EXAMPLE_CATEGORY=com.sgi.rhexamp.category.rhexampRhinoExampleCategory
D:  ITprefix=${RHINO_EXAMPLE_CATEGORY}.ItemTable
E:
F:  # Define the columns to displayed.  Call them "mode", "type",
G:  # "mode-icon", and "mode-text". 
H:  ${ITprefix}.column0=name
I:  ${ITprefix}.column1=type
J:  ${ITprefix}.column2=mode-icon
K:  ${ITprefix}.column3=mode-text
L:
M:  # Tells the ItemTable which Attributes of the Item to use to show the
N:  # columns.  It is not necessary to set a resource for mode-text because
O:  # it's using a "renderer" method, and basedOn is not used for the
P:  # "renderer" methods.
Q:  ${ITprefix}.basedOn.name=name
R:  ${ITprefix}.basedOn.type=type
S:  ${ITprefix}.basedOn.mode-icon=mode
T:
U:  # Sets the method that the ItemTable will use to display the four columns
V:  ${ITprefix}.method.name=richText
W:  ${ITprefix}.method.type=lookup
X:  ${ITprefix}.method.mode-icon=icon
Y:  ${ITprefix}.method.mode-text=stringRenderer
Z:
AA: # Additional resources that are necessary because the "mode-icon"
AB: # column is using the "icon" method. 
AC: ${ITprefix}.icon.mode-icon.33188=/com/sgi/rhexamp/category/images/blue-ball.gif
AD: ${ITprefix}.icon.mode-icon.33060=/com/sgi/rhexamp/category/images/red-ball.gif
AE: ${ITprefix}.icon.mode-icon=/com/sgi/rhexamp/category/images/yellow-ball.gif
AF:
AG: # Additional resources that are necessary because the "type" column
AH: # is using the "lookup" method.
AI: ${ITprefix}.lookup.type.Printer=Printer
AJ: ${ITprefix}.lookup.type.Clock=Clock
AK: ${ITprefix}.lookup.type.NetscapeExecutable=Netscape
AL:
AM: # Additional resources that are necessary because the "name" column
AN: # is using a "richText" method.
AO: ${ITprefix}.category.name=${RHINO_EXAMPLE_CATEGORY}
AP: ${ITprefix}.selector.name=name
AQ:
AR: # Sets the labels that will be used for the columns.
AS: ${ITprefix}.label.name=Name
AT: ${ITprefix}.label.type=Type
AU: ${ITprefix}.label.mode-icon=
AV: ${ITprefix}.label.mode-text=Access
AW:
AX: # Sets the widths of the columns
AY: ${ITprefix}.width.name=100
AZ: ${ITprefix}.width.type=100
BA: ${ITprefix}.width.mode-icon=10
BB: ${ITprefix}.width.mode-text=100
BC:
BD: # Sets the alignment that will be used for the columns.  There are
BE: # no alignment resources for the name or mode-icon columns because
BF: # alignment is only available on columns using the toString, lookup, and
BG: # stringRenderer methods.
BH: ${ITprefix}.alignment.type=left
BI: ${ITprefix}.alignment.mode-text=left
BJ:
BK: # Sets the type of sort that will be used for the columns.
BL: ${ITprefix}.sort.name=lexical
BM: ${ITprefix}.sort.type=lexical
BN: ${ITprefix}.sort.mode-icon=sorter
BO: ${ITprefix}.sort.mode-text=lexical
BP:
BQ: # Tells the ItemTable what class to use as the ItemTableColumnRenderer.
BR: ${ITprefix}.columnRenderer=${RHINO_EXAMPLE_CATEGORY}Renderers
BS:
BT: # Resources used by the ItemTableColumnRenderer.
BU: ${ITprefix}.modeStr.readWrite=Read/Write
BV: ${ITprefix}.modeStr.readOnly=Read Only