overlaid chart with xy-line and stacked bar

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
hank
Posts: 31
Joined: Mon May 12, 2003 10:02 am
Location: Lake of Constance, Germany

overlaid chart with xy-line and stacked bar

Post by hank » Thu May 06, 2004 5:59 pm

Hi,

I'd like to create a chart which has two basic datasets included into one chart.
The one dataset would be a TimeSeries, just a collection of series over time.
The other dataset would be some stacked bar chart, as they appear i.e. in 'Stacked Bar Chart Demo1'.

The position of the stacked bars would to be at certain points of time on the domain axis. There may be two or three or more of them in one chart.

I tried to work with 'Overlaid Plot Example' and replaced the createDataset1 method as follows.

Code: Select all

   /**
    * Creates a sample dataset.
    *
    * @return The dataset.
    */
   private IntervalXYDataset createDataset1() {

      TimeSeries series1 = new TimeSeries("Set1", Day.class);
      TimeSeries series2 = new TimeSeries("Set2", Day.class);
      TimeSeries series3 = new TimeSeries("Set3", Day.class);
      TimeSeries series4 = new TimeSeries("Set4", Day.class);

      series1.add(new Day(3, SerialDate.MARCH, 2002), 100);
      series2.add(new Day(3, SerialDate.MARCH, 2002), 80);
      series3.add(new Day(3, SerialDate.MARCH, 2002), 60);
      series4.add(new Day(3, SerialDate.MARCH, 2002), 40

      series1.add(new Day(7, SerialDate.MARCH, 2002), 80);
      series2.add(new Day(7, SerialDate.MARCH, 2002), 60);
      series3.add(new Day(7, SerialDate.MARCH, 2002), 40);
      series4.add(new Day(7, SerialDate.MARCH, 2002), 20);

      series1.add(new Day(14, SerialDate.MARCH, 2002), 60);
      series2.add(new Day(14, SerialDate.MARCH, 2002), 50);
      series3.add(new Day(14, SerialDate.MARCH, 2002), 40);
      series4.add(new Day(14, SerialDate.MARCH, 2002), 20);

      TimeSeriesCollection tsc = new TimeSeriesCollection();
      tsc.addSeries(series1);
      tsc.addSeries(series2);
      tsc.addSeries(series3);
      tsc.addSeries(series4);
      return tsc;

   }


Would this be a good way, or do I miss some more elegant dataset container for this?

My chart looks like this:
Image

Thanks and cheers

Heinrich

hank
Posts: 31
Joined: Mon May 12, 2003 10:02 am
Location: Lake of Constance, Germany

Post by hank » Thu Jun 17, 2004 4:51 pm

Hi

now I implemented a data container for my stacked bar charts with time series, here is how it looks like at the moment:

Image

But unfortunately there are some open questions:
1. Is there a more elegant way of doing this ingeneral? Or are there some data container already which met my requirements better?
2. Why are the bar charts so smal, how can I have them wider?
3. The tooltips show only the complete amount of the series, not the value I put into the series, this has todo with the renderer, I guess. But I've no idea how and where to change it.

Here is some code, no further changes would be neccessary in the existing JFreeChart 0.9.20:

The Example Class:

Code: Select all

package org.jfree.chart.demo;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.StandardXYItemRenderer;
import org.jfree.chart.renderer.XYBarRenderer;
import org.jfree.chart.renderer.XYItemRenderer;
import org.jfree.data.DefaultTableStackedTimeSeriesDataset;
import org.jfree.data.IntervalXYDataset;
import org.jfree.data.XYDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.StackedBarTimeSeries;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.date.SerialDate;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A demonstration application showing a time series chart overlaid with a vertical StackedTimeSeries bar chart.
 *
 * @author Heinrich G&tzger
 */
public class OverlaidXYPlotDemo3 extends ApplicationFrame {

   /**
    * Constructs a new demonstration application.
    *
    * @param title  the frame title.
    */
   public OverlaidXYPlotDemo3(String title) {

      super(title);
      JFreeChart chart = createOverlaidChart();
      ChartPanel panel = new ChartPanel(chart, true, true, true, true, true);
      panel.setPreferredSize(new java.awt.Dimension(500, 270));
      setContentPane(panel);

   }

   /**
    * Creates an overlaid chart.
    *
    * @return The chart.
    */
   private JFreeChart createOverlaidChart() {

      // create plot ...
      final IntervalXYDataset data1 = createDataset1();
      final XYItemRenderer renderer1 = new XYBarRenderer(0.2);
      renderer1.setToolTipGenerator(
          new StandardXYToolTipGenerator(
              StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
              new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0.00")
          )
      );
      final DateAxis domainAxis = new DateAxis("Date");
      domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
      final ValueAxis rangeAxis = new NumberAxis("Value");
      final XYPlot plot = new XYPlot(data1, domainAxis, rangeAxis, renderer1);

      // add a second dataset and renderer...
      final XYDataset data2 = createDataset2();
      final XYItemRenderer renderer2 = new StandardXYItemRenderer();
      renderer2.setToolTipGenerator(
          new StandardXYToolTipGenerator(
              StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
              new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0.00")
          )
      );
      plot.setDataset(1, data2);
      plot.setRenderer(1, renderer2);
      
      plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

      // return a new chart containing the overlaid plot...
      return new JFreeChart("Overlaid Plot Example 3", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
      
   }

   /**
    * Creates a sample dataset.
    *
    * @return The dataset.
    */
   private IntervalXYDataset createDataset1() {

      DefaultTableStackedTimeSeriesDataset ts = new DefaultTableStackedTimeSeriesDataset();

      StackedBarTimeSeries s1 = new StackedBarTimeSeries("Series 1", Day.class);
      StackedBarTimeSeries s2 = new StackedBarTimeSeries("Series 2", Day.class);
      StackedBarTimeSeries s3 = new StackedBarTimeSeries("Series 3", Day.class);
      StackedBarTimeSeries s4 = new StackedBarTimeSeries("Series 4", Day.class);

      s1.add(new Day(3, SerialDate.MARCH, 2002), 20);
      s1.add(new Day(7, SerialDate.MARCH, 2002), 10);
//      s1.add(new Day(14, SerialDate.MARCH, 2002), 30);

      s2.add(new Day(3, SerialDate.MARCH, 2002), 20);
//      s2.add(new Day(7, SerialDate.MARCH, 2002), 10);
      s2.add(new Day(14, SerialDate.MARCH, 2002), 30);

//      s3.add(new Day(3, SerialDate.MARCH, 2002), 20);
      s3.add(new Day(7, SerialDate.MARCH, 2002), 10);
      s3.add(new Day(14, SerialDate.MARCH, 2002), 30);
      
//      s4.add(new Day(3, SerialDate.MARCH, 2002), 20);
      s4.add(new Day(7, SerialDate.MARCH, 2002), 10);
//      s4.add(new Day(14, SerialDate.MARCH, 2002), 30);

      ts.addSeries(s1);
      ts.addSeries(s2);
      ts.addSeries(s3);
      ts.addSeries(s4);

      return ts;

   }

   /**
    * Creates a sample dataset.
    *
    * @return The dataset.
    */
   private XYDataset createDataset2() {

      // create dataset 2...
      TimeSeries series2 = new TimeSeries("Series 5", Day.class);

      series2.add(new Day(3, SerialDate.MARCH, 2002), 168.2);
      series2.add(new Day(4, SerialDate.MARCH, 2002), 196.3);
      series2.add(new Day(5, SerialDate.MARCH, 2002), 182.5);
      series2.add(new Day(6, SerialDate.MARCH, 2002), 153.3);
      series2.add(new Day(7, SerialDate.MARCH, 2002), 135.0);
      series2.add(new Day(8, SerialDate.MARCH, 2002), 126.3);
      series2.add(new Day(9, SerialDate.MARCH, 2002), 139.2);
      series2.add(new Day(10, SerialDate.MARCH, 2002), 119.2);
      series2.add(new Day(11, SerialDate.MARCH, 2002), 169.9);
      series2.add(new Day(12, SerialDate.MARCH, 2002), 178.2);
      series2.add(new Day(13, SerialDate.MARCH, 2002), 164.3);
      series2.add(new Day(14, SerialDate.MARCH, 2002), 179.6);
      series2.add(new Day(15, SerialDate.MARCH, 2002), 185.7);
      series2.add(new Day(16, SerialDate.MARCH, 2002), 195.9);

      TimeSeriesCollection tsc = new TimeSeriesCollection(series2);
      return tsc;

   }

   /**
    * Starting point for the demonstration application.
    *
    * @param args  ignored.
    */
   public static void main(String[] args) {

      OverlaidXYPlotDemo3 demo = new OverlaidXYPlotDemo3("Overlaid TimeSeriesPlot Demo 3");
      demo.pack();
      RefineryUtilities.centerFrameOnScreen(demo);
      demo.setVisible(true);

   }

}
The StackedBarTimeSeries is just to have a differnet series class:

Code: Select all

package org.jfree.data.time;

/**
 * Represents a sequence of zero or more data items in the form (period, value).
 */
public class StackedBarTimeSeries extends TimeSeries {

   /**
    * Creates a new (empty) time series. By default, a daily time series is
    * created. Use one of the other constructors if you require a different time
    * period.
    * @param name the series name (<code>null</code> not permitted).
    */
   public StackedBarTimeSeries(final String name) {

      super(name, DEFAULT_DOMAIN_DESCRIPTION, DEFAULT_RANGE_DESCRIPTION,
            Day.class);
   }


   /**
    * Creates a new (empty) time series.
    * @param name the series name (<code>null</code> not permitted).
    * @param timePeriodClass the type of time period (<code>null</code> not
    * permitted).
    */
   public StackedBarTimeSeries(final String name, final Class timePeriodClass) {

      super(name, DEFAULT_DOMAIN_DESCRIPTION, DEFAULT_RANGE_DESCRIPTION,
            timePeriodClass);
   }


   /**
    * Creates a new time series that contains no data.
    * <P>
    * Descriptions can be specified for the domain and range. One situation
    * where this is helpful is when generating a chart for the time series -
    * axis labels can be taken from the domain and range description.
    * @param name the name of the series (<code>null</code> not permitted).
    * @param domain the domain description (<code>null</code> permitted).
    * @param range the range description (<code>null</code> permitted).
    * @param timePeriodClass the type of time period (<code>null</code> not
    * permitted).
    */
   public StackedBarTimeSeries(final String name, final String domain,
         final String range, final Class timePeriodClass) {

      super(name, domain, range, timePeriodClass);
   }

}
The interface for the Table of TimeSeries ....
which is basicly a copy of

Code: Select all

 package org.jfree.data;

/**
 * A dataset containing one or more time series containing (x, y) data items, where all series 
 * in the dataset share the same set of x-values (points of time).  This is a restricted form of the 
 * {@link XYDataset} interface (which allows independent x-values between series). This is used 
 * primarily by the {@link org.jfree.chart.renderer.StackedXYAreaRenderer}.
 */
public interface TableTimeSeriesDataset extends XYDataset {

    /**
     * Returns the number of items every series.
     *
     * @return the item count.
     */
    public int getItemCount();

}
.... and it's implementation

which is basicly a copy of DefaultTableXYDataset with adjustment to StackedBarTimeSeries and the method updateYPoints:

Code: Select all

package org.jfree.data;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.StackedBarTimeSeries;
import org.jfree.data.time.TimeSeriesDataItem;
import org.jfree.util.ObjectUtils;

/**
 * An {@link XYDataset} where every series shares the same point-of-time-values (required for
 * generating stacked time bar charts).
 * 
 * @author Heinrich G&tzger
 */
public class DefaultTableStackedTimeSeriesDataset extends AbstractIntervalXYDataset 
                                   implements TableTimeSeriesDataset, IntervalXYDataset, DomainInfo {
    
    /** Storage for the data. */
    private List data = null;
    
    /** Storage for the x values. */
    private HashSet xPoints = null;
    
    /** A flag that controls whether or not events are propogated. */
    private boolean propagateEvents = true;
    
    private boolean autoPrune = false;
    
    private IntervalXYDelegate intervalDelegate;

    /**
     * Creates a new empty dataset.
     */
    public DefaultTableStackedTimeSeriesDataset() {
        this(false);
    }
    
    /**
     * Creates a new empty dataset.
     * 
     * @param autoPrune  a flag that controls whether or not x-values are removed whenever the
     *                   corresponding y-values are all <code>null</code>.
     */
    public DefaultTableStackedTimeSeriesDataset(boolean autoPrune) {
        this.autoPrune = autoPrune;
        this.data = new ArrayList();
        this.xPoints = new HashSet();
        this.intervalDelegate = new IntervalXYDelegate(this, false);
    }

    
    /**
     * Returns the flag that controls whether or not x-values are removed from the dataset when
     * the corresponding y-values are all <code>null</code>.
     * 
     * @return a boolean.
     */
    public boolean isAutoPrune() {
        return this.autoPrune;
    }

    /**
     * Adds a series to the collection and sends a {@link DatasetChangeEvent} to all registered
     * listeners.  The series should be configured to NOT allow duplicate x-values.
     *
     * @param series  the series (<code>null</code> not permitted).
     */
    public void addSeries(StackedBarTimeSeries series) {
        if (series == null) {
            throw new IllegalArgumentException("Null 'series' argument.");
        }

        updateXPoints(series);
        this.data.add(series);
        series.addChangeListener(this);
        updateYPoints(data);
        fireDatasetChanged();
    }

    /**
     * Cummulates all series with lower index of list <code>data</code> with the later
     * elements of <code>date</code>.
     * 
     * @param data  the series (<code>null</code> not permitted).
     */
   private void updateYPoints(List data) {
      if (data == null) {
         throw new IllegalArgumentException("Null 'data' not permitted.");
     }
      
      StackedBarTimeSeries addedSeries = (StackedBarTimeSeries) this.data.get(this.data.size() - 1);

      for (int seriesNo = 0; seriesNo < this.data.size() - 1; seriesNo++) {
         StackedBarTimeSeries dataSeries = (StackedBarTimeSeries) this.data.get(seriesNo);
         for (int itemNo = 0; itemNo < dataSeries.getItemCount(); itemNo++) {
            TimeSeriesDataItem ts = dataSeries.getDataItem(itemNo);
            if (ts.getValue() != null && addedSeries.getValue(itemNo) != null) {
               ts.setValue(new Double(ts.getValue().doubleValue()
                     + addedSeries.getValue(itemNo).doubleValue()));
            }
         }
      }

      
   }

   /**
    * Adds any unique x-values from 'series' to the dataset, and also adds any
    * x-values that are in the dataset but not in 'series' to the series.
    * @param series the series (<code>null</code> not permitted).
    */
    private void updateXPoints(StackedBarTimeSeries series) {
        if (series == null) {
            throw new IllegalArgumentException("Null 'series' not permitted.");
        }
        HashSet seriesXPoints = new HashSet();
        boolean savedState = this.propagateEvents;
        this.propagateEvents = false;
        for (int itemNo = 0; itemNo < series.getItemCount(); itemNo++) {
            RegularTimePeriod xValue = series.getTimePeriod(itemNo);
            seriesXPoints.add(xValue);
            if (!this.xPoints.contains(xValue)) {
                this.xPoints.add(xValue);
                for (int seriesNo = 0; seriesNo < this.data.size(); seriesNo++) {
                    StackedBarTimeSeries dataSeries = (StackedBarTimeSeries) this.data.get(seriesNo);
                    if (!dataSeries.equals(series)) {
                        dataSeries.add(xValue, null);
                    } 
                }
            }
        }
        Iterator iterator = this.xPoints.iterator();
        while (iterator.hasNext()) {
            RegularTimePeriod xPoint = (RegularTimePeriod) iterator.next();
            if (!seriesXPoints.contains(xPoint)) {
                series.add(xPoint, null);
            }
        }
        this.propagateEvents = savedState;
    }

    /**
     * Updates the x-values for all the series in the dataset.
     */
    public void updateXPoints() {
        this.propagateEvents = false;
        for (int s = 0; s < this.data.size(); s++) {
            updateXPoints((StackedBarTimeSeries) this.data.get(s));
        }
        if (this.autoPrune) {
            prune();
        }
        this.propagateEvents = true;
    }

    /**
     * Returns the number of series in the collection.
     *
     * @return the number of series in the collection.
     */
    public int getSeriesCount() {
       return this.data == null ? 0 : this.data.size();
    }

    /**
     * Returns the number of x values in the dataset.
     *
     * @return the number of x values in the dataset.
     */
    public int getItemCount() {
       return this.xPoints == null ? 0 : this.xPoints.size();
    }

    /**
     * Returns a series.
     *
     * @param series  the series (zero-based index).
     *
     * @return the series (never <code>null</code>).
     */
    public StackedBarTimeSeries getSeries(int series) {
        if ((series < 0) || (series > getSeriesCount())) {
            throw new IllegalArgumentException(
                "XYSeriesCollection.getSeries(...): index outside valid range.");
        }

        return (StackedBarTimeSeries) this.data.get(series);
    }

    /**
     * Returns the name of a series.
     *
     * @param series  the series (zero-based index).
     *
     * @return the name of a series.
     */
    public String getSeriesName(int series) {
        // check arguments...delegated
        return getSeries(series).getName();
    }

    /**
     * Returns the number of items in the specified series.
     *
     * @param series  the series (zero-based index).
     *
     * @return the number of items in the specified series.
     */
    public int getItemCount(int series) {
        // check arguments...delegated
        return getSeries(series).getItemCount();
    }

    /**
     * Returns the x-value for the specified series and item.
     *
     * @param series  the series (zero-based index).
     * @param item  the item (zero-based index).
     *
     * @return the x-value for the specified series and item.
     */
    public Number getXValue(int series, int item) {
        StackedBarTimeSeries s = (StackedBarTimeSeries) this.data.get(series);
        TimeSeriesDataItem ts = s.getDataItem(item);
        return new Long(ts.getPeriod().getMiddleMillisecond());
    }
    
	/**
	 * Returns the starting X value for the specified series and item.
	 *
	 * @param series  the series (zero-based index).
	 * @param item  the item (zero-based index).
	 *
	 * @return The starting X value.
	 */
	public Number getStartXValue(int series, int item) {
		return intervalDelegate.getStartXValue(series, item);
	}

	/**
	 * Returns the ending X value for the specified series and item.
	 *
	 * @param series  the series (zero-based index).
	 * @param item  the item (zero-based index).
	 *
	 * @return The ending X value.
	 */
	public Number getEndXValue(int series, int item) {
		return intervalDelegate.getEndXValue(series, item);
	}

    /**
     * Returns the y-value for the specified series and item.
     *
     * @param series  the series (zero-based index).
     * @param index  the index of the item of interest (zero-based).
     *
     * @return the y-value for the specified series and item (possibly <code>null</code>).
     */
    public Number getYValue(int series, int index) {
        StackedBarTimeSeries ts = (StackedBarTimeSeries) this.data.get(series);
        TimeSeriesDataItem dataItem = ts.getDataItem(index);
        return dataItem.getValue();
    }

	/**
	 * Returns the starting Y value for the specified series and item.
	 *
	 * @param series  the series (zero-based index).
	 * @param item  the item (zero-based index).
	 *
	 * @return The starting Y value.
	 */
	public Number getStartYValue(int series, int item) {
		return getYValue(series, item);
	}

	/**
	 * Returns the ending Y value for the specified series and item.
	 *
	 * @param series  the series (zero-based index).
	 * @param item  the item (zero-based index).
	 *
	 * @return The ending Y value.
	 */
	public Number getEndYValue(int series, int item) {
		return getYValue(series, item);
	}

    /**
     * Removes all the series from the collection and sends a {@link DatasetChangeEvent} to
     * all registered listeners.
     */
    public void removeAllSeries() {

        // Unregister the collection as a change listener to each series in the collection.
        for (int i = 0; i < this.data.size(); i++) {
            StackedBarTimeSeries series = (StackedBarTimeSeries) this.data.get(i);
            series.removeChangeListener(this);
        }

        // Remove all the series from the collection and notify listeners.
        this.data.clear();
        this.xPoints.clear();
        this.intervalDelegate.seriesRemoved();
        fireDatasetChanged();
    }

    /**
     * Removes a series from the collection and sends a {@link DatasetChangeEvent} to all 
     * registered listeners.
     *
     * @param series  the series (<code>null</code> not permitted).
     */
    public void removeSeries(StackedBarTimeSeries series) {

        // check arguments...
        if (series == null) {
            throw new IllegalArgumentException("Null 'series' argument.");
        }

        // remove the series...
        if (this.data.contains(series)) {
            series.removeChangeListener(this);
            this.data.remove(series);
            if (this.data.size() == 0) {
                this.xPoints.clear();
            }
			this.intervalDelegate.seriesRemoved();
            fireDatasetChanged();
        }

    }

    /**
     * Removes a series from the collection and sends a {@link DatasetChangeEvent} to all
     * registered listeners.
     *
     * @param series  the series (zero based index).
     */
    public void removeSeries(int series) {

        // check arguments...
        if ((series < 0) || (series > getSeriesCount())) {
            throw new IllegalArgumentException(
                "XYSeriesCollection.removeSeries(...): index outside valid range.");
        }

        // fetch the series, remove the change listener, then remove the series.
        StackedBarTimeSeries s = (StackedBarTimeSeries) this.data.get(series);
        s.removeChangeListener(this);
        this.data.remove(series);
        if (this.data.size() == 0) {
            this.xPoints.clear();
        }
        else if (this.autoPrune) {
            prune();
        }
		this.intervalDelegate.seriesRemoved();
        fireDatasetChanged();

    }

    /**
     * Removes the items from all series for a given x value.
     *
     * @param x  the x-value.
     */
    public void removeAllValuesForX(RegularTimePeriod x) {
        if (x == null) { 
            throw new IllegalArgumentException("Null 'x' argument.");
        }
        boolean savedState = this.propagateEvents;
        this.propagateEvents = false;
        for (int s = 0; s < this.data.size(); s++) {
            StackedBarTimeSeries series = (StackedBarTimeSeries) this.data.get(s);
            series.delete(x);
        }
        this.propagateEvents = savedState;
        this.xPoints.remove(x);
        this.intervalDelegate.seriesRemoved();
        fireDatasetChanged();
    }

    /**
     * Returns <code>true</code> if all the y-values for the specified x-value are <code>null</code>
     * and false otherwise.
     * 
     * @param x  the x-value.
     * 
     * @return a boolean.
     */
    protected boolean canPrune(RegularTimePeriod x) {
        for (int s = 0; s < this.data.size(); s++) {
            StackedBarTimeSeries series = (StackedBarTimeSeries) this.data.get(s);
            if (series.getValue(x) != null) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Removes all x-values for which all the y-values are <code>null</code>.
     */
    public void prune() {
        HashSet hs = (HashSet) this.xPoints.clone();
        Iterator iterator = hs.iterator();
        while (iterator.hasNext()) {
            RegularTimePeriod x = (RegularTimePeriod) iterator.next();
            if (canPrune(x)) {
                removeAllValuesForX(x);
            }
        }
    }
    
    /**
     * This method receives notification when a series belonging to the dataset changes.  It 
     * responds by updating the x-points for the entire dataset and sending a 
     * {@link DatasetChangeEvent} to all registered listeners.
     *
     * @param event  information about the change.
     */
    public void seriesChanged(SeriesChangeEvent event) {
        if (this.propagateEvents) {
            updateXPoints();
            fireDatasetChanged();
        }
    }

    /**
     * Tests this collection for equality with an arbitrary object.
     *
     * @param obj  the object (<code>null</code> permitted).
     *
     * @return A boolean.
     */
    public boolean equals(Object obj) {
    	
    	/*
    	 * I wonder if these implementations of equals and hashCode are 
    	 * sound... (AS)
    	 */

        if (obj == null) {
            return false;
        }

        if (obj == this) {
            return true;
        }

        if (obj instanceof DefaultTableStackedTimeSeriesDataset) {
            DefaultTableStackedTimeSeriesDataset c = (DefaultTableStackedTimeSeriesDataset) obj;
            return ObjectUtils.equal(this.data, c.data);
        }

        return false;

    }

    /**
     * Returns a hash code.
     * 
     * @return a hash code.
     */
    public int hashCode() {
        int result;
        result = (this.data != null ? this.data.hashCode() : 0);
        result = 29 * result + (this.xPoints != null ? this.xPoints.hashCode() : 0);
        result = 29 * result + (this.propagateEvents ? 1 : 0);
        result = 29 * result + (this.autoPrune ? 1 : 0);
        return result;
    }
    
	/**
	 * @return the domain range
	 */
	public Range getDomainRange() {
		return intervalDelegate.getDomainRange();
	}

	/**
	 * @return the maximum domain value.
	 */
	public Number getMaximumDomainValue() {
		return intervalDelegate.getMaximumDomainValue();
	}

	/**
	 * @return the minimum domain value.
	 */
	public Number getMinimumDomainValue() {
		return intervalDelegate.getMinimumDomainValue();
	}
	
	/**
	 * Returns the interval position factor. 
	 * @return the interval position factor.
	 */
	public double getIntervalPositionFactor() {
		return intervalDelegate.getIntervalPositionFactor();
	}

	/**
	 * Sets the interval position factor. Must be between 0.0 and 1.0 inclusive.
	 * If the factor is 0.5, the gap is in the middle of the x values. If it
	 * is lesser than 0.5, the gap is farther to the left and if greater than
	 * 0.5 it gets farther to the right.
	 *  
	 * @param d the new interval position factor.
	 */
	public void setIntervalPositionFactor(double d) {
		intervalDelegate.setIntervalPositionFactor(d);
		fireDatasetChanged();
	}

	/**
	 * returns the full interval width. 
	 * 
	 * @return the interval width to use.
	 */
	public double getIntervalWidth() {
		return intervalDelegate.getIntervalWidth();
	}

	/**
	 * Sets the interval width manually. 
	 * 
	 * @param d the new interval width.
	 */
	public void setIntervalWidth(double d) {
		intervalDelegate.setIntervalWidth(d);
		fireDatasetChanged();
	}

	/**
	 * Returns wether the interval width is automatically calculated or not.
	 * 
	 * @return wether the width is automatically calcualted or not.
	 */
	public boolean isAutoWidth() {
		return intervalDelegate.isAutoWidth();
	}

	/**
	 * Sets the flag that indicates wether the interval width is automatically
	 * calculated or not. 
	 * 
	 * @param b
	 */
	public void setAutoWidth(boolean b) {
		intervalDelegate.setAutoWidth(b);
		fireDatasetChanged();
	}
}
Thanks and cheers
Heinrich

hank
Posts: 31
Joined: Mon May 12, 2003 10:02 am
Location: Lake of Constance, Germany

Post by hank » Wed Jul 21, 2004 9:20 am

David,

may I kindly ask you to take a look to my questions please, it still is important to me.

Thanks and cheers

Heinrich

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 Jul 21, 2004 1:16 pm

hank wrote:1. Is there a more elegant way of doing this ingeneral? Or are there some data container already which met my requirements better?
The approach use in your first post is the way I would do it.
hank wrote:2. Why are the bar charts so smal, how can I have them wider?
The bar widths are determined by the values returned for the start and end x-values in the IntervalXYDataset interface.
hank wrote:3. The tooltips show only the complete amount of the series, not the value I put into the series, this has todo with the renderer, I guess. But I've no idea how and where to change it.
I don't understand what you mean here. There is a tool tip generator registered with the renderer, that's what you need to change if the tooltips are not coming out in the format you require.
David Gilbert
JFreeChart Project Leader

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

Guest

Post by Guest » Wed Jul 21, 2004 1:39 pm

david.gilbert wrote:
hank wrote:1. Is there a more elegant way of doing this ingeneral? Or are there some data container already which met my requirements better?
The approach use in your first post is the way I would do it.
The disadvantage of this approach is, that I would need to sum up the values for a certain date if I add values of a new series to this bar.
That's why I tried with the second approch with a special container which does the summing internal. But with the second approach, I have the other problems mentioned above :-(

Thanks anyway, cheers

Heinrich

Locked