I want to draw some vertical lines to track the tasks as shown by the red lines in the figure below. I believe the lines can be drawn using the Gantt Renderer.
What I want to is store the coordinates of the end points of the lines during drawing of the tasks and then finally draw those lines in the plot.
I want to know if there is a method that lets you draw anything on the plot and whether this is the right way to approach this problem.
Here is my code for the gantt renderer:
public class Renderer extends GanttRenderer {
private Color markerColorChannel = Color.BLUE;
private Color markerColorFunction = new Color(138,43,226);
private Color functionDurationMarkerColor = new Color(0,100,0);
private boolean functionTrace = false;
private List<ProcessorTask> listOfDrawingTask = new ArrayList<ProcessorTask>();
/**
* CONSTRUCTOR
*
* @param model
*/
public Renderer() {
}
/**
* This method is used to draw the task/subtasks for each channel or row item.
* The method is called each time the gannt chart is repainted: including zooming,
* sliding and changes to gannt chart input configurations.
*
* @param g2 The graphics device.
* @param state The renderer state.
* @param dataArea The data plot area.
* @param plot The plot.
* @param domainAxis The domain axis.
* @param rangeAxis The range axis.
* @param dataset The set of data to be drawn
* @param row The row index (zero-based).
* @param column Indicates the index of the task item to be drawn (starts from zero)
*/
// DRAW TASKS
@Override
protected void drawTasks(Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
ValueAxis rangeAxis, GanttCategoryDataset dataset, int row, int column) {
try {
// plot.setDomainCrosshairVisible(true);
// plot.setRangeCrosshairVisible(true);
// System.out.println("ROW: " + row + " COL: " + column + " time " + System.currentTimeMillis());
/* Get the total number of subtasks in the channel or row item*/
int count = dataset.getSubIntervalCount(row, column);
/* If the item contains no subtask the count is zero. Then draw only the single task. */
if (count == 0) {
drawTask(g2, state, dataArea, plot, domainAxis, rangeAxis, dataset, row, column);
}
/*If the item contains subtasks, loop through each of them*/
for (int subinterval = 0; subinterval < count; subinterval++) {
RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
Number subtaskStart; // start time
Number subtaskEnd; // end time
double subtaskStartTranslated;
double subtaskEndTranslated;
/* Sub task start time */
subtaskStart = dataset.getStartValue(row, column, subinterval);
if (subtaskStart == null) {
System.out.println("No starting time for subtask " + subinterval + " item " + column + " found!");
return;
}
subtaskStartTranslated = rangeAxis.valueToJava2D(subtaskStart.doubleValue(), dataArea, rangeAxisLocation);
/* Sub task end time */
subtaskEnd = dataset.getEndValue(row, column, subinterval);
if (subtaskEnd == null) {
System.out.println("No end time for subtask " + subinterval + " item " + column + " found!");
return;
}
subtaskEndTranslated = rangeAxis.valueToJava2D(subtaskEnd.doubleValue(), dataArea, rangeAxisLocation);
/*Set the rectangular bar properties*/
double rectYAxisStart;
double rectLength;
double rectBreadth;
Rectangle2D bar = null;
Number percent; // task percentage completion
rectYAxisStart = calculateBarW0(plot, plot.getOrientation(), dataArea, domainAxis, state, row, column);
rectLength = Math.abs(subtaskEndTranslated - subtaskStartTranslated);
rectBreadth = state.getBarWidth();
percent = dataset.getPercentComplete(row, column, subinterval);
/*Draw the rectangular bar*/
if (plot.getOrientation() == PlotOrientation.HORIZONTAL) { // horizontal is applied for the ganntchart
bar = new Rectangle2D.Double(subtaskStartTranslated, rectYAxisStart, rectLength, rectBreadth);
} else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
bar = new Rectangle2D.Double(rectYAxisStart, subtaskStartTranslated, rectBreadth, rectLength);
}
/*Drawing the task completion bar in the subtask bar:
* This feature is currently not needed in the gantt chart*/
/* Painting the task/subtask */
Paint seriesPaint = getItemPaint(row, column, subinterval);
g2.setPaint(seriesPaint);
g2.fill(bar);
if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
g2.setStroke(getItemStroke(row, column));
g2.setPaint(getItemOutlinePaint(row, column));
g2.draw(bar);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method is used to paint the subtasks of a channel or row item
* @param row
* @param col Index of the channel or the row item
* @param subinterval Index of the subtask
* @return Paint Item
*/
private Paint getItemPaint(int row, int col, int subinterval) {
return this.listOfDrawingTask.get(col).getSubTaskColorList().get(subinterval);
}
}
Update:
It seems that the LineAnnotations is the best way to implement the lines. Link1
The lines can be added onto the Gantt Chart using the CategoryLineAnnotation. The line annotations are added to the plot.
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.addAnnotation(new CategoryLineAnnotation("Category 2", 5.0,
"Category 4", 8.0, Color.red, new BasicStroke(2.0f)));
Here is an MCV example by David Gilbert:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------------
* BarChartDemo1.java
* ------------------
* (C) Copyright 2003-2007, by Object Refinery Limited and Contributors.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): ;
*
* Changes
* -------
* 09-Mar-2005 : Version 1 (DG);
*
*/
package org.jfree.chart.demo;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.CategoryLineAnnotation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
/**
* A simple demonstration application showing how to create a bar chart.
*/
public class BarChartDemo1 extends ApplicationFrame {
/**
* Creates a new demo instance.
*
* @param title the frame title.
*/
public BarChartDemo1(String title) {
super(title);
CategoryDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart, false);
chartPanel.setPreferredSize(new Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Returns a sample dataset.
*
* @return The dataset.
*/
private static CategoryDataset createDataset() {
// row keys...
String series1 = "First";
String series2 = "Second";
String series3 = "Third";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1.0, series1, category1);
dataset.addValue(4.0, series1, category2);
dataset.addValue(3.0, series1, category3);
dataset.addValue(5.0, series1, category4);
dataset.addValue(5.0, series1, category5);
dataset.addValue(5.0, series2, category1);
dataset.addValue(7.0, series2, category2);
dataset.addValue(6.0, series2, category3);
dataset.addValue(8.0, series2, category4);
dataset.addValue(4.0, series2, category5);
dataset.addValue(4.0, series3, category1);
dataset.addValue(3.0, series3, category2);
dataset.addValue(2.0, series3, category3);
dataset.addValue(3.0, series3, category4);
dataset.addValue(6.0, series3, category5);
return dataset;
}
/**
* Creates a sample chart.
*
* @param dataset the dataset.
*
* @return The chart.
*/
private static JFreeChart createChart(CategoryDataset dataset) {
// create the chart...
JFreeChart chart = ChartFactory.createBarChart(
"Bar Chart Demo 1", // chart title
"Category", // domain axis label
"Value", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips?
false // URLs?
);
// NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
// set the background color for the chart...
chart.setBackgroundPaint(Color.white);
// get a reference to the plot for further customisation...
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.white);
plot.addAnnotation(new CategoryLineAnnotation("Category 2", 5.0,
"Category 4", 8.0, Color.red, new BasicStroke(2.0f)));
// ******************************************************************
// More than 150 demo applications are included with the JFreeChart
// Developer Guide...for more information, see:
//
// > http://www.object-refinery.com/jfreechart/guide.html
//
// ******************************************************************
// set the range axis to display integers only...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
// disable bar outlines...
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setDrawBarOutline(false);
// set up gradient paints for series...
GradientPaint gp0 = new GradientPaint(0.0f, 0.0f, Color.blue,
0.0f, 0.0f, new Color(0, 0, 64));
GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.green,
0.0f, 0.0f, new Color(0, 64, 0));
GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.red,
0.0f, 0.0f, new Color(64, 0, 0));
renderer.setSeriesPaint(0, gp0);
renderer.setSeriesPaint(1, gp1);
renderer.setSeriesPaint(2, gp2);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(
CategoryLabelPositions.createUpRotationLabelPositions(
Math.PI / 6.0));
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
/**
* Starting point for the demonstration application.
*
* @param args ignored.
*/
public static void main(String[] args) {
BarChartDemo1 demo = new BarChartDemo1("Bar Chart Demo 1");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}