JGantt Manual



Copyright © BeeSoft ®, 2010
www.beesoft.eu

 

 

Content

 

 

1 Introduction

JGantt is the Swing component for the gantt chart painting and editing.

It is powerful component, despite its complexity focused on easy-to-use programming. You can see it has the "standard gantt chart" look. But almost all you see can be customized. Your chart can look quite differently.

 

1.1 JGantt features

This chapter contains descriptions of JGantt's most essential features:

Standard view - Standard chart appearance and behavior customizable settings. There are a treetable and a chart component side by side. The treetable on the left hand side, and the chart component on the right. Exactly as you know it from other gantt components. But you can modify their appearance as you need.

Advanced treetable - The treetable has a few very interesting features: It is derived from eu.beesoft.gaia.swing.JTreeTable, so it has the features of JTable and JTree - it is easy to use it, if you are familiar with Swing programming. JTreeTable can paint "zebra" background and also show / hide columns on user selection (right click on treetable header displays popup menu with column names to hide / show). There is also built-in support for the context popup menu and double click processing.

Data binding - Model for JGantt is oriented on the easy programming and usage. One of its features is automated data binding. You can set a name of the property of your domain object you want to display in some column and JGantt displays it without any more programming. And the same it does with setting user-changed visual data to domain object.

Lazy loading - If your application works with a large dataset, it is suitable to load to the memory just the visible part of the data. JGantt treetable listens to treeexpand event and if node is expanded for the first time, it invokes method explore() on GanttModel. This is the place you can load data for node's user object and build subnodes. Do you know any more simple solution?

Layers - Gantt chart is painted in some layers. You can choose which layers you want install into gantt chart, and also you can hide / show layers at runtime. Each layer has specific purpose and paints only the gadgets it is programmed for. You can develop new layers or customize the existing. This is the way you can customize the whole chart, change the shape of timeline objects or dependency lines or add an absolutelly new functionality. In each layer you can solve also a mouse service, there is a built-in support.

Relationships - Timeline objects (tasks) can have relationship with each other. You can define constraints on such relationship (for example: this task can start after that task is finished). In the JGantt you need implement one interface on the domain objects level. And you can subclass layer for dependencies painting to get your own visualization of dependencies, if the delivered is nor suitable for you.

Actions - JGantt comes with predefined set of actions. There are actions for zoom-in and zoom-out, creating, deleting and moving nodes (and their user-objects) in the tree hierarchy, and also actions for undo and redo operations. And also abstract superclasses for the smart building another actions.

Localization - JGantt uses data from resource bundle for treetable column names and action properties. There is a built-in mechanism to do it without any programming. If your application contains more resource bundles for more languages, you can build a multi-lingual gantt chart in a very simple way. JGantt listens to the language changes at runtime and repaints itself if gets event.

 

1.2 Quick start

Here is the picture of our demo application distributed with JGantt:

The source codes are distributed as examples with JGantt, too. All of it you can find in DEMO directory in our distribution. Let's see what you have to do to build your own application based on JGantt - in 9 java files with about 40 KB texts.

Every object you want to display in JGantt treetable must implement eu.beesoft.gantt.TimelineObject interface. There are methods in this interface to get / set a start and end date of object, etc. In our example we create class Task for our domain objects. Our Task is the bean with some additional logic to handle start and end date changes:

public class Task extends AbstractBean implements TimelineObject {

	private String taskId;
	private String name;
	private String description;
	private Date startDate;
	private Date endDate;
	private long effort;
	private boolean milestone;
	private Task supertask;
	private List<Task> subtask;
	private List<Dependency> dependencies;
	private Resource assignee;


	

	public Task () {
		// empty
	}



	public String getName () {
		return name;
	}



	public void setName (String name) {
		String old = this.name;
		this.name = name;
		firePropertyChange ("name", old, name);
	}


        .....


	public Date getStartDate () {
		if ((startDate == null) && isSummary ()) {
			updateStart ();
		}
		return startDate;
	}



	public void setStartDate (Date start) {
		if (Objects.equals (this.startDate, start)) {
			return;
		}
		Date old = this.startDate;
		this.startDate = start;
		if (supertask != null) {
			supertask.updateStart ();
		}
		firePropertyChange ("startDate", old, start);
	}



	private void updateStart () {
		if (isSummary ()) {
			Date thisStart = null;
			List<Task> tasks = getSubtask ();
			for (Task task : tasks) {
				Date taskStart = task.getStartDate ();
				if (taskStart != null) {
					if ((thisStart == null) || thisStart.after (taskStart)) {
						thisStart = taskStart;
					}
				}
			}
			if (thisStart != null) {
				setStartDate (thisStart);
			}
		}
	}


        .....
}

Next, we create our model. We implement these methods:

Here is the source:

public class Model extends GanttModel {

	public Model () {
		super ();
	}



	@Override
	public Class getColumnClass (int column) {
		switch (column) {
			case 2:
			case 3:
				return Date.class;
			default:
				return super.getColumnClass (column);
		}
	}



	@Override
	public boolean isCellEditable (TreeTableNode node, int column) {
		if (column == 0) {
			return true;
		}
		return (column >= 2);
	}



	@Override
	public void explore (GanttNode node) {
		Task task = (Task) node.getUserObject ();
		for (Task t : task.getSubtask ()) {
			GanttNode child = new GanttNode (this, t);
			if (t.getSubtask ().isEmpty ()) {
				child.setExplorable (false);
			}
			node.add (child);
		}
	}



	@Override
	public boolean moveObject (TimelineObject object,
	        TimelineObject newContainer, int newIndex, UndoStep undo) {
		Task task = (Task) object;
		Task supertask = (Task) newContainer;
		undo.registerObject (task);
		undo.registerObject (supertask);
		Task oldSupertask = task.getSupertask ();
		if (supertask != oldSupertask) {
			if (oldSupertask != null) {
				undo.registerObject (oldSupertask);
				oldSupertask.removeSubtask (task);
			}
			supertask.addSubtask (task);
		}
		supertask.shiftSubtask (task, newIndex);
		return true;
	}



	@Override
	public boolean deleteObject (TimelineObject what, UndoStep undo) {
		Task task = (Task) what;
		Task parent = task.getSupertask ();
		undo.registerObject (parent);
		undo.registerObject (task);
		parent.removeSubtask (task);
		return true;
	}



	@Override
	public TimelineObject createObject (TimelineObject parent, int index,
	        UndoStep undo) {
		undo.registerObject (parent);
		Task parentTask = (Task) parent;
		Task task = new Task ();
		String id = Gantt.getNextTaskId ();
		task.setTaskId (id);
		task.setName ("Task " + id);
		parentTask.addSubtask (task);
		parentTask.shiftSubtask (task, index);
		return task;
	}



	@Override
	public String getLabel (TimelineObject object) {
		if (object instanceof Task) {
			Resource assignee = ((Task) object).getAssignee ();
			if (assignee != null) {
				return assignee.getName ();
			}
		}
		return null;
	}
}

Now we can create our DemoGantt class that subclasses JGantt. It is very simple class, it has only two methods to support mouse actions:

public class DemoGantt extends JGantt {

	private static Action createNodeAction;
	private static Action editNodeAction;
	private static Action deleteNodeAction;
	private static Action indentNodeAction;
	private static Action unindentNodeAction;
	private static Action moveNodeUpAction;
	private static Action moveNodeDownAction;
	private static Action expandAllNodesAction;
	private static Action collapseAllNodesAction;
	private static Action zoomInAction;
	private static Action zoomOutAction;
	private static Action todayAction;
	private static Action undoAction;
	private static Action redoAction;
	private List popupActions;



	public DemoGantt (GanttModel model) {
		super (model);
	}



	@Override
	protected List<Action> getPopupActions (List<GanttNode> selectedNodes) {
		if (popupActions == null) {
			popupActions = new ArrayList<Action> ();
			popupActions.add (createNodeAction);
			popupActions.add (editNodeAction);
			popupActions.add (deleteNodeAction);
			popupActions.add (null);
			popupActions.add (indentNodeAction);
			popupActions.add (unindentNodeAction);
			popupActions.add (moveNodeUpAction);
			popupActions.add (moveNodeDownAction);
		}
		return popupActions;
	}



	@Override
	public void doubleClicked (GanttNode node) {
		Task task = (Task) node.getUserObject ();
		TaskPropertiesAction.showTaskProperties (task, this);
	}
}

To keep the example here as simple as possible we ignore another auxiliary classes (as actions, form to edit task properties or date cell renderer). All of them you can find in our DEMO directory.

So what we need is put it all together. It is done in DemoGantt.main() method:

		// create model
		// it extends GanttModel
		GanttModel model = new Model ();

		// create domain objects
		// they should come from database or server in real application
		Resource worker_1 = new Resource ();
		worker_1.setName ("Smith John");

		.....

		Task task_1_1 = createTask ("Task 1.1", -20, +1, 92);
		task_1_1.setAssignee (worker_1);

		.....

		Task task_1 = createTask ("Task 1", 0, 0, 0);
		task_1.addSubtask (task_1_1);

		.....

		Project project = new Project ();
		project.setName ("Project");
		project.addResource (worker_1);
		project.addSubtask (task_1);

		.....

		// set created project as gantt model root object
		model.setRootObject (project);


		.....

		// create gantt component with "zebra" background
		// and vertical column-line-separators
		JGantt gantt = new DemoGantt (model);
		JTreeTable treeTable = gantt.getTreeTable ();
		treeTable.setAlternateBackground (treeTable
		        .getDefaultAlternateBackground ());
		treeTable.setShowVerticalLines (true);

		// create columns in gantt tree-table
		// this is the first column with task tree
		GanttColumn column = new GanttColumn ();
		column.setHeaderValue ("Task name");
		column.setBinding ("name");
		gantt.addColumn (column);

		column = new GanttColumn ();
		column.setHeaderValue ("Task ID");
		column.setBinding ("taskId");
		gantt.addColumn (column);

		.....

		// resize columns to appropriate width
		gantt.getTreeTable ().pack ();

		// create layers for gantt chart
		// order of layers is important for painting
		gantt.addLayer (new BackgroundLayer ());
		gantt.addLayer (new CalendarLayer ());
		gantt.addLayer (new GridLayer ());
		gantt.addLayer (new TodayLayer ());
		gantt.addLayer (new GanttNodeLayer ());
		gantt.addLayer (new LabelLayer ());
		gantt.addLayer (new DependencyLayer ());

		// create gantt actions
		createNodeAction = new CreateNodeAction (gantt);
		editNodeAction = new TaskPropertiesAction (gantt);

		.....
		
		build menu and toolbar, create a swing frame and show it

Note in this example:

 

2 Installation

Simply unzip downloaded file to appropriate directory (you must create such directory). You will get this structure:

    JGANTT                      - this is the root directory
        license.txt             - license agreement
        DEMO                    - Java demo example for JGantt usage, contains sources and JAR file with instructions
        DOC                     - documentation directory
             manual.html        - JGantt manual, this is what you are reading
             IMAGES             - directory with images for manual
             API                - Javadoc directory 
        LIB                     - jars directory
             jgantt_2010_2.jar  - component library
             gaia_2010_2.jar    - BeeSoft general library
             abeona_2010_3.jar  - license protector

You can copy JAR files to any appropriate place for your development. It is not necessary to keep them in the installation directory.

 

2.1 Packages

JGantt consists of these packages:

   
  • eu.beesoft.gantt
  •     - contains main classes and interfaces (JGantt, GanttModel, TimelineObject, Dependency)
       
  • eu.beesoft.gantt.action
  •     - contains all implemented actions
       
  • eu.beesoft.gantt.chart
  •     - contains chart related classes (ChartComponent, Layer, TimeSpan, TimeUnit)
       
  • eu.beesoft.gantt.treetable
  •     - contains treetable related classes (GanttTreeTable, GanttColumn, GanttNode)
       
  • eu.beesoft.gantt.undo
  •     - contains classes for undo / redo functionality (UndoStep, StateEditableObject)

    JGantt strongly uses classes from our Gaia library. This is our company general library and is available for free. Current version of this library is included in your distribution, but you can upgrade at any time. These packages from Gaia are used by JGantt:

       
  • eu.beesoft.gaia.swing
  •     - contains Swing components and classes for Swing support
       
  • eu.beesoft.gaia.util
  •     - contains utility classes

     

    2.2 License installation

    JGantt is component protected by Abeona protection system. You can freely download this component and use it, but there is one feature built-in: if JGantt is not licensed, it stops to work 10 minutes after it was constructed. You must restart your application which uses this component.

    When you purchase a license for JGantt, you will get a license file to your email. Copy this file where you want to your classpath and then complete your application with a similar code:

           JGantt gantt = new JGantt ();
    
           ... init gantt component
    
           InputStream is = SomeMyClass.class.getInputStream ("path-to-license-file");
           License license = gantt.setLicense (is);
           if (license == null) {
                throw new RuntimeException ("Ooops, something goes wrong here...");
           }
    

     

    3 Model for JGantt

    The model for JGantt consists of:

    That's all. Your domain objects must implement the given interfaces. And your model must subclass the GanttModel class to serve some methods.

     

    3.1 TimelineObject

    TimelineObject is an interface that prescribes some methods for your domain objects. Each of these methods concerns on getting / setting data for the gantt chart:

    void addPropertyChangeListener (PropertyChangeListener)     Adds instance of java.beans.PropertyChangeListener to a listener list. Date getStartDate ()     Returns the start date of this TimelineObject.
    void setStartDate (Date)     Sets the new start date for this TimelineObject.
    Date getEndDate ()     Returns the end date of this TimelineObject.
    void setEndDate (Date)     Sets the new end date for this TimelineObject.
    boolean isSummary ()     Returns true if this is a summary object (it contains some subtasks)
    boolean isMilestone ()     Returns true if this is a milestone object.
    void setMilestone (boolean)     Sets the milestone property.
    List<Dependency> getDependencies ()     Returns a list of all dependencies between this TimelineObject and other objects.
    void setDependencies (List<Dependency>)     Sets a list of all dependencies between this TimelineObject and other objects.

    A typical application's domain object that has to implement this interface is a task.

     

    3.2 Dependency

    Dependency is an interface that describes dependency between TimelineObjects. Here is the list of methods you need to implement:

    TimelineObject getSuccessor ()     Returns a dependant object.
    void setSuccessor (TimelineObject)     Sets a dependant object.
    TimelineObject getPredecessor ()     Returns an object which dependant depends on.
    void setPredecessor (TimelineObject)     Sets object which dependant depends on.
    int getType ()     Returns the type of this Dependency (one of the constants FINISH_TO_START, FINISH_TO_FINISH, START_TO_START, START_TO_FINISH).
    void setType (int)     Sets the new type of this Dependency (one of the constants FINISH_TO_START, FINISH_TO_FINISH, START_TO_START, START_TO_FINISH).

    There are some constants defined in the Dependency interface. They define the type of dependency:

    FINISH_TO_START     Constant for dependency type where dependant cannot begin until the object it depends on is complete.
    FINISH_TO_FINISH     Constant for dependency type where dependant cannot be completed until the object that it depends on is completed.
    START_TO_START     Constant for dependency type where dependant cannot begin until the object that it depends on begins.
    START_TO_FINISH     Constant for dependency type where dependant cannot be completed until the object that it depends on begins.

     

    3.3 GanttModel

    GanttModel extends JTreeTable model from Gaia library. You have to implement these methods:

    TimelineObject createObject (TimelineObject, int, UndoStep)     Creates a new domain object and adds it as child to parent (you don't need to care about treetable nodes). Register all modified objects to undo before any change.
    boolean deleteObject (TimelineObject, UndoStep)     Removes given object from its parent on domain objects level (you don't need to care about treetable nodes). Register object, its parent and all modified objects to undo before any change.
    boolean moveObject (TimelineObject, TimelineObject, int, UndoStep)     Moves given object on domain objects level (you don't need to care about treetable nodes). Register all modified objects to undo before any change.

    The methods above are designed to manipulate with objects on the domain objects level. You don't need to work with treetable nodes.

    If you want to paint in the chart component on the time lines some texts (if you use LabelLayer or TooltipLayer), you need override these methods:

    String getLabel (TimelineObject)     Returns label text for given object. This text uses LabelLayer to paint additional info to timeline object. Typically, for a task is name of the assignee probably the best result.
    String getTooltipText (TimelineObject)     Returns tooltip text for given object.

    GanttModel supports lazy loading for treetable data. The possibilities of ExplorableTreeNode, which is an ancestor of GanttNode, is emplyed here. When node is expanded and was not explored still, method explore(GanttNode) is invoked.

    void explore (GanttNode)     This method is called by GanttNode for data loading.
    Override this method to loading children of your domain object. In the typical lazy-loading implementation:

     

    4 Gantt Tree Table

    GanttTreeTable is the tree table for gantt chart. It is the left-located component of the JGantt.

    GanttTreeTable is the descendant of the eu.beesoft.gaia.swing.JTreeTable (you can read about it in the next chapter, and the next informations are accessible in API documentation).

     

    4.1 JTreeTable description

    The eu.beesoft.gaia.swing.JTreeTable class is a combination of a JTree and a JTable - a component capable of both expanding and contracting rows, as well as showing multiple columns of data.

    This component always displays a tree in the first column and the additional data in the next columns. You can see its usage in a very simple example of the directory tree.

    This component has the next features:

     

    4.2 GanttNode

    GanttNode is the only javax.swing.tree.TreeNode acceptable by a gantt tree data structure. It is a final class, so there is no way to customize it.

    Here are the key features of the GanttNode:

     

    4.3 Gantt column and data binding

    GanttColumn represents a column in the GanttTreeTable. It is a descendant of javax.swing.table.TableColumn . It supports:

    Data binding is implemented by eu.beesoft.gaia.util.Miner class. It gets values from any object and sets them in. In the first step via property accessors (getter / setter) and if appropriate accessor is not found, on the field access level. More informations about Miner class you can find in API documentation.

    GanttModel has implemented these methods related to data binding:

    Miner getMiner ()     Returns the current instance of the Miner used by this GanttModel.
    void setMiner (Miner)     Sets a new instance of the Miner for use by this GanttModel. The Miner class is designated to obtain property value on method or field level from any object. You can subclass Miner class to reach your requirements.
    Object getValueAt (TreeTableNode, int)     Returns value from given node and for given column.
    void setValueAt (TreeTableNode, int, Object)     Sets given value to the user object in the node and column.
    All you need to do for automated data binding is to set property name to gantt column. Then methods getValueAt() and setValueAt() in GanttModel can work fully automatically. If your domain objects are not suitable for data binding, override methods getValueAt() and setValueAt(). You can also subclass Miner class and set it to GanttModel by method setMiner(Miner).

    These methods support data binding in GanttColumn:

    String getBinding ()     Returns binding for this column. Binding is a property name (or dot-separated chain of property names). A value for this column is mined from this property.
    void setBinding (String)     Sets binding for this column. Binding is a property name (or dot-separated chain of property names). A value for this column is mined from this property.

     

    4.4 Localization

    A GanttColumn has built-in support for resource bundle usage. These methods are implemented:

    String getResourceBundleKey ()     Returns key used for resource bundle.
    void setResourceBundleKey (String)     Sets resource bundle key. This key is used when accessing resource bundle to get (localized) column label.
    void languageChanged (Language)     Implements LanguageListener. Invoked when environment changes. Reinitializes column header from resource bundle.

    First two methods operates with resource bundle key. It is a key under which is stored localized text in resource bundle. The third method is a listener method and is invoked, when you change language settings in application. It is invoked from eu.beesoft.gaia.util.Language.

    What resource bundle is used? The way the resource bundle is found, is described here.

     

    5 Gantt Chart

    Gantt chart is located on the right side of the JGantt component. It consists of:

    All classes of the gantt chart are in the package eu.beesoft.gantt.chart.

    There are two important classes for whole package:

    TimeUnit is an enumeration for time unit granularity. It contains constants from seconds to year and some useful methods.

    TimeSpan envelopes date range (start time - end time). Instances of TimeSpan are created by ChartComponent in its updateChart() method. They contains information about:

    All of these informations are used by chart component to prepare painting.

    The painting in gantt chart is implemented through the layers. A Layer is an abstract class that provides functionality to paint chart and interact with a user.

    When you construct a gantt, you set to the ChartComponent several layers. Chart component, when painting, iterates through them and invokes the paint(Graphics) method on each of them. The order you add layers to ChartComponent is important.

     

    5.1 Chart header

    ChartHeader paints headers above the ChartComponent instance. This component contains two headers - major and minor - and their models.

    HeaderModel is used to paint major or minor header for ChartComponent. It contains data for header columns.

    HeaderColumn is a subclass of javax.swing.table.TableColumn to hold list of TimeSpan instances. These instances are used to calculate sizes of the column.

    There is very low probability you need to customize these classes. They are created by JGantt in initialization phase. All you need to do is to use them.

     

    5.2 Chart component

    A ChartComponent is one of the most meaningful sub-components of JGantt. It is painted on the right side of JGantt (there is an instance of JTreeTable on the left).

    It co-ordinates painting with registered instances of the Layer class and dispatches events to them.

    The ChartComponent is created by JGantt in initialization phase and there is no way to customize it.

     

    5.3 Layer

    A layer is an object having a graphical representation that can be displayed in the gantt chart and that can interact with the user.

    The Layer class is the abstract superclass of the each gantt chart layer.

    The gantt ChartComponent holds a stack of user-defined layers. When the method paint(Graphics) on ChartComponent is invoked, it walks through this stack (in order the layers were added) and if the layer is visible (method isVisible() returns true) calls method paint(Graphics) on it.

    Here are the methods that eu.beesoft.gantt.chart.Layer class provides:

    JGantt getGantt ()     Returns instance of JGantt to which this Layer belongs.
    boolean isVisible ()     Returns value of property 'visible'.
    void setVisible (boolean)     Sets a new value for property 'visible'. Layer is painted only if visible = true.
    List<GanttNode> getPaintedNodes ()     Returns list of currently on-screen visible and painted gantt nodes.
    int getPosition (Date)     Returns x-coordinate for given date.
    void mouseClicked (MouseEvent)     Invoked when the mouse has been clicked on a component. In this implementation does nothing.
    void mouseEntered (MouseEvent)     Invoked when the mouse enters a component. In this implementation does nothing.
    void mouseExited (MouseEvent)     Invoked when the mouse exits a component. In this implementation does nothing.
    void mousePressed (MouseEvent)     Invoked when a mouse button has been pressed on a component. In this implementation does nothing.
    void mouseReleased (MouseEvent)     Invoked when a mouse button has been released on a component. In this implementation does nothing.
    void mouseMoved (MouseEvent)     Invoked when the mouse button has been moved on a component (with no buttons no down). In this implementation does nothing.
    void mouseDragged (MouseEvent)     Invoked when a mouse button is pressed on a component and then dragged. In this implementation does nothing.

    There is a set of implemented layers you can use. Of course, you can write your own - subclass eu.beesoft.gantt.chart.Layer and implement method paint(Graphics).

    You can also modify an existing layer - subclass it and override method you need.

     

    5.4 List of the implemented layers

    Here is the list of the implemented layers you can use:

    BackgroundLayer     Paints colored background for gantt chart.
    CalendarLayer     Paints background for weekend days.
    DependencyLayer     Paints dependencies between gantt nodes.
    GanttNodeLayer     Paints gantt nodes as time-line objects on chart component.
    GridLayer     Paints grid (horizontal and vertical lines) in gantt chart component.
    LabelLayer     Paints text label beside node.
    TodayLayer     Paints strong vertical line on chart component at given date (usually today).

     

    6 Gantt actions

    As a standard Swing component, JGantt is controlled by actions.

     

    6.1 AbstractGanttAction

    AbstractGanttAction is a base class for gantt component actions. It is not necessary to subclass this class, you can use any action. But AbstractGanttAction offers these features:

    AbstractGanttAction processes actionPerformed (ActionEvent) method to offer undo / redo support. It invokes executeAction (ActionEvent, UndoStep) method, which is an abstract method, and if it returns true, registers all changes from UndoStep in UndoManager.

     

    6.2 Localization

    AbstractGanttAction gets its properties from resource bundle. All action properties (currently: text, icon and tooltip) must be described in resource bundle. This process is automated, so you must observed some rules:

    For example, if your action class is mydomain.mypackage.MyAction, then in the resource bundle should be:

    mydomain.mypackage.MyAction.text=Text for action
    mydomain.mypackage.MyAction.icon=mydomain/mypackage/MyIcon.gif
    mydomain.mypackage.MyAction.tooltip=This is a tooltip for my action
    
    or shorter:
    MyAction.text=Text for action
    MyAction.icon=mydomain/mypackage/MyIcon.gif
    MyAction.tooltip=This is a tooltip for my action
    

    The way the resource bundle is found, is described here.

     

    6.3 Undo / Redo

    JGantt uses Swing undo package functionality to provide support for undo/redo operations.

    There are two classes in eu.beesoft.gantt.undo package for that purpose:

    StateEditableObject implements javax.swing.undo.StateEditable interface. Its constructor takes one object, and StateEditableObject can this object introspect and to remember changed properties.

    UndoStep is the descendant of javax.swing.undo.CompoundEdit class. It serves as a container of all operations for one undo / redo step. It offers two methods:

    void registerObject (Object)     Registers object to store / restore its state. If given object does not implement interface javax.swing.undo.StateEditable, the object is covered by StateEditableObject to make it eligibly for undo / redo operations. Then is object registered and its pre-state is obtained.
    void end ()     Gets the post-edit state of the required objects and ends the edit.

    If you want to process undo / redo, you have to:

    1. create an instance UndoStep
    2. call registerObject(Object) for each object that can be changed in executed action before any change occurs
    3. call end() after action finished
    4. obtain from JGantt instance an UndoManager
    5. on UndoManager instance invoke addEdit (UndoStep) method

    AbstractGanttAction supports all of these steps except step 2. So what you have to do, if your action is deriver from AbstractGanttAction, is to call registerObject(Object) for each object that can be changed in method executeAction (ActionEvent, UndoStep) only.

     

    6.4 List of the implemented actions

    Here is the list of the implemented actions you can use:

    CollapseAllNodesAction     This action collapses all nodes in the JGantt treetable.
    CreateNodeAction     This action asks GanttModel.createObject(TimelineObject, int, UndoStep) to create new domain object and then creates a new GanttNode} and includes it in hierarchy.
    DeleteNodeAction     Action asks GanttModel.deleteObject(TimelineObject, UndoStep) to delete domain object and if it is successful, removes the node from tree hierarchy.
    ExpandAllNodesAction     This action expands all nodes in the JGantt treetable.
    IndentNodeAction     This action asks GanttModel.moveObject(TimelineObject, TimelineObject, int, UndoStep) to move a domain object into domain hierarchy and then moves also corresponding GanttNode.
    MoveNodeDownAction     This action asks GanttModel.moveObject(TimelineObject, TimelineObject, int, UndoStep) to move a domain object into domain hierarchy and then moves also corresponding GanttNode.
    MoveNodeUpAction     This action asks GanttModel.moveObject(TimelineObject, TimelineObject, int, UndoStep) to move a domain object into domain hierarchy and then moves also corresponding GanttNode.
    RedoAction     This action asks JGantt.getUndoManager() to redo next operation.
    TodayAction     This action scrolls the date/time columns in the ChartComponent} so the column with today date is visible. You can set any date for this action as today date.
    UndoAction     This action asks JGantt.getUndoManager() to undo last operation.
    UnindentNodeAction     This action asks GanttModel.moveObject(TimelineObject, TimelineObject, int, UndoStep) to move a domain object into domain hierarchy and then moves also corresponding GanttNode.
    ZoomInAction     This action zooms in the content of ChartComponent.
    ZoomOutAction     This action zooms out the content of ChartComponent.

     

    7 JGantt component

    JGantt covers all above components:

    These components are constructed in the initialization phase and developer has no impact to it. You can change their properties only.

     

    7.1 Getting standard sub-components

    The standard JGantt subcomponents are accessible by these methods:

    GanttTreeTable getTreeTable ()     Returns the tree table object of this JGantt.
    ChartComponent getChartComponent ()     Returns the instance of ChartComponent.
    ChartHeader getChartHeader ()     Returns the instance of ChartHeader.
    UndoManager getUndoManager ()     Returns the undo manager for JGantt operations.
    getDividerLocation ()     Returns divider location of the split pane (between treetable and chart component).
    setDividerLocation (int)     Sets the divider location of the split pane (between treetable and chart component).

     

    7.2 Building a treetable

    Here are JGantt methods you can use to build a chart:

    GanttModel getModel ()     Returns GanttModel instance for this JGantt object. .
    void setModel (GanttModel)     Sets the new model for JGantt object.
    void addColumn (GanttColumn)     Appends a column to the end of table columns.
    GanttColumn addColumn (String, String)     Appends a column to the end of table columns.
    void removeColumn (GanttColumn)     Removes the column from the treetable.
    void removeColumn (String)     Removes a column with given key from the treetable.

    The methods working with columns are implemented in GanttTreeTable and methods in JGantt simply redirect to them.

     

    7.3 Building a chart

    Here are JGantt methods you can use to build a chart:

    void addLayer (Layer)     Adds given layer to the list of chart component layers.
    void addLayer (Layer, int)     Adds given layer to the list of chart component layers.
    void removeLayer (Layer)     Removes given layer from the list of chart component layers.
    List<Layer> getLayers ()     Returns the list of chart component layers.

    All of these methods are implemented in ChartComponent and methods in JGantt simply redirect to them.

     

    7.4 Mouse support

    JGantt has built-in mouse support, so you don't need to work with mouse listeners. Use these methods instead:

    void doubleClicked (GanttNode)     Invoked when user double clicked on the node. In this implementation does nothing. Typically, you should display properties dialog for node's user object.
    List<Action> getPopupActions (List<GanttNode>)     Returns a list of actions for selected nodes. Invoked when user right clicks on the node(s) in treetable. In this implementation does nothing and returns null, you must override it to give it some functionality.

    Method doubleClicked() is invoked from treetable and also from gantt chart component. The getPopupActions() is treetable method only. If you return a non-null list, the popup menu is displayed.

     

    7.5 Localization

    The JGantt components (treetable columns and actions) intense use resource bundle technique. These methods of JGantt are about resource bundles:

    String getResourceBundleName ()     Returns the name of the resource bundle.
    void setResourceBundleName (String)     Sets the name of resource bundle. This name must according to java.util.ResourceBundle specification. Resource bundle is then used to construct treetable columns and gantt actions.
    But resource bundle may be accessed also if you don't set its name explicitly. So how does it work?

    The main class for these purposes is eu.beesoft.gaia.util.Language. In the Swing environment is a singleton (but it has a public constructor, so you can create as many instances as you need in server environment). The singleton is accessible via method

          Language.getInstance ();
    

    which returns last created instance of Language. Using Language has big advantage when you change application's Locale. Setting this into Language provides for all LanguageListeners notification to easy reloading texts from resource bundles.

    When you take a look at Language API documentation, you can see method getText() with first argument either a resource bundle name or some object. These methods are used from JGantt and its subcomponents.

    1. if resource bundle name is set (by method JGantt.setResourceBundleName()), this resource bundle is constructed and used. Note, that resource bundle name must have a form of class name.
    2. if no resource bundle name is set, then the name of current JGantt class (its subclass) is taken and used to find resource. If resource is not found, or key with given name is not found, Language class takes a superclass name and repeats searching.
    So if you don't use method JGantt.setResourceBundleName(), you must create a properties file in the same package where your JGantt subclass is stored and with the same name as thas subclass has. In that case it will work without explicitly setting the resource bundle name and you can use the advantages of inheritance.

     

    7.6 License

    JGantt is protected by the Abeona protection system.

    It works without any license, but 10 minutes after JGantt was created it displays a warning message and stops to paint itself.

    So if you want to develop an application, which will work more than 10 minutes, you need purchase the license from BeeSoft. License is plain properties file protected by digital signature and here are methods to tell JGantt about license:

    License setLicense (InputStream)     Loads license from given licenseStream. This is a key method of library protection system.
    License getLicense ()     Returns instance of valid License or null.

    The first method has an input stream from license file as argument, and returns newly created License instance. You don't need to work with this object, just check for non-null return value. If it is null, you have some problem with that file.

     

    8 Shipping to customer

    When you will deploy your application based on the JGantt at your customer (or you will ship it), your product must contain libraries from our JGantt lib directory these JAR files:

    and also license file you obtain when you purchase JGantt.

    No other files are required.