6
Programming JClass Chart

Programming Basics · Axis Labelling · Batching Chart Updates

Coordinate Conversion Methods · Double Buffering · FastAction

Programming Actions · Programming ChartStyles

Using a Time-axis · Data Sources · Stock Data Sources

Image Filled Bar Charts · Using JCStrings

Using Pick and Unpick


Controlling the chart in an application program is generally quite straightforward once you are familiar with the programming basics and the object hierarchy. For most JClass Chart objects, all the information needed to program them can be found in the Application Programming Interface (API). In addition, extensive information on how they can be used can be found in the numerous example and demonstration programs provided with JClass Chart.

This chapter covers some basic programming concepts for JClass Chart and also looks at more complex chart programming tasks.


Programming Basics

The following topics provide a brief introduction to the concepts you need to understand in order to program the JClass Chart control.

The following topics are covered:

Object Hierarchy

JClass Chart is up of a number of objects. The top-level object is JCChart. JCChart manages four objects; the header and footer (both instances of JCTitle), the legend (JCLegend) and the chart area (JCChartArea).

The header and footer are titles used to annotate the chart. The legend shows how each data series is represented on the chart. The chart area contains the charted data and the axes. All four components can be positioned explicitly; by default, they will be laid out by JClass Chart.

Most of the properties of JClass Chart are accessed through JCChartArea. The chart area is responsible for plotting the data. As a result, it is responsible for managing all the X- and Y- axes (JCAxis). JCChartArea performs all the layout necessary to display the graph.

The data in JClass Chart is managed by the JCChart object. JCChart contains an array of ChartDataView instances. Each ChartDataView instance can, in turn, contain one or more ChartDataViewSeries instance. The ChartDataViewSeries objects represent each individual data series, and are constructed as a result of the data contained in the data source. For more information on the data source model in JClass Chart, see the Data Sources section later in this chapter.

The following illustration depicts the high-level objects defined as children of the JClass Chart control:

The high-level objects that comprise a typical chart

As can be seen in the above figure, a JCChart object contains two JCTitle objects representing the header and footer, a JCLegend object for the legend, and a JCChartArea object for the ChartArea. The ChartArea is the part of the graph where the actual charting occurs. JCChartArea contains two or more JCAxis objects, meant to represent each axis in the chart. The JCAxis objects are referenced in different collections: one for the X axes and one for the Y axes.

The JCChart object also contains one or more ChartDataView objects. ChartDataView references the data that is being charted. Each ChartDataView can have its own chart type. A ChartDataview object contains one or more ChartDataViewSeries objects. Each ChartDataViewSeries represents one series of points (e.g. one set of bars of the same color).

The ChartDataView object does not "own" the data. The data are owned by the DataSource. The DataSource can be a "stock" data source provided with JClass Chart, or a custom data source. For more details, see Data Sources later in this chapter.

Setting an Object Property

The following statement sets the background color of the chart area.
	c.getChartArea().setBackground(); 

This statement navigates the JClass Chart object hierarchy by retrieving the values of successive properties. First, the value of the ChartArea property is retrieved, which is a JCChartArea object. Then, the object's Background property is set.

Using Collections

Many JClass Chart objects are organized into collections. For example, the chart axes are organized into the XAxis collection and the YAxis collection. In Beans terminology, these objects are held in indexed properties.

To access a particular element of a collection, specify the index which uniquely identifies this element. For example, the following code changes the maximum value of the first X axis to 25.1:

	c.getChartArea().getAxis(0).setMax(25.1);

Note that the index refers to the first element of a collection. Also, note that by default JCChartArea contains one element in XAxis and one in YAxis.

Calling Methods

To call a JClass Chart method, access the object with which it is associated. For example, the following statement uses the coordToDataCoord method, defined by the ChartDataView collection, to convert the location of a mouse click event in pixels to their equivalent in data coordinates:
	JCDataCoord dc = c.getDataView(0).coordToDataCoord(10,15);

Details on each method can be found in the API documentation for each class. More information on coordToDataCoord and related methods can be found in the Coordinate Conversion Methods later in this chapter.

Demo Programs

Sample Java applets and applications are included as part of the JClass Chart distribution. These demonstration programs are contained in the jclass/chart/demos/ directory. In addition, a collection of simple example files can be found in the jclass/chart/examples/ directory. A collection of HTML-only charts can be found in jclass/chart/applet/.


Axis Labelling

By default, the AnnotationMethod for an axis is set to JCAxis.VALUE. This means that JCChart will generate labels for the axis based on the data range of the axis.

If the AnnotationMethod property is set to JCAxis.VALUE_LABELS, the chart places user-provided labels at explicit locations along an axis. The ValueLabels property of JCAxis, which is a ValueLabels collection, supplies this list of strings and their locations. For example, the following code sets value labels at the locations 10, 20 and 30:

	JCAxis x=c.getChartArea.getXAxis(0);
	x.setValueLabel(0, new JCValueLabel(10, 0, "Label"));
	x.setValueLabel(1, new JCValueLabel(20, 0, "Label 2"));
	x.setValueLabel(2, new JCValueLabel(30, 0, "Label 3"));

The ValueLabels collection can be indexed either by subscript or by value:

JCValueLabel v1
// this retrieves the label for the second Value-label 
	v1=c.getChartLabelArea().getXAxis(0);
		getValueLabel(2);
// this retrieves the label at chart coordinate 2.0
	v1=c.getChartLabelArea().getXAxis(0);
		getValueLabel(2.0);

If the AnnotationMethod property is set to JCAxis.POINT_LABELS, the chart evenly spaces the points across the axis, and annotates them with a list of strings. This labelling method can only be used on the X-axis. It is most common to associate point labels with the data. This can be done either by using the file format required by one of the stock data sources, or by implementing the getPointLabels() method in a custom data source. For more details, see Data Sources later in this chapter.

The labels can also be supplied by setting the PointLabels property of the ChartDataView object for this chart. For example, the following code specifies labels for each of the three points on the X-axis:

	c.getChartArea.getxAxis(0).setAnnotationMethod(JCAxisPOINT_LABELS);
	ChartDataView cd = c.getDataView(0);
	cd.setPointLabel(0, "Point 1");
	cd.setPointLabel(1, "Point 2");
	cd.setPointLabel(2, "Point 3");

If the AnnotationMethod property is set to JCAxis.TIME_LABELS, the chart treats the axis as a time-axis. To define the values to appear on a time-axis, use the following properties:


Batching Chart Updates

Normally, the chart is repainted immediately after a property is set. To make several changes to a chart before causing a repaint, set the IsBatched property of the JCChart object to true. Property changes do not cause a repaint until IsBatched is reset to false.

The IsBatched property is also defined for the ChartDataView object. This IsBatched property is independent of JCChart.IsBatched. It is used to control the update requests sent from the DataSource to the chart.

It is recommended that you batch around the creation or updating of multiple chart labels.


Coordinate Conversion Methods

The ChartDataView object provides methods which enable you to do the following:

These functions can be accomplished by using coordToDataCoord and dataIndexToCoord respectively, or by using their functional equivalents map and unmap.

CoordToDataCoord and DataIndexToCoord

To convert from data coordinates to pixel coordinates, call the dataCoordToCoord method. For example, the following code obtains the pixel coordinates corresponding to the screen coordinates (5.1, 10.2):
	Pointp=c.getDataView(0).dataCoordToCoord(5.1,10.2);

This works in the same way as unmap. Note that the screen coordinate positioning is relative to the upper left corner of the JCChart component display.

To convert from pixel coordinates to data coordinates, call coordToDataCoord(). For example, the following converts the pixel coordinates (225, 92) to their equivalent data coordinates:

	JCDataCoord cd=c.getDataView(0).coordToDataCoord(225,92);

This works in the same manner as map. coordToDataCoord returns a JCDataCoord object containing the x and y values in the data space.

To determine the pixel coordinates of a given data point, call dataIndexToCoord. For example, the following code obtains the pixel coordinates of the third point in the first data series:

	JCDataIndex di=newJCDataIndex(3,c.getDataView(0).getSeries(0));
	Point cdc=c.getDataView(0).dataIndexToCoord(di);

To determine the closest data point to a set of pixel coordinates, call coordToDataIndex:

	JCDataIndex di=c.getDataView(0).coordToDataIndex(225,92, ChartDataView.PICK_FOCUSXY);

Essentially, these last two examples demonstrate that dataIndexToCoord works in much the same way as pick and unpick. The third argument passed to coordToDataIndex specifies how the nearest series and point value are determined. This argument can be one of ChartDataView.PICK_FOCUSXY, ChartDataView.PICK_FOCUSX or ChartDataView.PICK_FOCUSY. For more information on the pick and unpick methods, see the Using Pick and Unpick section later in this chapter.

JCDataIndex contains the series and point value corresponding to the closest data point, and also returns the distance in pixels between the pixel coordinates and the point. coordToDataIndex returns a JCDataIndex instance.

Map and Unmap

The map and unmap are functionally equivalent to coordToDataCoord and dataIndexToCoord methods. They are provided as convenience methods, and are more in keeping with typical Java terminology than coordToDataCoord and dataIndexToCoord, which are used as method names within KL Group's Olectra Chart product for Windows developers.


Double Buffering

Double buffering is a graphics technique which will reduce the amount of flashing perceived by a user when a chart changes. By default, double buffering is in effect. To turn off double buffering for a JCChart object, set its DoubleBuffer property to false.

When double buffering is turned on, every time the chart changes, it will:

When double buffering is turned off, the chart clears the screen image every time a chart is changed (possibly causing a visual flash). Then, it renders the complete image to the visible window (possibly allowing the user to see the chart being drawn piece by piece).

Turning off double buffering can improve the chart's graphing performance and reduce its memory requirements, but it will likely result in a chart display that "flashes" as updates are continually drawn to the screen. By default DoubleBuffer is true.


FastAction

The FastAction property determines whether chart actions will use an optimized mode in which it does not bother to update display axis annotations or grid lines during a chart action. Default value is false.

Using FastAction can greatly improve the performance of a chart display, because relatively more time is needed to draw such things as axis annotations or grid lines than for simply updating the points on a chart. It is designed for use in dynamic chart displays, such as charts that enable the user to perform translation or rotation actions.

The following line of code shows how FastAction can be used in a program:

	c.getChartArea().setFastAction(true);

Programming Actions

A chart action is a user event that causes some interactive action to take place in the control. In JClass Chart, actions like zoom, translate and rotate can be mapped to a mouse button and a modifier. For example, it is possible to bind the translate event to the combination of mouse button 2 and the Control key. Whenever the user hits Control and mouse button 2 and drags the mouse, the chart will move.

Event Triggers

An event trigger is a mapping of a mouse operation and/or a key press to a chart action. In the example above, the trigger for translate is a combination of mouse button 2 and the Control key.

An event trigger has two parts:

Valid actions include EventTrigger.ZOOM, EventTrigger.TRANSLATE, EventTrigger.ROTATE and EventTrigger.DEPTH.

Valid Modifiers

The value of a modifier is specified using AWT modifiers, as shown in the following list:

If you are using the JDK 1.1, you can also specify the mouse button using one of the following modifiers:

Programming Event Triggers

To program an event trigger, use the setTrigger method to add the new action mapping to the collection.

For example, the following tells JClass Chart to perform a zoom operation when Shift and mouse button 1 are pressed:

	c.setTrigger(0,newEventTrigger(Event.SHIFT_MASK, EventTrigger.ZOOM);

Removing Action Mappings

To remove an existing action mapping, set the trigger to null, as in the following example:
	c.setTrigger(0,null);

Calling an Action Directly

In JClass Chart, it is possible to force some actions by calling a method of JCChart. The following is a list of the methods that can be called upon to force a particular action:

Specifying Action Axes

Actions like translation occur with respect to one or more axes. In JClass Chart, the axes can be set using the HorizActionAxis and VertActionAxis properties of JCChartArea, as the following code fragment illustrates:
	ChartDataView arr = c.getDataView(0);
	c.getChartArea().setHorizActionAxis(arr.getXAxis());
	c.getChartArea().setVertActionAxis(arr.getYAxis());

Note that it is possible to have a null value for an action axis. This means that chart actions like translation do not have any effect in that direction. By default, the HorizActionAxis is set to the default X-axis, and the VertActionAxis is set to the default Y-axis.


Programming ChartStyles

A JCChartStyle object defines the characteristics of a slice of a pie chart, a bar in a bar chart, or the points and lines in a plot. One JCChartStyle object is defined for each series within a data view. As new series are added, new JCChartStyle objects are automatically created by the chart.

ChartStyle is an indexed property of ChartDataView that "owns" the JCChartStyle objects for that data view. It can be manipulated like any other indexed property, as demonstrated in the following example:

	arr.setChartStyle(0, new JCChartStyle()); 

This adds the specified ChartStyle to the indexed property at the specified index. If the ChartStyle is null, the JCChartStyle at the specified point is removed. The following lists some of the other ways ChartStyle can be used:

Normally, you will not need to add or remove JCChartStyle objects from the collection yourself. If a JCChartStyle object already exists when its corresponding series is created, the previously created JCChartStyle object is used to display the data in this series.

By looping through the JCChartStyle indexed property, you can quickly change the behavior of all of the bars, lines or points in a chart. For example, the following code lightens all of the bars in a chart whenever the mouse is clicked:

	JCChartStyle[] style=c.getDataView(1).getChartStyle();
		for(int:=0; i < styles.length, i++);
		JCFillStyle fs=styles[i].getFillStyle();
		fs.setColor(fg.getColor().brighten());

Customizing Chart Styles

Each JCChartStyle object is made up of three smaller objects that control different aspects of the style:

Many of the most common chart style sub-properties are repeated in JCChartStyle. For example, FillColor is a property of JCChartStyle that corresponds to the Color property of JCFillStyle object. A complete list of repeated properties is provided in the following list:


Using a Time-axis

JClass Chart enables you to draw charts displaying data that changes over time. To do this, specify that the axis is to be treated as a time dimension by setting one of the following time-related properties in JCAxis:

For example, the following statement sets the starting point to January 15, 1985:

	c.getChartArea().getXAxis(0).setTimeBase(newDate(15,0,85));

And the following sets the starting point to the current time:

	c.getChartArea().getXAxis(0).setTimeBase(newDate());

Date Methods

The dateToValue method converts a Java date value into a time-axis position (a floating-point value). To convert a time-axis position to a date, use the ValueToDate method. For example:
JCAxis y;
date d.valueToDate(3.0)double val=y.datetoValue(newDate(90,1,0));

To convert a date to a formatted text string, use the JCChartTimeUtil.timeLabel. This method takes a format string and a Java Date object.


Data Sources

JClass Chart does not "own" the data, even though it uses an internal data representation to speed up display. There are a number of ways of getting data into JClass Chart.

Chartable and EditableChartable

The Chartable and EditableChartable objects are Java interfaces. They are intended for use with existing data objects. (Java's single inheritance does not allow for a lightweight mix-in class unless it is an interface. Using an interface allows an existing object to preserve its class inheritance.) Both Chartable and EditableChartable assume data is available in table form, and is well-suited to retrieve data that originates from databases or other "flat" files. The ChartDataView object contains a collection of ChartDataViewSeries objects; one for each data series in the data view.

ChartDataView and ChartDataViewSeries are used to control how the data is used by JClass Chart. DataSource is a property of ChartDataView that points to the data source. In JClass Chart, the DataSource is an object derived from Chartable, EditableChartable or ChartDataModel.

The Chartable interface contains elements for retrieving data. An object that implements the Chartable interface can be attached to ChartDataView as a data source using the DataSource property. ChartDataView uses its DataSource property to retrieve data for display. Example uses of Chartable can be found throughout the demos. The basic demo (jclass/chart/demos/basic/) contains ArrayData.java and GeneralData.java, two good examples of data sources that use the Chartable interface.

The EditableChartable interface extends the Chartable interface so that it includes methods for setting data in the data source. EditableChartable can be attached to the DataSource property of ChartDataView. In this case, user changes to the data are sent back to the data source. This represents another level of connectivity between JClass Chart and the external data source. A good example can be found in the table demo (jclass/chart/demos/table/) in Data.java.

The ChartDataModel class is an abstract class that extends EditableChartable. In order to make use of ChartDataModel, developers must use it as a base class. The advantage of using ChartDataModel is that the ChartDataModel can use model-view to update JClass Chart. In other words, ChartDataView will be registered as an Observer of ChartDataModel. This allows the external data object to inform JClass Chart of changes to the data.

The model-view aspect of ChartDataModel is handled by the Java utility classes Observer and Observable. ChartDataView inherits from Observer. ChartDataModel inherts from Observable. If a ChartDataModel is attached to the DataSource property of a ChartDataView instance, it will register itself with the ChartDataModel. In the object derived from ChartDataModel (i.e. the external data source object), a call to update() will send a message to ChartDataView.

The details of the messages sent from ChartDataModel to ChartDataView are handled by the ChartDataModelUpdate class. An instance of ChartDataModelUpdate must be constructed by the external data source and passed to the update() method. Possible messages include CHANGE_VALUE, NEW_VALUE, CHANGE_ROW, NEW_ROW. For a complete list of messages, see the API documentation for ChartDataModelUpdate. A good example of an updating data source can be found in the strip chart demonstration program (jclass/chart/demos/stripper/) in StripperData.java.


Stock Data Sources

For most users, the details of Chartable, EditableChartable, ChartDataModel and ChartDataModelUpdate are too cumbersome for most simple tasks. To this end, JClass Chart provides a number of pre-fabricated data sources, including:

Note for all of the data sources listed above, a fixed format for file data is used, as is explained in the following section.

InputStreamDataSource and Other Stock Data Sources

This class is the base for any data source that relies on input from a data stream. This includes such things as files, URLs, large strings, and other formats. The other three sources are derived from this file source format.

InputStreamDataSource uses the readArrayData method, which reads the data from the stream as if it is in array format--one set of X-axis data, multiple sets of Y-axis data.

The data may or may not be transposed. For example, the two following data files are equivalent:

ARRAY 2 4  # 2 series (+x-data) w. 4 points each
1 2 3 4    # x-data
1 2 3 4    # y1
1 4 9 16   # y2


ARRAY 2 4 T
1 1 1
2 2 4
3 3 9
4 4 16

The following are two further examples of equivalent data files that incorporate both name and point labels:

ARRAY 'My Chart' 2 4
                 'Point Label 1' 'Point Label 2' 'Point Label 3' 'Point Label 4'
'X Axis Data'    1               2               3               4
'Y Axis #1 Data' 1               2               3               4
'Y Axis #2 Data' 1               4               9               16 

ARRAY 'MyChart' 2 4 T
                'X Data' 'Y Data' 'Y 2 Data'
'Point Label 1' 1        1        1
'Point Label 2' 2        2        4
'Point Label 3' 3        3        9
'Point Label 4' 4        4        16

The other external file formats are all derived from InputStreamDataSource. URLDataSource takes a URL and turns it into a Chartable data source. FileDataSource creates an InputStreamDataSource from a file, and AppletDataSource pulls the data from the DATA <PARAM> tag associated with the specified applet.

For more detailed information on the format used by the stock data sources, see the API documentation for InputStreamDataSource.


Image-Filled Bar Charts

It is possible to use image to fill a bar chart. This is accomplished by using the Image property of JCFillStyle. The Image property sets the image used to paint the fill region of bar charts. It takes an AWT Image class representing the image to be used to paint image fills. If set to null, no image fill is done.

The following code fragment shows how Image can be incorporated into a program:

	// Set the labels of each series.
	String seriesLabels[] = {"CD", "Cassette"};
	String imageStrings[] = {"cd.gif", "tape.gif"};
	ChartDataViewSeries seriesList[] = arr.getSeries();
	for (int i = 0; i < arr.getNumSeries(); i++) {
		if (i < seriesLabels.length) {
			seriesList[i].setLabel(seriesLabels[i]);
			if (imageStrings[i] != null) {
				seriesList[i].getStyle().getFillStyle().setImage(
					this, imageStrings[i]);
			}
		}
	}

The effects can be seen in the ImageBar demonstration program, (in the jclass/chart/demos/imagebar/ directory), which comes with JClass Chart.

The imagebar demonstration program displayed

The image is clipped at the point of the highest value indicated for the bar chart.

Image only tiles the image along a single axis. For example, if the bars were widened in the above illustration, it would still tile along the vertical Y-axis only, and would not fill in the image across the horizontal X-axis. This same principle applies (though along different axes) of the bar chart is rotated 90 degree.

Note: Image can only be used with the image formats that can be used in Java.


Using JCStrings

There are often cases where it would be desirable to add such things as images, text and hyperlinks within a JClass Chart component, particularly if the component is to be used within an Applet. Most JClass Chart components support a rich text format called "JCString", which allows a mixture of hypertext, images and text within Chart components. Text can also appear in a variety of colors, fonts and styles, including underline and strikeout.

For example, the following line of code adds a number of JCStrings within a chart (in this case, the Exploder demonstration included with JClass Chart):

	c.getHeader().getLabel().setText("[IMAGE=yuri.gif][FONT=TimesRoman-italic-20] 
Yuri Presents ...[NEWLINE][VERT_SPACE=5][FONT=TimesRoman-bold-16]The Exploding Pie Slice Demo
[NEWLINE][FONT=TimesRoman-plain-16]Pick a slice and watch it explode![NEWLINE]", true);

For more information on the types of JCStrings available in JClass Chart, see "JCString Properties".


Using Pick and Unpick

The pick method is used to retrieve an x,y coordinate in a Chart from user input and then translate that into selecting the data point nearest to it. For example, if a user clicks within a single bar within a bar chart, pick takes the coordinates of the mouse-click and selects that bar for any action within the program. Similarly, if a user clicks in an area immediately above a bar chart, pick is used to select the bar that is closest to the mouse click.

Consider the following code listing (the code that comprises the DrillDown demonstration program that comes with JClass Chart, in jclass/chart/demo/drilldown/) in which demonstrates how pick can be used to "drill down" to reveal more information:

package jclass.chart.demos.drilldown;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.GridLayout;
import jclass.bwt.BWTEnum;
import jclass.chart.ChartDataView;
import jclass.chart.ChartDataViewSeries;
import jclass.chart.EventTrigger;
import jclass.chart.JCAxis;
import jclass.chart.JCPickListener;
import jclass.chart.JCPickEvent;
import jclass.chart.JCChartStyle;
import jclass.chart.JCChart;
import jclass.chart.JCChartLabel;
import jclass.chart.JCDataIndex;
import jclass.chart.JCLegend;
import jclass.chart.JCChartArea;
import jclass.chart.demos.DemoFrame;
/** This applet demonstrates using pick to drill down to more refined data **/
public class DrillDown extends Applet implements JCPickListener
{
Data d = null;
JCChart c = null;
public void init()
{
        setLayout(new BorderLayout(10,10));
        d = new Data();
        Color Turquoise = new Color(64,224,208);
        Color DarkTurquoise = new Color(0x00,0xce,0xd1);
        //Color DarkerTurquoise = new Color(0x00,0x9c,0x9e);
        c = new JCChart(this, "chart");
        c.setTrigger(0, new EventTrigger(0, EventTrigger.PICK));
        c.setBackground(DarkTurquoise);
        c.getChartArea().getInterior().setBackground(Turquoise);
        c.getChartArea().setBorderWidth(4);
        c.getChartArea().setBorderType(BWTEnum.SHADOW_ETCHED_IN);
        c.getHeader().setBackground(Turquoise);
        c.getHeader().getLabel().setText("[FONT=TimesRoman-bold-16]Drill Down Demo\n[FONT=TimesRoman-plain-16]Independent Comic Book Sales 1996", true);
        c.getHeader().setBorderType(BWTEnum.SHADOW_ETCHED_OUT);
        c.getHeader().setIsShowing(true);
        c.getLegend().setIsShowing(true);
        c.getLegend().setBackground(Turquoise);
        c.getLegend().setBorderType(BWTEnum.SHADOW_IN);
        c.setIsBatched(false);
        JCChartStyle.resetDefaults();
        c.getDataView(0).setDataSource(d);
        c.getDataView(0).setChartType(JCChart.BAR);
        c.getDataView(0).setHoleValue(-1000);
    
        c.getFooter().setIsShowing(true);
        c.getFooter().getLabel().setText("[FONT=TimesRoman-italic-12]Drill Down -> Mouse Down on Bar or Legend\nDrill Up -> Mouse Down on Other Area of Graph", true);
        c.getFooter().setAdjust(JCChartLabel.LEFT);
        c.getChartArea().setDepth(10);
        c.getChartArea().setElevation(20);
        c.getChartArea().setRotation(20);
        // Set colors for each data series
        Color colors[] = {Color.red, Color.blue, Color.white, Color.magenta, 
                          Color.green, Color.cyan, Color.orange, 
                          Color.yellow};
        ChartDataView arr = c.getDataView(0);
        ChartDataViewSeries seriesList[] = arr.getSeries();
        for (int i = 0; i < arr.getNumSeries(); i++) {
                seriesList[i].getStyle().setFillColor(colors[i]);
        }
        JCAxis yaxis = arr.getYAxis();
        
        // Set up pick and rotate trigger
        c.setTrigger(0, new EventTrigger(0, EventTrigger.PICK));
        c.setTrigger(0, new EventTrigger(Event.SHIFT_MASK, EventTrigger.ROTATE));
        // Add listener for pick events
        c.addPickListener(this);
        add("Center",c);
}
/** Pick event listener.  Upon receipt of a pick event, it either drills
 *  up or down to more general or refined data.
 */

public void pick(JCPickEvent e)
{        JCDataIndex di = e.getPickResult();
        // If clicked on bar or legend item, drill down.  If clicked on
        // any other area of chart, drill up.
        if (di != null) {
                Object obj = di.getObject();
                ChartDataView vw = di.getDataView();
                int srs = di.getSeriesIndex();
                int pt = di.getPoint();
                int dist = di.getDistance();
        
                if (vw != null && srs != -1) {
                        if (srs >= 0) {
                                if ((obj instanceof JCLegend) ||
                                        (obj instanceof JCChartArea && dist == 0))
                                        d.downLevel(srs);
                                else
                                        d.upLevel();
                        }
                } else {
                        d.upLevel();
                }
        } else {
                d.upLevel();
        }
}
public static void main(String args[]) {
        DemoFrame f = new DemoFrame("Basic Drilldown example");
        DrillDown tc = new DrillDown();
        tc.init();
        f.setLayout(new GridLayout(1,1));
        f.add(tc);
        f.pack();
        f.show();
        f.resize(500,400);
	}
}

When compiled and run, the DrillDown.class program displays the following:

The DrillDown demonstration program displayed

When a bar or legend within this chart is clicked by the user, the program "drills down" to reveal more refined data comprising that bar. If an area outside of the bars is clicked upon, then the program "drills up" to reveal more general data.

pick is key to this program, determining the way the program interacts with the user. pick requires an event trigger and listener to work, as the following code fragment shows:

        c.setTrigger(0, new EventTrigger(0, EventTrigger.PICK));
        c.setTrigger(0, new EventTrigger(Event.SHIFT_MASK, EventTrigger.ROTATE));
        c.addPickListener(this);
		add("Center",c);
}
public void pick(JCPickEvent e)
{
        JCDataIndex di = e.getPickResult();

When a user clicks in the DrillDown demonstration program, the event is triggered, the x,y coordinates are passed along to the pick event listener, which in turn takes the information and performs the indicated action. The pick method returns a JCDataIndex which encapsulates the point index and data series of the selected point.

Pick Focus

pick normally takes an x,y coordinate value, but it can take an x or y value only, which is useful for specific chart types. This can be specified using the PickFocus property, which specifies how distance is determined for pick operations. When set to PICK_FOCUS_XY (default), a pick operation will use the actual distance between the point and the drawn data. When set to values of PICK_FOCUS_X or PICK_FOCUS_Y, only the distance along the X- or Y-axis is used.

This is a particularly useful method to use within programs that display typical bar charts. In most cases it is more desirable to know which bar the user is over than which bar the user is closest to when the user clicks their mouse over a chart.

For example, a user may click over a relatively small bar in a bar chart, with the intension of raising the value of the bar displayed. If an adjacent bar in the chart is closer to the area of the mouse click along the Y-axis than the X-axis, then the adjacent bar could be selected instead of the intended target bar.

To overcome this, use PickFocus and select the axis whose values are to be reported back to the program. For example, the following line of code sets PickFocus to only report the x coordinate of a pick event:

	arr.setPickFocus(ChartDataView.PICK_FOCUS_X);

Unpick

The unpick method essentially functions in the opposite manner of pick: given a data series and a data point within that series, unpick returns the pixel coordinates of that point relative to the chart area. It takes two sets of parameters: pt for the point index, and series for the data series. For bar charts it returns the top-middle location for a given bar, and the middle of an arc for a pie chart. unpick can be used to display information at a given point in a chart, and can be used for attaching labels to chart regions.