57 45 4c 4c 20 44 4f 4e 45 21
                   

The SWT GANTT Chart Widget is a customizable GANTT chart widget written in Java for SWT/JFace applications.

The GANTT widget has taken hints from Microsoft Project as far as arrow styles and overall look and feel goes. There are features such as dependencies, checkpoints, revised dates, and much more. Nearly everything is customizable and you can zoom in to detailed day views all the way out to yearly overviews (12 zoom levels). Events can be resized, dragged and dropped and various other things.

The widget is extremely simple to use for those wishing a basic implementation, or you can customize everything down to the pixel level if you so wish. Basically, if you don’t like something, change it!

External Site

This widget is under the Eclipse Nebula project, which is a group of custom written widgets that are not part of the standard SWT API but perhaps aim to be so in the future. This site contains more information and also example snippets that are very useful to understanding how to use the widget. Please visit the Nebula homepage for more information.

Go to the Eclipse Nebula homepage

License

The Calendar Combo is released under the EPL (Eclipse Public License). It is imperative that you understand what this license allows you to do. If you do not know what this license entails, please read the full license details at the following link;

The EPL license

Compatability

The code is compiled using Java 1.4 and should work fine with all newer Java versions post 1.4.

Download

Download JAR’s, source and API documentation
View Example Code Snippets
CVS Repository

GANTT Chart Widget Usage

Here’s a few links of people/applications using the GANTT chart. If you have an application that uses the GANTT Chart widget (that is public – ideally) and want be on the list, let me know!

Screenshots

Silver Theme – Using Sections, Gantt Groups, Reverse Dependencies, Limited Scopes

Customized Blue Theme – Using Sections

Tester

The default package comes with a tester that can be used for testing out the chart and various features. The class in question is called GanttTester and has a normal main method you can run. Here’s a screenshot of the tester in action.

Documentation

Using the widget is very easy as it is a normal composite at the root level – that is then wrapped inside two more composites for providing scrollbars and optional extra features. But in the root, it’s a control that can exist anywhere any other SWT control can exist.

Normal Creation

GanttChart ganttChart = new GanttChart(parent, SWT.NONE)
...

Adding Gantt Chart Events

All events are GanttEvents regardless of type (normal, checkpoint, scopes, etc). There are a few different constructors for GanttEvents, depending on what type you are creating (types may be changed on the fly as well). To create your typical normal event that can be resized, moved, etc, here is how it’s done:

// make a 10 day long event
Calendar cStartDate = Calendar.getInstance(Locale.getDefault());
Calendar cEndDate = Calendar.getInstance(Locale.getDefault());
cEndDate.add(Calendar.DATE, 10);

GanttEvent ganttEvent = new GanttEvent(ganttChart, "Event Name", cStartDate, cEndDate, 50);
...

Revised Dates

Revised dates are simply an indication that an event didn’t start and/or end on the initially set start and/or end dates. You may set revised dates when creating a GanttEvent if you already know what they are, and you may also set them later on. By default, the widget will draw lines (when the user requests to do so) showing what the revised start and end dates are. The start date is drawn in a different color than the end date. Please see screenshot #4 above for a reference.

To set the revised dates when the GanttEvent is created, here is an example:

// make a 10 day long event
Calendar cStartDate = Calendar.getInstance(Locale.getDefault());
Calendar cEndDate = Calendar.getInstance(Locale.getDefault());
cEndDate.add(Calendar.DATE, 10);

// make some revised dates
Calendar rStartDate = Calendar.getInstance(Locale.getDefault());
Calendar rEndDate = Calendar.getInstance(Locale.getDefault());
// pretend dates were 2 days earlier than the start date and 5 days later than the end date
rStartDate.add(Calendar.DATE, -2);
rEndDate.add(Calendar.DATE, 15);

GanttEvent revisedEvent = new GanttEvent(ganttChart, "Revised", cStartDate, cEndDate, rStartDate, rEndDate, 50);

That’s it. When a user looks at the revised dates, they will see lines drawn to the dates set in the above code. To set the dates at a later point, there are two methods to call:

// set revised dates
revisedEvent.setRevisedStart(rStartDate);
revisedEvent.setRevisedEnd(rEndDate);

Adding Checkpoints

Setting an event to be a checkpoint is simply a flag. Even checkpoints can span over more than one day (despite by nature having a definition as existing only on one day, which you can control should you not like it).

If we take the above event creation code and simply add the below line somewhere after constructing the GanttEvent object:

ganttEvent.setCheckpoint(true);

Then voila, the event is now a checkpoint.

Note: A checkpoint – by definition – is a point in time on which you check something (a project, a task or similar). There is nothing in the code preventing you from treating checkpoints in any way you prefer (in fact, the code supports it). But ideally they should be 1 day long.

Adding Scopes

Scopes are slightly more complex than checkpoints, however, not overly so. The idea behind a scope is that it is linked to n number of events and its visibility, size, percentage complete, etc – is dependent on the events that it is linked to.

For example’s sake, presume we have 3 normal GanttEvents (any types are fine really). And let’s pretend they are named ge, ge2, and ge3. To create a scope for these events, we would use the following code:

GanttEvent scope = new GanttEvent(ganttChart, "Scope for events: ge, ge2, ge3");
scope.addScopeEvent(ge);
scope.addScopeEvent(ge2);
scope.addScopeEvent(ge3);

// reindex the scope to index 0 as it's our "whole project scope".
ganttChart.reindex(scope, 0);

That’s all you have to do. Usually you will want scope events to be above the events it encompasses, so it’s perfectly OK to create the scope object at the top, and add the actual events it encompasses later in your code. You can also add chart events at an index.

Should you wish to change an event on the fly to become a scope, or you wish to use a different constructor than above, you can change the type by using the following code:

ganttEvent.setScope(true); ...

Important: It’s important to know that changing start/end dates on a scope does nothing if it has scope events attached to it as it will then go by the earliest and latest dates of those attached events. If you wish to control a scope’s dates without having linked events, simply set the start/end date and do not add any scoped event children to it.

Adding Images

It’s also possible to add events that are simply image representations. You may change an event on the fly to become an image representation via two methods, or you can do it when constructing the GanttEvent. Here’s an example of both:

GanttEvent iEvent = new GanttEvent("Image", ImageCache.getImage("/picture.gif"));

And here’s how it would have to be done on the fly (assuming no image was set when constructing it):

iEvent.setImage(true);
iEvent.setPicture(ImageCache.getImage("/picture.gif"));

Important: By default, images do not resize on zoom levels that would cause the image to expand in size. However, images will shrink to try to fit a day if the width of one day is smaller than the width of the image.

Creating Dependencies / Adding Connections

A dependency is one event that is linked to another. There are a few features built-in for dependent events, but they are only as linked as you want them to be. The only thing the Gantt Widget will do for you is the following:

  • Draw lines and arrows (depending on possible customized settings) will be drawn between events.
  • Linked events will be moved together (assuming DND is enabled) if the shift key is held down when moving an event with dependencies.
  • If A depends on B, and B depends on C, and C depends on A (infinite loop), this is OK! Such links are fully supported (even if they are illogical).

Anything else will have to be handled by you through listening to events or overriding methods or via implementing interfaces.

Creating the links themselves is very easy. Here is some example code that will be very self-explanatory. Assume we have events ge and ge2. ge2 is dependent on ge.

// create dependency
ganttChart.addConnection(ge, ge2);

That is truly everything you have to do. Dependencies may be modified on the fly.

Changing Event Colors

To change the color of an event, there are two methods (you may also control other properties via overriding the default color settings). One controls the foreground, and one controls the background. Both are used for drawing events in a gradient way, or only one if the gradient feature is turned off.

Here’s a sample where the event colors are changed. The example uses the built in ColorCache component which caches all colors so that you don’t run out of handles, but you may of course create colors in any way you want. Assume the event object is named “ganttEvent”.

// set plain color and gradient color.
// both are used to create the gradient (if turned on in settings).
ganttEvent.setStatusColor(ColorCache.getInstance().getColor(246, 159, 82));
ganttEvent.setGradientStatusColor(ColorCache.getInstance().getColor(252, 225, 201));

Listening to Events

Listening to events is very easy. The IGanttEventListener lets you listen to everything that happens to an event.

ganttChart.addGanttEventListener(new IGanttEventListener() {

   public void eventDoubleClicked(GanttEvent event, MouseEvent me) {
   }

   public void eventPropertiesSelected(GanttEvent event) {
   }

   public void eventsDeleteRequest(List<GanttEvent> events, MouseEvent me) {
   }

   public void eventSelected(GanttEvent event, List<GanttEvent> allSelectedEvents, MouseEvent me) {
   }

   public void eventsMoved(List<GanttEvent> events, MouseEvent me) {
   }

   public void eventsResized(List<GanttEvent> events, MouseEvent me) {
   }

   public void zoomedIn(int newZoomLevel) {
   }

   public void zoomedOut(int newZoomLevel) {
   }

   public void zoomReset() {
   }

   etc...

});

There is also an adapter if you don’t want to implement all the methods for each listener you are introducing. The adapter is called GanttEventListenerAdapter.