Charts > Using the Charts Library > Data Handling > Modifying Data and Updating Charts > Using Listeners to Catch Data Changes
 
Using Listeners to Catch Data Changes
The listeners set on data catch modifications made to the data. Listeners are set at the level of the data sets and at the level of the chart data objects. For both types of listeners, a method is defined for each type of modification that can be made to the object on which the listener is set. The method corresponding to a given modification is called when the modification that has occurred is propagated to the listener (see Figure 6.3).
Listeners on Data Sets
Listeners set on data sets are instances of subclasses of the IlvChartDataSetListener class. The IlvChartDataSetListener class is used to watch for all the modifications that can be made to a given data set. If you remember, these modifications include adding new data items, replacing existing data items, and removing data items (see Modifications Made at the Data Set Level). Methods corresponding to these types of modifications are defined in the IlvChartDataSetListener class:
*dataPointAdded is called when a new data item is added to the data set.
*dataPointChanged is called when an existing data item is changed in the data set.
*dataPointRemoved is called when a data item is removed from the data set.
Listeners on Chart Data Objects
Listeners set on chart data objects are instances of subclasses of the IlvChartDataListener class. The IlvChartDataListener class is used to listen to all the modifications that can be made to a given chart data object. These modifications include adding new data sets, changing existing data sets, and removing data sets (see Modifications Made at the Chart Data Object Level). Methods corresponding to these types of modifications are defined in the IlvChartDataListener class:
*dataSetAdded is called when a new data set is added.
*dataSetChanged is called when an existing data set is changed.
*dataSetRemoved is called when a data set is removed.
Since a chart data object handles data sets, the modifications made at the level of a data set are also reported at the level of the chart data object. The corresponding methods that are defined in the IlvChartDataListener class are:
*dataPointAdded is called when a new data item is added to a data set.
*dataPointChanged is called when an existing data item is changed in a data set.
*dataPointRemoved is called when a data point is removed from a data set.
Defining Your Own Listeners
You can define your own data listeners to perform specific tasks when certain types of modifications are made to a data set or to a chart data object. To do so, you need to perform these steps:
1. Create a subclass of the IlvChartDataSetListener class (or the IlvChartDataListener class).
2. Implement the specific tasks you want to be performed when some types of modifications are made by subclassing the corresponding methods. The methods corresponding to a given type of modification for the IlvChartDataSetListener class can be found in Listeners on Data Sets and for the IlvChartDataListener class in Listeners on Chart Data Objects.
3. Add an instance of the created subclass to the data set (or to the chart data object).
Example of a User-Defined Listener
We are now going to show you how to define a listener that performs specific tasks when new data items are added to a data set. We will use the Temperatures Chart again (see Creating a Simple Cartesian Chart).
In this example, we want the chart to indicate when temperatures for each data set fall outside of a given interval. We are going to add two cursors to the Temperatures Chart that indicate the minimum and maximum values of the interval. When a new temperature that is added to a data set is outside of this interval, a message will be printed on the standard output. To do this, we can define a specific listener (inherited from IlvChartDataSetListener) to be set on each temperatures data set.
The complete source code of this example can be found in the listener.cpp file located in the $ILVHOME/samples/charts/userman/src directory. The example shows only the part of the code that is specific to creating the dedicated listener.
Defining the TemperatureDataSetListener Class
The following code is used to declare the TemperatureDataSetListener class:
class TemperatureDataSetListener
: public IlvChartDataSetListener
{
public:
TemperatureDataSetListener(IlDouble min,
IlDouble max,
IlvChartGraphic* chart = 0,
IlvPalette* cursorPalette = 0);
 
virtual void dataPointAdded(const IlvChartDataSet* dataSet,
IlUInt position);
 
protected:
IlDouble _min;
IlDouble _max;
IlvChartGraphic* _chart;
};
Only the dataPointAdded method is subclassed since we want to perform a specific task when a new data item is added, and nothing special when other types of modifications are made to the data set.
The constructor is implemented as follows:
TemperatureDataSetListener::
TemperatureDataSetListener(IlDouble min,
IlDouble max,
IlvChartGraphic* chart,
IlvPalette* cursorPalette)
: IlvChartDataSetListener(),
_min(min),
_max(max)
{
if (chart) {
IlvDisplay* dpy = chart->getDisplay();
IlvPalette* palette = cursorPalette ? cursorPalette
: dpy->getPalette(dpy->getColor("white"), 0);
chart->addOrdinateCursor(_min, palette);
chart->addOrdinateCursor(_max, palette);
}
}
The constructor takes the minimum and maximum values of the considered interval as parameters. When a temperature that is outside of this interval is added, a message is printed. If a chart is specified as a parameter, cursors will be drawn in the chart at the minimum and maximum values of the interval.
The implementation of the dataPointAdded method is the following:
void
TemperatureDataSetListener::dataPointAdded(const IlvChartDataSet* dataSet,
IlUInt position)
{
IlvDoublePoint dataPoint;
dataSet->getPoint(position, dataPoint);
if (dataPoint.y() < _min)
cout << dataSet->getName() << ": Temperature at the index "
<< position << " = " << dataPoint.y() << " degrees ( < "
<< _min << " )" << endl;
if (dataPoint.y() > _max)
cout << dataSet->getName() << ": Temperature at the index "
<< position << " = " << dataPoint.y() << " degrees ( > "
<< _max << " )" << endl;
}
The method compares the new temperature value that is added to the data set with the minimum and the maximum values defined. A specific message is printed on the standard output when the temperature value is smaller than the minimum and when the temperature value is greater than the maximum.
Adding a TemperatureDataSetListener Object to the Temperatures Data Sets
The listener to be added to the temperatures data sets is created by the following code:
TemperatureDataSetListener* listener =
new TemperatureDataSetListener(10, 22, chart);
The created listener is set on all the temperatures data sets that are defined. It is set on dataSets[0] that corresponds to the morning mean temperatures data set and on dataSets[1] that corresponds to the afternoon mean temperatures data set.
dataSets[0]->addListener(listener);
dataSets[1]->addListener(listener);
Note: The listener must be set on the temperatures data sets before putting the data into the data sets. Otherwise, the message indicating whether a temperature is outside of the defined interval will not be printed when the temperature is added to a data set.
Now that the listener has been added, the Temperatures Chart appears as shown in Figure 6.4:
Figure 6.4    The Temperatures Chart with a Listener Set On the Temperatures Data Sets
Notice that a cursor has been added at the minimum value (10) and at the maximum value (22) which are passed as parameters to the constructor of the listener.
The messages that are printed to the standard output are the following:
Morning Temperatures: Temperature at the index 1 = 8 degrees ( < 10 )
Afternoon Temperatures: Temperature at the index 3 = 25 degrees ( > 22 )
Afternoon Temperatures: Temperature at the index 5 = 24 degrees ( > 22 )
Afternoon Temperatures: Temperature at the index 6 = 26 degrees ( > 22 )

Version 6.0
Copyright © 2015, Rogue Wave Software, Inc. All Rights Reserved.