Search
Tutorial 2: Adapting Custom Data

This tutorial shows how to implement the Series interface to return data values directly from application's model objects, instead of extracting them into dedicated lists as parameters for SimpleSeries. The code builds upon Tutorial 1, replacing SimpleSeries instances with the custom series.

1. Declare an enumeration specifying which data value of the model should be returned by a specific series:

Java  Copy Code

enum PriceType
{
    open,
    close,
    low,
    high
};

2. Add a MySeries class that implements Series interface:

Java  Copy Code

class MySeries implements Series
{
}

3. Define a reference to the stock-price service results from previous tutorial:

Java  Copy Code

private List<StockPrice> prices;

4. Add a field of the enum type above:

Java  Copy Code

private PriceType priceType;

5. The only constructor we allow must receive a reference to the model data:

Java  Copy Code

public MySeries(List<StockPrice> prices, PriceType priceType)
{
    this.prices = prices;
    this.priceType = priceType;
}

6. Now implement the interface members, starting with getSize:

Java  Copy Code

@Override public int getSize()
{
    return prices.size();
}

7. For the BarChart in this example, we only return one-dimensional data (Y values):

Java  Copy Code

@Override public int getDimensions()
{
    return 1;
}

8. getValue implementation returns the data from specified StockPrice member:

Java  Copy Code

@Override
public double getValue(int index, int dimension)
{
    switch (priceType)
    {
    case open:
        return prices.get(index).getOpen();
    case close:
        return prices.get(index).getClose();
    case low:
         return prices.get(index).getLow();
    case high:
        return prices.get(index).getHigh();
    }
    return 0;
}

9. getSupportedLabels declares X axis labels for one of the series. If each series shows X labels, they would be rendered on separate rows under the axis:

Java  Copy Code

@Override
public EnumSet<LabelKinds> getSupportedLabels()
{
    return priceType == PriceType.open ?
        EnumSet.of(LabelKinds.XAxisLabel) :
        EnumSet.noneOf(LabelKinds.class);
}

10. getLabel returns the date as label. Here you could as well return labels to draw inside or above bars, at either axis, or as tooltips:

Java  Copy Code

@Override
public String getLabel(int index, LabelKinds kind)
{
    DateTime date = new DateTime(
        prices.get(index).getDate());
    return date.toShortDateString();
}

11. getTitle results are displayed inside the legend box:

Java  Copy Code

@Override public String getTitle()
{
    return priceType.toString();
}

12. The chart refreshes automatically if this event is raised (not used in this example):

Java  Copy Code

@Override
public void addDataChangedListener(DataChangedListener listener) {}
@Override
public void removeDataChangedListener(DataChangedListener listener) {}

13. The charts draw respective data element as highlighted if this returns true:

Java  Copy Code

@Override public boolean isEmphasized(int index)
{
    return false;
}

14. The chart can do some optimizations, such as binary search for viewport clipping, if it knows data values are returned sorted. Return true if your data is actually sorted, or you will get incorrect results:

Java  Copy Code

@Override public boolean isSorted(int arg0)
{
    return false;
}

15. Now you can replace SimpleSeries with MySeries instances when setting chart.Series:

Java  Copy Code

// a series of daily opening prices
chart.getSeries().add(
    new MySeries(stockPrices, PriceType.open));

// a series of daily closing prices
chart.getSeries().add(
    new MySeries(stockPrices, PriceType.close));

// a series of daily min prices
chart.getSeries().add(
    new MySeries(stockPrices, PriceType.low));

// a series of daily max prices
chart.getSeries().add(
    new MySeries(stockPrices, PriceType.high));

16. The chart will look as in previous tutorial, but data values are no longer copied to new arrays, and are returned directly from the model objects: