repto
repto

Reputation: 80

Text labels inside jfree Gantt chart bars

I have a simple Gantt chart here, that consists of a number of Tasks just like that:

TaskSeries s1 = new TaskSeries("Planned Tasks");
Task newTask = new Task("Task" +
String.valueOf(taskIndex),
new
SimpleTimePeriod(currentTime,
currentTime +
(int) distributionTime)
);
s1.add(newTask) 
final TaskSeriesCollection collection = new TaskSeriesCollection();
collection.add(s1);

JFreeChart chart = ChartFactory.createGanttChart(
"Distribution ", 
"Task", 
"Time", 
collection, 
true, 
true, 
false 
);

Is there a way to write something INSIDE each bar, representing a task? For example, if the task is made up of a two subtasks, is it possible to mark them with labels, so their names would be seen on a plot? Thanks in advance!

Upvotes: 3

Views: 7698

Answers (2)

repto
repto

Reputation: 80

Eventually i found the solution for this issue. Post it here maybe it will help some one else.

The problem is that in the exisiting drawTasks function in GanttRenderer don't have code for displaying labels. So we have to extend the GanttRenderer class with our new drawTasks function:

   public class MyGanttRenderer extends GanttRenderer {
      private transient Paint completePaint;
      private transient Paint incompletePaint;
      private double startPercent;
      private double endPercent;

      public MyGanttRenderer() {
         super();
         setIncludeBaseInRange(false);
         this.completePaint = Color.green;
         this.incompletePaint = Color.red;
         this.startPercent = 0.35;
         this.endPercent = 0.65;
      }

      protected void drawTasks(Graphics2D g2,
            CategoryItemRendererState state,
            Rectangle2D dataArea,
            CategoryPlot plot,
            CategoryAxis domainAxis,
            ValueAxis rangeAxis,
            GanttCategoryDataset dataset,
            int row,
            int column) {

         int count = dataset.getSubIntervalCount(row, column);
         if (count == 0) {
            drawTask(g2, state, dataArea, plot, domainAxis, rangeAxis, 
                  dataset, row, column);
         }

         for (int subinterval = 0; subinterval < count; subinterval++) {

            RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();

            // value 0
            Number value0 = dataset.getStartValue(row, column, subinterval);
            if (value0 == null) {
               return;
            }
            double translatedValue0 = rangeAxis.valueToJava2D(
                  value0.doubleValue(), dataArea, rangeAxisLocation);

            // value 1
            Number value1 = dataset.getEndValue(row, column, subinterval);
            if (value1 == null) {
               return;
            }
            double translatedValue1 = rangeAxis.valueToJava2D(
                  value1.doubleValue(), dataArea, rangeAxisLocation);

            if (translatedValue1 < translatedValue0) {
               double temp = translatedValue1;
               translatedValue1 = translatedValue0;
               translatedValue0 = temp;
            }

            double rectStart = calculateBarW0(plot, plot.getOrientation(), 
                  dataArea, domainAxis, state, row, column);
            double rectLength = Math.abs(translatedValue1 - translatedValue0);
            double rectBreadth = state.getBarWidth();

            // DRAW THE BARS...
            Rectangle2D bar = null;

            if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
               bar = new Rectangle2D.Double(translatedValue0, rectStart, 
                     rectLength, rectBreadth);
            }
            else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
               bar = new Rectangle2D.Double(rectStart, translatedValue0, 
                     rectBreadth, rectLength);
            }

            Rectangle2D completeBar = null;
            Rectangle2D incompleteBar = null;
            Number percent = dataset.getPercentComplete(row, column, 
                  subinterval);
            double start = getStartPercent();
            double end = getEndPercent();
            if (percent != null) {
               double p = percent.doubleValue();
               if (plot.getOrientation() == PlotOrientation.HORIZONTAL) {
                  completeBar = new Rectangle2D.Double(translatedValue0, 
                        rectStart + start * rectBreadth, rectLength * p, 
                        rectBreadth * (end - start));
                  incompleteBar = new Rectangle2D.Double(translatedValue0 
                        + rectLength * p, rectStart + start * rectBreadth, 
                        rectLength * (1 - p), rectBreadth * (end - start));
               }
               else if (plot.getOrientation() == PlotOrientation.VERTICAL) {
                  completeBar = new Rectangle2D.Double(rectStart + start 
                        * rectBreadth, translatedValue0 + rectLength 
                        * (1 - p), rectBreadth * (end - start), 
                        rectLength * p);
                  incompleteBar = new Rectangle2D.Double(rectStart + start 
                        * rectBreadth, translatedValue0, rectBreadth 
                        * (end - start), rectLength * (1 - p));
               }

            }

            Paint seriesPaint = getItemPaint(row, column);
            g2.setPaint(seriesPaint);
            g2.fill(bar);

            if (completeBar != null) {
               g2.setPaint(getCompletePaint());
               g2.fill(completeBar);
            }
            if (incompleteBar != null) {
               g2.setPaint(getIncompletePaint());
               g2.fill(incompleteBar);
            }
            if (isDrawBarOutline() 
                  && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
               g2.setStroke(getItemStroke(row, column));
               g2.setPaint(getItemOutlinePaint(row, column));
               g2.draw(bar);
            }

            CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
            if (generator != null && isItemLabelVisible(row, column)) {
               drawItemLabel(g2, dataset, row, column, plot, generator, bar, false);
            }

            // collect entity and tool tip information...
            if (state.getInfo() != null) {
               EntityCollection entities = state.getEntityCollection();
               if (entities != null) {
                  String tip = null;
                  if (getToolTipGenerator(row, column) != null) {
                     tip = getToolTipGenerator(row, column).generateToolTip(
                           dataset, row, column);
                  }
                  String url = null;
                  if (getItemURLGenerator(row, column) != null) {
                     url = getItemURLGenerator(row, column).generateURL(
                           dataset, row, column);
                  }
                  CategoryItemEntity entity = new CategoryItemEntity(
                        bar, tip, url, dataset, dataset.getRowKey(row), 
                        dataset.getColumnKey(column));
                  entities.add(entity);
               }
            }
         }
      }
   }

And to display labels on each bar (including subtask) just do the following:

 CategoryPlot plot = (CategoryPlot) chart.getPlot();

 MyGanttRenderer renderer = new MyGanttRenderer();
 plot.setRenderer(renderer);

 renderer.setBaseItemLabelGenerator(new CategoryItemLabelGenerator() {

      public String generateLabel(CategoryDataset dataSet, int series, int categories) {
       /* your code to get the label */
       return label;
      }

      public String generateColumnLabel(CategoryDataset dataset, int categories) {
          return dataset.getColumnKey(categories).toString();
      }

      public String generateRowLabel(CategoryDataset dataset, int series) {
          return dataset.getRowKey(series).toString();
      }
 });

 renderer.setBaseItemLabelsVisible(true);
 renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE9, TextAnchor.CENTER_LEFT));

And this is it. Hope it will useful for some one.

Upvotes: 1

GrahamA
GrahamA

Reputation: 5923

To add a a lable inside each item set the setBaseItemLabelGenerator in this case I'm using a IntervalCategoryItemLabelGenerator but you can implement you own by extending CategoryItemLabelGenerator.

Use this code:

CategoryPlot plot = (CategoryPlot) chart.getPlot();
CategoryItemRenderer renderer = plot.getRenderer();
renderer.setBaseItemLabelGenerator( new IntervalCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelPaint(Color.BLACK);
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(
ItemLabelAnchor.INSIDE6, TextAnchor.BOTTOM_CENTER));

You shold then get this: b

Ganttt Chart with BaseItemLabelGenerator

To customise the lables implement CategoryItemLabelGenerator

renderer.setBaseItemLabelGenerator( new CategoryItemLabelGenerator(){

    @Override
    public String generateRowLabel(CategoryDataset dataset, int row) {
        return "Your Row Text  " + row;
    }

    @Override
    public String generateColumnLabel(CategoryDataset dataset, int column) {
        return "Your Column Text  " + column;
    }

    @Override
    public String generateLabel(CategoryDataset dataset, int row, int column) {
        return "Your Label Text  " + row + "," + column;
    }


});

In this example generateLabel controls the lable in the bar, CategoryDataset, row and column can be used to determine which bar you are labelling

enter image description here

Upvotes: 8

Related Questions