skip to main content
Programmer's documentation > Developing with the JViews Gantt SDK > Gantt charts > Customizing table columns
 
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.
*Running the example
*Describes how to run the customData sample.
*Tree column icons
*Describes how to customize the expanded and collapsed icons for parent activities in a column.
*The PriorityColumn class
*Describes how the custom table-column class is implemented.
*Adding the column to the table
*Explains how to add a PriorityColumn object to the table.
*Dynamic columns
*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:
<installdir>/jviews-gantt/samples/customData/src/customData/CustomGanttExample.java
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:
<installdir>/jviews-gantt/samples/customData/src/customData/PriorityColumn.java
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:
*Override the createEditor method of the class PriorityColumn that it inherits from IlvAbstractJTableColumn:
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:
*Add the column to the IlvJTable instance of the chart from its getTable method.
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:
*Activities in an IlvGanttChart
*Resources in an IlvScheduleChart
This explanation is based on the Dynamic Columns code example found in:
<installdir>/jviews-gantt/codefragments/table/dynamicColumns. You can find the corresponding source code in:
<installdir>/jviews-gantt/codefragments/table/dynamicColumns/src/DynamicColumnSample.java
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
*Use Ant as explained in Starting the samples.
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.
This adapter can be accessed by the generic IlvStringProperty interface.
To create the adapter, instantiate an IlvAbstractUserDefinedProperty subclass. See Creating the user-defined property adapter.
2. Customize the formatting of the property adapter.
The customization is based on the property class. See Customizing format.
3. Create the configurable table column for the property adapter.
To create the configurable column, instantiate an IlvConfigurableTableColumn object. See Creating a configurable table column.
4. Add the table column to the table. See Adding the column to the table.
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:
*IlvActivityUserDefinedProperty for the user-defined properties of an IlvGeneralActivity object.
*IlvResourceUserDefinedProperty for the user-defined properties of an IlvGeneralResource object.
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 columnslatestStart 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.