Customizing table columns
Explains how to customize an existing column in the table portion of the Gantt chart or Schedule chart and also how to define a new type of column and add it to the table.
Describes how to run the customData sample.
Describes how to customize the expanded and collapsed icons for parent activities in a column.
Describes how the custom table-column class is implemented.
Explains how to add a PriorityColumn object to the table.
Explains the custom code implemented in the Dynamic Columns code example.
Running the example
This section refers to the
Rendering a Custom Data Model sample. You can find the corresponding source code in:
To run the example:
1. Make sure that the Ant utility is properly configured. If not, read
Starting the samples for instructions on how to configure
Ant for
JViews Gantt:
2. Go to the directory where the example is installed and type:
ant run
to run the example as an application.
Tree column icons
The first column in the table is an instance of the
IlvTreeColumn class. This type of column uses a renderer that implements the standard Swing
TreeCellRenderer interface to display its contents. As in the Swing
JTree component, the default renderer that the column uses is a Swing
DefaultTreeCellRenderer object. The following code shows how to customize the expanded and collapsed icons for parent activities in the column:
IlvTreeColumn treeColumn = gantt.getTable().getTreeColumn("Name");
DefaultTreeCellRenderer renderer =
(DefaultTreeCellRenderer)treeColumn.getRenderer();
renderer.setOpenIcon(new ImageIcon(...));
renderer.setClosedIcon(new ImageIcon(...));
The PriorityColumn class
New custom columns can be added to the table by creating an implementation of the
IlvJTableColumn interface and adding it to the chart table. The custom table-column implementation is located in the file:
This class is an extension of
IlvAbstractJTableColumn: and thereby implements the
IlvJTableColumn interface. Start out by duplicating each of the superclass constructors and adding an
init method, which is where you will customize various aspects of the column.
The basic skeleton of the class looks like this:
public class PriorityColumn extends IlvAbstractJTableColumn {
public PriorityColumn(Object headerValue) {
super(headerValue);
}
public PriorityColumn(Object headerValue, int width) {
super(headerValue, width);
}
...
}
An
IlvJTableColumn object is a wrapper around a standard Swing
javax.swing.table.TableColumn object. The underlying
TableColumn object is responsible for rendering and editing each cell within the column. However, because the standard
TableColumn object considers row indices, the
IlvJTableColumn wrapper maps the column to work in terms of
IlvHierarchyNode data nodes (that is, activities and resources) instead. The
TableColumn object also provides hooks so that the column can refresh automatically in response to data model events.
The custom PriorityColumn has two purposes:
Rendering the priority of each custom activity as a numeric string. The color of the text should change depending on the value.
Permitting the application user to edit the priority values using a standard
JSlider component.
When an instance of
IlvAbstractJTableColumn (and hence of
PriorityColumn) is initially constructed, it creates an underlying Swing
TableColumn object that has no cell renderer or cell editor set. This means that the column cells will be rendered and edited using the class-based default settings of the table. Typically, this means that a
JLabel object will be used for rendering text and a
JTextField object will be used for editing. To obtain the customized rendering and editing behavior you want instead, create a
TableCellRenderer and
TableCellEditor object for the column explicitly.
Support methods
Before the review of the column renderer and editor, implement the following IlvJTableColumn methods in the class PriorityColumn.
The methods to be implemented are:
1. The method
getValue returns the priority for an activity. Because priorities are stored as primitive
int values, wrap the priority in an
Integer object.
public Object getValue(IlvHierarchyNode activity) {
return PriorityProperty.getPriority((IlvActivity)activity);
}
2. The method
setValue sets the priority for an activity. The priority will be passed in as an
Integer because of the way
getValue is coded.
public void setValue(IlvHierarchyNode activity, Object value) {
if (!(activity instanceof IlvUserPropertyHolder && value instanceof
Number))
return;
PriorityProperty.setPriority((IlvActivity)activity, (Number)value);
}
3. The method
isEditable is overridden to return
true so that the priority values can be edited.
public boolean isEditable(IlvHierarchyNode activity) {
Number priority = PriorityProperty.getPriority((IlvActivity)activity);
return priority != null;
}
The cell renderer
The renderer of the priority column is created as an extension of the Swing DefaultTableCellRenderer class.
To create the priority column renderer:
1. Overriding the
createRenderer method that the class
PriorityColumn inherits from
IlvAbstractJTableColumn.
Only two methods are of the class DefaultTableCellRenderer are overridden:
Override the
setValue method to use a
NumberFormat to format the priority value into a text string for display.
Override the
getTableCellRendererComponent method to center the text in the column and to set the text color based upon the priority value.
The new additions to PriorityColumn look like this:
Example 10 – Additions to the PriorityColumn
private NumberFormat formatter = NumberFormat.getInstance();
protected TableCellRenderer createRenderer() {
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
private Color darkGreen = Color.green.darker();
protected void setValue (Object value) {
if (!(value instanceof Integer))
setText("");
else
setText(formatter.format(value));
}
public Component getTableCellRendererComponent
(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component comp = super.getTableCellRendererComponent
(table,
value,
isSelected,
hasFocus,
row,
column);
if (value instanceof Integer) {
int intVal = ((Integer) value).intValue();
Color color;
if (intVal <= 2)
color = Color.red;
else if (intVal <= 4)
color = Color.orange;
else if (intVal <= 7)
color = darkGreen;
else
color = Color.blue;
comp.setForeground(color);
}
return comp;
}
};
renderer.setHorizontalAlignment(JLabel.CENTER);
return renderer;
}
2. Set the PriorityColumn to automatically refresh any activities whose value has changed.
This change will be signaled from the Gantt data model by an instance of
ActivityUserPropertyEvent. When the column is added to the table, the method
setGanttConfiguration will be called. Use this opportunity to register the column to receive the desired
ActivityUserPropertyEvent notifications. To act as an event listener, the column must implement the
GenericEventListener interface and its
inform method. In the
inform method, the column calls the
cellUpdated method of its superclass to refresh the activity whose priority has changed. The relevant code looks like this:
Example 11 – Set the PriorityColumn.
public class PriorityColumn extends IlvAbstractJTableColumn
implements GenericEventListener {
private IlvGanttConfiguration ganttConfig;
public void setGanttConfiguration(IlvGanttConfiguration ganttConfig) {
// When the column is removed from the table, unregister from
// all notifications.
if (this.ganttConfig != null)
this.ganttConfig.removeListener(this);
this.ganttConfig = ganttConfig;
// When the column is added to the table, register for
// user-defined property events.
if (this.ganttConfig != null)
this.ganttConfig.addListener(this, ActivityUserPropertyEvent.class);
}
// GenericEventListener implementation
public void inform(EventObject event) {
if (!(event instanceof ActivityUserPropertyEvent))
// This should never happen, but we will verify anyway.
return;
ActivityUserPropertyEvent pEvent = (ActivityUserPropertyEvent) event;
// Make sure that the event is not an about-to-change event. This would do
// no harm, but it would be an unnecessary repaint.
if (PriorityProperty.PRIORITY_PROPERTY.equals(pEvent.getPropertyName())
&& pEvent.isChangedEvent())
cellUpdated((IlvHierarchyNode) event.getSource());
}
}
The cell editor
To be able to use a Swing JSlider as the editor for the priority column, there is a subclass of JSlider that implements the TableCellEditor interface. This class is named SliderEditor and is a nested inner class of PriorityColumn. All methods of the class SliderEditor are basic implementations of the TableCellEditor interface.
To create the editor:
protected TableCellEditor createEditor() {
return new SliderEditor();
}
Adding the column to the table
Now that you have designed the PriorityColumn class, you need to add an instance of it to the table.
To add a PriorityColumn object to the table:
In the Custom Gantt chart example, this is implemented in the addCustomTableColumns method:
protected void addCustomTableColumns() {
IlvJTable table = gantt.getTable();
table.addColumn(new PriorityColumn("Pri"));
}
Dynamic columns
When your Gantt data model implements the in-memory default data model that defines
IlvGeneralActivity or
IlvGeneralResource objects, you can add user-defined properties for:
This explanation is based on the Dynamic Columns code example found in:
Starting the sample
Explains how to start an activity-based Gantt chart with the mandatory properties of each activity and the resources assigned to some activities.
To start the Dynamic columns example:
Choose one of the following options:
double-clicking the executable JAR file
or
The following figure shows the running the dynamic columns example.
The example shows an activity-based Gantt chart with the mandatory properties of each activity and the resources assigned to some activities.
When you click Add the user-defined property columns, the example displays columns with the user-defined properties of the activities as shown in the next figure. Before clicking to display the columns for user-defined properties, you might want to adjust the width of the sample window, so that you can see the additional columns.
The following figure shows the columns for user-defined properties.
Adding customized table columns
To add customized table columns that map user-defined properties, you need to:
1. Create the user-defined property adapter.
2. Customize the formatting of the property adapter.
3. Create the configurable table column for the property adapter.
Creating the user-defined property adapter
The class
IlvAbstractUserDefinedProperty provides a common framework for accessing the user-defined properties of an
IlvUserPropertyHolder through the generic
IlvStringProperty interface.
The following subclasses of IlvAbstractUserDefinedProperty are provided:
To make to create an adapter for the user-defined property property of class propertyClass of an IlvGeneralActivity object:
Add the following code to your application:
Example 12 – Creating an adapter of user-defined properties
// Create the user-defined property adapter that can be accessed
// through the generic IlvStringProperty interface.
IlvActivityUserDefinedProperty userDefinedProperty =
new IlvActivityUserDefinedProperty(property, propertyClass);
If the property class is not provided, the default is String.
Customizing format
A Format object can be supplied to convert properties of types other than String to or from a string.
The class of the user-defined property is also used to try to convert property values of types other than
String to or from a string. The conversion that uses the user-defined property class is done by using
convert. This conversion is performed when no format is specified and the property class is not
String.
To set the format for formatting a Date or an IlvDuration:
Add the following code to your application:
Example 13 – Setting the formatting of a date or duration
// Customize formatting based on the property class.
if (propertyClass.isAssignableFrom(Date.class)) {
DateFormat dateFormat =
IlvDateFormatFactory.getDateInstance(DateFormat.DEFAULT,
getLocale());
userDefinedProperty.setFormat(dateFormat);
} else if (propertyClass.isAssignableFrom(IlvDuration.class)) {
IlvDurationFormat durationFormat =
new IlvDurationFormat(IlvDurationFormat.TIME_UNIT_MEDIUM);
durationFormat.setLenientParseMode(true);
userDefinedProperty.setFormat(durationFormat);
}
Examples of the result of applying this code can be seen in the columns
latestStart and
Total Slack in
Starting the sample.
Creating a configurable table column
The class
IlvConfigurableTableColumn defines a column that can be customized for rendering and editing a property of an
IlvHierarchyNode, that is, an activity or a resource in an
IlvJTable. This class is an extension of
IlvStringColumn, through which it implements the
IlvJTableColumn interface.
The property that is rendered is defined by an
IlvStringProperty. Property editing can be enabled separately for rows of parent activities or resources or of leaf activities. or resources.
If editing is not customized, the property will be edited in an
IlvTextFieldTableEditor. Editing can be customized at instantiation time or through a call to the method
setTableCellEditor.
If the rendering is not customized,
IlvDefaultTableCellRenderer will be used. Rendering can be customized at instantiation time or through a call to the method
setTableCellRenderer.
Instantiating a column with specific table cell editor and renderer shows how to instantiate a column with a specific table cell editor and a specific table cell renderer. You specify the cell editor as a slider and render the cell in different colors according to the priority of the activity or resource.
To instantiate a column with a specific table cell editor:
Add the following code to your application:
Example 14 – Instantiating a column with specific table cell editor and renderer
// For the "priority" property use a slider as cell editor and
// render the value with different colors.
IlvConfigurableTableColumn propertyColumn =
new IlvConfigurableTableColumn (headerValue,
userDefinedProperty,
property,
new SlideEditor(0,10,0),
new PriorityRenderer());
The effect of attributing different colors according to priority is shown in the
Priority column in
Starting the sample.
Adding the column to the table
To add the configurable column
propertyColumn to the table, add the column to the
IlvJTable instance of the Gantt chart.
To do this:
Use the following code in your application.
table.addColumn(propertyColumn);
The column is added as the last column in the table. You can then move the position of the column by using
http://java.sun.com/javase/7/docs/api/javax/swing/JTable.html#moveColumn(int, int).
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.