Performance
The following is a list of items that need special attention in order to avoid performance degradation:
Gantt Chart Model
The Gantt chart model interface IGanttChartModel defines a method, which returns an iterator that can be used to iterate over the timeline objects stored on a Gantt chart node. The method is called getTimelineObjectsIterator(ILayer, ITimeSpan) and gets invoked very frequently. It is important that this method returns an iterator very quickly but at the same time the number of timeline objects that are iterated over should not be very large. A large number of timeline objects would cause long running rendering operations. These two goals are often enough in conflict with each other.
The default Gantt chart node implementation uses a list to store its timeline objects. The easiest and fastest way to return an iterator for a list is to simply call List.iterator(). Unfortunately this will result in an iterator over all timeline objects of the list / node. Applications that only store one timeline object per node (for example project planning software that shows one task bar per row) can use this approach. However, in manufacturing execution systems it is quite common to have hundreds or even thousands of timeline objects per row. If this is the case then then the timeline object layer would iterate over all timeline objects per row and then decide for each one of them whether they need rendering or not.
The TimelineObjectIterator class solves this performance problem by performing a binary search to find the first visible timeline object for a given time span. The time span used for this search is the span that was passed to the getTimelineObjectsIterator(ILayer, ITimeSpan) method. This iterator will only work if the list of timeline objects passed to it is sorted based on start time and if any timeline object A that starts later than timeline object B also finishes later than B (A.start > B.start && A.end > B.end). If this precondition can not be met then it is up to the application developers to take advantage of their application data model in order to find out whether there are more efficient strategies for returning an iterator that balances 'time to create' and 'number of timeline objects'.
Renderers
FlexGantt uses various types of renderers for its tree table, the timeline objects, the row header, and so on. Each of these renderers returns a component to which the actual rendering is delegated. Swing components can have any complexity they like. They can be containers that contain several other components (or containers). Each one of these components can perform complex calculations and event notifications. It is rather obvious that all of this can result in bad rendering performance.
Renderers should try to limit their complexity and perform low level rendering operations directly in their own paintComponent() method instead of composing their appearance based on layout managers and several children components. Renderer components can also disable several of their standard features (validation, event notification) because these are only needed when the components are used inside a container hierarchy (which renderers aren't). The following are several methods that can often be overriden.
@Override
public void validate() {
}
@Override
public void invalidate() {
}
@Override
public void revalidate() {
}
@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue) {
}
@Override
public void firePropertyChange(String propertyName, byte oldValue,
byte newValue) {
}
@Override
public void firePropertyChange(String propertyName, char oldValue,
char newValue) {
}
@Override
public void firePropertyChange(String propertyName, double oldValue,
double newValue) {
}
@Override
public void firePropertyChange(String propertyName, float oldValue,
float newValue) {
}
@Override
public void firePropertyChange(String propertyName, long oldValue,
long newValue) {
}
@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
}
@Override
public void firePropertyChange(String propertyName, short oldValue,
short newValue) {
}
@Override
public void repaint() {
}
@Override
public void repaint(int x, int y, int width, int height) {
}
@Override
public void repaint(long tm) {
}
