Index of a subtask

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Nitro

Index of a subtask

Post by Nitro » Thu May 19, 2005 2:16 pm

How I can get the index of a subtask in a gantt chart when I click left button of the mouse.

Now I can get the index of the main task from the CategoryItemEntity but I can't know which is the subtask I clicked.

Thanks.

Nitro

The source code

Post by Nitro » Thu May 19, 2005 2:39 pm

EntityCollection entities = chart.getChartRenderingInfo().getEntityCollection();
Insets insets = getInsets();
int x = (int) ((e.getTrigger().getX() - insets.left) / chart.getScaleX());
int y = (int) ((e.getTrigger().getY() - insets.top) / chart.getScaleY());
entity = entities.getEntity(x, y);

CategoryPlot plot = chart.getChart().getCategoryPlot();

GanttCategoryDataset dataset = (GanttCategoryDataset)plot.getDataset();
TaskSeriesCollection taskseries = (TaskSeriesCollection)plot.getDataset();

List list = taskseries.getRowKeys();
TaskSeries taskserie = (TaskSeries)list.get(0);
List tasks = taskserie.getTasks();

Task task = (Task)tasks.get(((CategoryItemEntity)entity).getCategoryIndex());

if( task.getSubtaskCount() == 0 )
{
task.setPercentComplete(0.0);
taskseries.remove(taskserie);
taskseries.add(taskserie);
}else
{
Task subTask = task.getSubtask( ??? );
subTask.setPercentComplete(0.0);
taskseries.remove(taskserie);
taskseries.add(taskserie);
}

Craig

I want this too

Post by Craig » Thu Sep 29, 2005 9:17 pm

I am dying to know the answer to this also... Does anyone know?? I need to display tooltips of individual subtasks, but right now my program just gives me the time that the overall task takes place in, which is useless to me.

angel
Posts: 899
Joined: Thu Jan 15, 2004 12:07 am
Location: Germany - Palatinate

Post by angel » Fri Sep 30, 2005 7:18 am

Maybe extending the IntervalCategoryToolTipGenerator and setting yours in renderer.setBaseToolTipGenerator() ?

Craig

balh

Post by Craig » Tue Oct 25, 2005 7:54 pm

I am already extending the IntervalCategoryToolTipGenerator and setting it in setBaseToolTipGenerator...

My code for the extension is this:

Code: Select all

private class CustomToolTipGenerator extends IntervalCategoryToolTipGenerator {
      
      public CustomToolTipGenerator() {
         super();
      }

      @Override
      protected Object[] createItemArray(CategoryDataset dataset, int row, int column) {
         /**
          * Creates the array of items that can be passed to the 
          * <code>MessageFormat</code> class for creating labels.
          *
          * @param dataset  the dataset (<code>null</code> not permitted).
          * @param row  the row index (zero-based).
          * @param column  the column index (zero-based).
          *
          * @return The items (never <code>null</code>).
          */
             GregorianCalendar cal = new GregorianCalendar();
             Object[] result = new Object[5];
             result[0] = dataset.getRowKey(row).toString();
             result[1] = dataset.getColumnKey(column).toString();
             
             Number value = dataset.getValue(row, column);
             cal.setTimeInMillis(value.longValue());
             result[2] = cal.getTime();
             
             if (dataset instanceof IntervalCategoryDataset) {
                 IntervalCategoryDataset icd = (IntervalCategoryDataset) dataset;
                 TaskSeriesCollection collection = (TaskSeriesCollection) icd;
                 Number start = collection.getStartValue(row, column);
                 Number end = collection.getEndValue(row, column);
                 cal.setTimeInMillis(start.longValue());
                 result[3] = cal.getTime(); 
                 cal.setTimeInMillis(end.longValue());
                 result[4] = cal.getTime();
             }
             return result;
         }
      }
My problem here is that the time is being displayed as the time for the full task. I do not know how to get the value for the particular subtask for which the mouse is hovering over. If anyone knows how to do this that would be most appreciated.

Craig

image

Post by Craig » Tue Oct 25, 2005 8:09 pm

Btw, here is a screenshot of the problem:

Image

Notice how the dates say the 16th thru the 22nd, but the task is only a couple days in length.
thanks again
Craig

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Wed Oct 26, 2005 10:09 am

Getting this to work will require some special case code in the drawTasks() method in the GanttRenderer. Near the end of that method, you'll see that the tool tip generator is used to create a tool tip for the subtask, but it never sees the sub task index (so the same tool tip is generated for all subtasks). Here you could check for a special class of tool tip generator, and if it is found call a special method for generating the tooltip (one that accepts the subtask index as an argument). It would probably be worth also creating a new subclass of the CategoryItemEntity class to record the subtask index in the entity also.

The above would be a bit of an ugly hack, but probably in keeping with the rest of the Gantt chart code. :lol:
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Craig

fixed

Post by Craig » Thu Oct 27, 2005 7:55 pm

Thanks for the reply David, that really helped!
I have the Gantt chart now working with subtask tooltips. I have yet to implement the new subclass of CategoryItemEntity but that also does sound like a good idea. What I did was just overload all the methods that are required to make a tool tip in a Gantt chart. You can edit the code and make your own jars..but for now I am just extending everything and writing custom private classes. So, here is the code to do this if you want your subtasks to display appropriate tool tips.:

First, I changed this part in the drawTasks() method in the GanttRenderer:

Code: Select all

// collect entity and tool tip information...
              if (state.getInfo() != null) {
                  EntityCollection entities 
                      = state.getInfo().getOwner().getEntityCollection();
                  if (entities != null) {
                      String tip = null;
                      if (getToolTipGenerator(row, column) != null) {
                          tip = ((CustomToolTipGenerator)getToolTipGenerator(row, column)).generateToolTip(
                              dataset, row, column, subinterval
                          );
                      }
                      String url = null;
                      if (getItemURLGenerator(row, column) != null) {
                          url = getItemURLGenerator(row, column).generateURL(
                              dataset, row, column
                          );
                      }
                      CategoryItemEntity entity = new CategoryItemEntity(
                          bar, tip, url, dataset, row, 
                          dataset.getColumnKey(column), column
                      );
                      entities.add(entity);
                  }
              }
(This is at the very bottom of the drawTasks() method.)
The only change in the above is to pass the subinterval into generateToolTip() and also to cast getToolTipGenerator to CustomToolTipGenerator.

So now we are calling generateToolTip, but this overloaded method doesn't exist yet, so I created it in my CustomToolTipGenerator class, which looks like this:


Code: Select all

private class CustomToolTipGenerator extends IntervalCategoryToolTipGenerator {
      
      public CustomToolTipGenerator() {
         super();
      }

      @Override
      public String generateToolTip(CategoryDataset arg0, int arg1, int arg2) {
         // TODO Auto-generated method stub
         return super.generateToolTip(arg0, arg1, arg2);
      }
      
      public String generateToolTip(CategoryDataset arg0, int arg1, int arg2, int arg3) {
         // TODO Auto-generated method stub
         return generateLabelString(arg0, arg1, arg2, arg3);
      }
      
      /**
       * Generates a for the specified item.
       *
       * @param dataset  the dataset (<code>null</code> not permitted).
       * @param row  the row index (zero-based).
       * @param column  the column index (zero-based).
       *
       * @return The label (possibly <code>null</code>).
       */
      protected String generateLabelString(CategoryDataset dataset, 
                                           int row, int column, int subtask) {
          if (dataset == null) {
              throw new IllegalArgumentException("Null 'dataset' argument.");
          }
          String result = null;   
          Object[] items = createItemArray(dataset, row, column, subtask);
          result = MessageFormat.format(getLabelFormat(), items);
          return result;
      }

      @Override
      protected Object[] createItemArray(CategoryDataset dataset, int row, int column) {
         /**
          * Creates the array of items that can be passed to the 
          * <code>MessageFormat</code> class for creating labels.
          *
          * @param dataset  the dataset (<code>null</code> not permitted).
          * @param row  the row index (zero-based).
          * @param column  the column index (zero-based).
          *
          * @return The items (never <code>null</code>).
          */
             GregorianCalendar cal = new GregorianCalendar();
             Object[] result = new Object[5];
             result[0] = dataset.getRowKey(row).toString();
             result[1] = dataset.getColumnKey(column).toString();
             
             Number value = dataset.getValue(row, column);
             /*if (getNumberFormat() != null) {
                 result[2] = getNumberFormat().format(value);  
             }
             else if (getDateFormat() != null) {
                 result[2] = getDateFormat().format(value);
             }*/
             //result[2] = getDateFormat().format(value);
             cal.setTimeInMillis(value.longValue());
             result[2] = cal.getTime();
             
             if (dataset instanceof IntervalCategoryDataset) {
                 IntervalCategoryDataset icd = (IntervalCategoryDataset) dataset;
                 TaskSeriesCollection collection = (TaskSeriesCollection) icd;
                 //TODO: add a mouselistener here to find out which subtask is being hovered over
                 //this way tool tips will be able to be displayed correctly.
                 Number start = collection.getStartValue(row, column, 0); //row, column, subtask
                 //Number start = icd.getStartValue(row, column);
                 Number end = collection.getEndValue(row, column, 0);
                 //if (getNumberFormat() != null) {
                 cal.setTimeInMillis(start.longValue());
                 result[3] = cal.getTime();
                 cal.setTimeInMillis(end.longValue());
                 result[4] = cal.getTime();
             }
             return result;
         }
      
      protected Object[] createItemArray(CategoryDataset dataset, int row, int column, int subtask) {
         /**
          * Creates the array of items that can be passed to the 
          * <code>MessageFormat</code> class for creating labels.
          *
          * @param dataset  the dataset (<code>null</code> not permitted).
          * @param row  the row index (zero-based).
          * @param column  the column index (zero-based).
          *
          * @return The items (never <code>null</code>).
          */
             GregorianCalendar cal = new GregorianCalendar();
             Object[] result = new Object[5];
             result[0] = dataset.getRowKey(row).toString();
             result[1] = dataset.getColumnKey(column).toString();
             
             Number value = dataset.getValue(row, column);
             /*if (getNumberFormat() != null) {
                 result[2] = getNumberFormat().format(value);  
             }
             else if (getDateFormat() != null) {
                 result[2] = getDateFormat().format(value);
             }*/
             //result[2] = getDateFormat().format(value);
             cal.setTimeInMillis(value.longValue());
             result[2] = cal.getTime();
             
             if (dataset instanceof IntervalCategoryDataset) {
                 IntervalCategoryDataset icd = (IntervalCategoryDataset) dataset;
                 TaskSeriesCollection collection = (TaskSeriesCollection) icd;
                 //TODO: add a mouselistener here to find out which subtask is being hovered over
                 //this way tool tips will be able to be displayed correctly.
                 Number start = collection.getStartValue(row, column, subtask); //row, column, subtask
                 //Number start = icd.getStartValue(row, column);
                 Number end = collection.getEndValue(row, column, subtask);
                 //if (getNumberFormat() != null) {
                 cal.setTimeInMillis(start.longValue());
                 result[3] = cal.getTime();
                 cal.setTimeInMillis(end.longValue());
                 result[4] = cal.getTime();
             }
             return result;
         }
      }
This method overloads createItemArray, generateLabelString, and generateToolTip.
Hope this helps everyone!
And thanks again David, I really appreciate the help.
Craig :D

java_development

Post by java_development » Wed Nov 09, 2005 7:31 pm

I have a subtask that I want to be able to label the start date and end date on the bar. I have extended the GanttRender and override the drawTasks() and create the CustomToolTipGenerator. My question is: How do I call these this so that I can generate the label? Please help!

princeahan
Posts: 2
Joined: Mon Nov 14, 2005 8:30 am

still don't work

Post by princeahan » Mon Nov 14, 2005 9:08 am

I do like this,but still don't show correctly.the sub task show the tips same as the main task.
could you give me your source compelely?

Eyefinity-Rick

Are there any plans to add this support to the next version?

Post by Eyefinity-Rick » Sat Feb 04, 2006 12:23 am

Seems like this is something a lot of folks (us included) would like to have.

POruganti
Posts: 10
Joined: Tue May 08, 2007 1:09 pm
Location: LONDON

Post by POruganti » Fri May 18, 2007 5:58 pm

Hi,

I am also trying to get the index of subtask.
I need to get the index of subtask in drawTasks() method of GanttRenderer and then I need to fetch the description for that subtask.

With this code, I can fetch all the subtasks index.

List list = taskseries.getRowKeys();
TaskSeries taskserie = (TaskSeries)list.get(0);
List tasks = taskserie.getTasks();

But in the GanttRenderer, there is a for loop which draws all the subtasks with the subinterval count.

I want to know in this for loop, how can i access individual subtask's description as subinterval's index is not a subtask's index.

Depending on the subtask description, i need to set the color of the rectangle.


Please help me out to achieve this.

Thanks,
Pavani.

selene
Posts: 1
Joined: Fri Sep 04, 2009 10:21 am
antibot: No, of course not.

Re: Index of a subtask

Post by selene » Tue Sep 08, 2009 8:08 am

Hello,
does anybody have a solution for this problem by now? I tried out Craigs solution, but it doesn't work for me because of a Class Cast Exception when I try to cast to CustomToolTipGenerator.
And beyond that do I not know how to create an appropriate MouseListener which is mentioned in Craigs code...
I even tried many ways of Trial And Error but none could give me a way to see the desired tooltips.

I would be glad to read of someone who managed this problem :)

Greetings, Selene

yourganesan
Posts: 1
Joined: Tue Dec 20, 2011 5:24 pm
antibot: No, of course not.

Re: Index of a subtask

Post by yourganesan » Tue Dec 20, 2011 5:27 pm

Wow.. It really worked great.. Thanks for the post.. Really appreciated.. Spread the news guys.. there are a ton of people looking out a solution for this problem.. Thanks guys..

Locked