Multiline ToolTips for multi datasets

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

Multiline ToolTips for multi datasets

Post by Sergey » Tue Jul 23, 2002 5:40 am

Hello,

I'm working on charts with dynamic multidatasets (timeseries). I needed to see tool tip containing all the values with a single date, of course, better on separate lines, so I made some modifications to TimeSeriesToolTipGenerator.
Now the problem I have is when the data gets added to the chart and the oldest set is deleted the ToolTipGenerator throws an exception (XYDataset .getYValue(int,int)).
I've tried to "fix" it by comparing series id with the number of series,etc. - no luck.

Could you please advise what should be done to implement the desired behavior. Chart/ToolTipGenerator/exception are below.

Thank you very much!


:::::::::::::::::::::::: Chart :::::::::::::::::::::::::
public class ChartTimeSeries extends JPanel implements Runnable {
static final Color[] _LCLR = {
new Color(0xff0000), new Color(0x0000ff), new Color(0x00aaaa), new Color(0x00FFFF),
new Color(0xffa500), new Color(0xC0DCC0), new Color(0xFFCCFF), new Color(0x45ab1f),
new Color(0x90422d), new Color(0xa0a0a0), new Color(0x14ff14), new Color(0xFFFF00)
};
final String [] legend = new String[]{"d0","d1","d2","d3","d4",
"d5","d6","d7","d8","d9",
"d10","d11"};

Color c = new Color(0xCCCCFF);
Calendar cal;
JFreeChart pieChart;
JFreeChart totChart;
ChartPanel piePanel;
ChartPanel totPanel;
BasicTimeSeries [] bts;
TimeSeriesCollection tsc;
DefaultPieDataset pieData;
Font fn0 = new Font(null,0,10);
Color bg0 = Color.decode("0x666699");
Thread thr;

public ChartTimeSeries(){
cal = new GregorianCalendar();
setLayout(new GridLayout(2,1));
//------------------------------------------------------------------ Pie
pieData = new DefaultPieDataset();
Double v = new Double(100 / legend.length);

for (int i = 0; i < legend.length; i++){
pieData.setValue(legend, v);
}
pieChart = ChartFactory.createPie3DChart("Test", pieData, true);

Pie3DPlot plot = (Pie3DPlot)pieChart.getPlot();
plot.setSeriesPaint(new Paint[] { _LCLR[0],_LCLR[1],_LCLR[2],_LCLR[3],_LCLR[4],_LCLR[5],
_LCLR[6],_LCLR[7],_LCLR[8],_LCLR[9],_LCLR[10],_LCLR[11]});
plot.setSectionLabelType(5);
plot.setValueFormatString("######0.0");
plot.setInteriorGapPercent(0.23);
plot.setSectionLabelGapPercent(0.15);
TextTitle title = (TextTitle)pieChart.getTitle(0);
Paint p = new GradientPaint(0, 0, c, 0, 200, bg0);
pieChart.setBackgroundPaint(p);
piePanel = new ChartPanel(pieChart);
piePanel.setBackground(getBackground());
add(piePanel);
//---------------------------------------------------------------- Chart
bts = new BasicTimeSeries[legend.length];
tsc = new TimeSeriesCollection();
long tm = System.currentTimeMillis();
for (int i=0; i<bts.length; i++){
cal.setTimeInMillis(tm - 60000);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
bts = new BasicTimeSeries(legend, null, null, FixedMillisecond.class);
for (int j=0; j<12; j++){
cal.add(Calendar.SECOND, 5);
Double d = new Double(i * j);
bts.add(new FixedMillisecond(cal.getTimeInMillis()), d);
}
tsc.addSeries(bts);
}
totChart = ChartFactory.createTimeSeriesChart("INIT...", null, null, tsc, false, legend.length);
Paint pnt = new GradientPaint(0, 0, bg0, 0, 200, c);
totChart.setBackgroundPaint(pnt);
XYPlot plot2 = (XYPlot)totChart.getPlot();
plot2.setSeriesPaint(new Paint[] { _LCLR[0],_LCLR[1],_LCLR[2],_LCLR[3],_LCLR[4],_LCLR[5],
_LCLR[6],_LCLR[7],_LCLR[8],_LCLR[9],_LCLR[10],_LCLR[11]});
ValueAxis axis = plot2.getDomainAxis();
axis.setAutoRange(true);
axis.setFixedAutoRange(60000.0); // 60 seconds
axis = plot2.getRangeAxis();

HorizontalDateAxis ax = (HorizontalDateAxis)plot2.getDomainAxis();
ax.setAutoTickUnitSelection(true);
ax.setTickUnit(new DateUnit(Calendar.MINUTE,1));
ax.getTickLabelFormatter().applyPattern("MM/dd HH:mm");
ax.setVerticalTickLabels(true);

ChartPanel totPanel = new ChartPanel(totChart);
totPanel.setMouseZoomable(true,false);
add(totPanel);
start();
}
public void start(){
if (thr == null){
thr = new Thread(this, "Test");
thr.start();
}
}
public void run() {
Thread myThread = Thread.currentThread();
Double [] sum = new Double[bts.length];
while(true){
try {
Thread.sleep(5000);
cal.add(Calendar.SECOND, 5);
for (int j=0; j<bts.length; j++){
double factor = j*32.0 + (Math.random()*10*j-(Math.random()*j)) + 30;
int cnt = bts[j].getItemCount();
if (cnt > 13){
bts[j].delete(0,1);
System.out.println("DSCnt: " + bts[j].getItemCount());
}
sum[j] = new Double(factor);
bts[j].add(new FixedMillisecond(cal.getTimeInMillis()), factor);
}
for (int i = 0; i<sum.length; i++){
pieData.setValue(legend, sum);
}
} catch (Exception e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Chart Tests");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ChartTimeSeries cts = new ChartTimeSeries();
frame.setContentPane(cts);
frame.pack();
frame.setVisible(true);
}
}



::::::::::::::: ToolTipGenerator ::::::::::::::::::::::::::::::::::::::::::::::::::::

public class TimeSeriesToolTipGenerator2 implements XYToolTipGenerator {
protected DateFormat domainFormat;
protected NumberFormat rangeFormat;
/** Number of series */
protected int count = 1;
/** Tool tip buffer */
StringBuffer sbuff = new StringBuffer();

public TimeSeriesToolTipGenerator2(int seriesCount) {
this("MM-dd HH:mm", "#####0.0");
this.count = seriesCount;
}
public TimeSeriesToolTipGenerator2(String dateFormat, String valueFormat) {
this(new SimpleDateFormat(dateFormat), new DecimalFormat(valueFormat));
}
public TimeSeriesToolTipGenerator2(DateFormat domainFormat, NumberFormat rangeFormat) {
this.domainFormat = domainFormat;
this.rangeFormat = rangeFormat;
}

public String generateToolTip(XYDataset data, int series, int item) {
sbuff.delete(0,sbuff.length());
long x = data.getXValue(series, item).longValue();
sbuff.append("<html><font color=blue><b>");
sbuff.append(domainFormat.format(new Date(x)));
sbuff.append("</b></font><table>");
Number y = null;
for (int i=0; i<count; i++){
sbuff.append("<tr><td>");
sbuff.append(data.getSeriesName(i));
sbuff.append("</td><td>");
y = data.getYValue(i, item);
if (y!=null){
sbuff.append(rangeFormat.format(y));
} else {
sbuff.append("null");
}
sbuff.append("</td></tr>");
y = null;
}
sbuff.append("</table></html>");
return sbuff.toString();
}
}
::::::::::::::: exception ::::::::::::::::::::::::

java.lang.IndexOutOfBoundsException: Index: 12, Size: 12
at java.util.ArrayList.RangeCheck(ArrayList.java:508)
at java.util.ArrayList.get(ArrayList.java:320)
at com.jrefinery.data.BasicTimeSeries.getDataPair(Unknown Source)
at com.jrefinery.data.TimeSeriesCollection.getYValue(Unknown Source)
at com.jrefinery.chart.tooltips.TimeSeriesToolTipGenerator2.generateToolTip(TimeSeriesToolTipGenerator2.java:98)

Locked