Writing your own interactor
When writing your own interactor, you can use and extend the source code of the built-in JViews Charts interactors. You find this source code in the <installdir>/jviews-charts/samples/interactor/src/ directory.
This example is extracted from the stock sample. The source code of this example can be found in
<installdir>/jviews-charts/samples/stock/src/stock/ZoomScaleInteractor.java directory.
The ZoomScaleInteractor class defined in this example allows the user to zoom a given portion of the display area by selecting the area to zoom in on the scale itself instead of on the plot area.
1. Extend the IlvChartInteractor class.
public class ZoomScaleInteractor extends IlvChartInteractor
{ ... }
2. Define the attributes of the class.
private boolean swap = false; protected IlvStyle
style; protected int axisIdx; protected double start; protected
double end;
The axisIdx attribute specifies the axis index on which the zoom is performed (-1 = x-axis). The bounds of the zoomed area are defined by the start and end attributes. This data is updated each time the mouse is dragged.
3. Add the constructor.
/** * Create new ZoomScaleInteractor associated
with the specified axis * that zoom in on a BUTTON1 event and zoom
out on SHIFT+BUTTON1. */ public ZoomScaleInteractor(int axisIdx) {
super(axisIdx != -1 ? axisIdx : 0, MouseEvent.BUTTON1_MASK);
this.axisIdx = axisIdx; renderer = new IlvStyle(new BasicStroke(5),
IlvColor.magenta); ...
An interactor is always attached to a unique y-axis. Indeed, since several y-axes may coexist on the same chart, an interactor needs to know on which y-axis the interactions are performed, so that conversions from display space to data space (and vice versa) are possible. This y-axis is referenced at the IlvChartInteractor level using its index and is the first parameter of the constructor.
We want to handle both mouse motion events and mouse click events, as well as key events (to handle cancellation using ‘ESC’ key):
... enableEvents(AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.KEY_EVENT_MASK); }
4. Filter the events.
Since the interaction is performed on the scale, the interactor is only interested in the events that occur within the scale bounds:
public boolean isHandling(int x, int y) {
return (getScale() != null) ? getScale().getBounds(scaleBounds).contains(x,
y) : false; }
5. Process the events.
The event coordinate is converted to a data value on the scale, and the start and end attributes are initialized to the previous and next steps of the scale, respectively.
public void processMouseEvent(MouseEvent evt)
{ double value; switch (evt.getID()) { case MouseEvent.MOUSE_PRESSED
: ... startOperation(evt); value = getScale().toValue(evt.getX(),
evt.getY()); start = getScale().getStepsDefinition().previousStep(value);
end = getScale().getStepsDefinition().incrementStep(start);
drawGhost(); evt.consume(); ...
break; ... }
The
drawGhost method is then called. This method allows you to have a visual feedback of the interaction by temporarily drawing over the chart area.
Mouse dragged events are handled as follows:
public void processMouseMotionEvent(MouseEvent
evt) { if (evt.getID() == MouseEvent.MOUSE_DRAGGED && isInOperation()){
drawGhost(); double value = getScale().toValue(evt.getX(),
evt.getY()); computeStartEnd(value); drawGhost();
evt.consume(); } }
First erase the previous ghost (note that it has effects only in XOR mode), then compute the new start and end values, and finally draw the new ghost.
The zoom is effectively performed when the button is released.
public void processMouseEvent(MouseEvent evt)
{ ... case MouseEvent.MOUSE_RELEASED: if (!isInOperation())
break; value = getScale().toValue(evt.getX(),
evt.getY()); computeStartEnd(value); drawGhost();
zoomScale(); endOperation(evt);
evt.consume(); break; ... }
The new start and end values are computed, the scale is zoomed, and the interaction is set as ended. Finally, we want to cancel the interaction that is performed when the ‘ESC’ key is pressed:
public void processKeyEvent(KeyEvent evt)
{ if (evt.getID() == KeyEvent.KEY_PRESSED && evt.getKeyCode()
== KeyEvent.VK_ESCAPE ) { if (isInOperation())
drawGhost(); abort(); evt.consume(); } }
If the interactor is in operation, the ghost is erased (it has only effects in XOR mode), and the interaction state is set as aborted, with the
abort method implemented as follows:
protected void abort() { super.abort();
swap = false; /* Disable ghost drawing operation */ setAllowDrawGhost(false);
}
6. Draw a ghost.
A ghost can be drawn either in XOR mode or in Paint mode, depending on the value of the interactor xorGhost property. By default, most of the default interactors draw their ghost in paint mode. In a general manner, XOR mode should be avoided due to the poor control it gives on the drawing.
To be able to draw a ghost, an interactor must first enable the draw ghost mechanism, calling the
setAllowDrawGhost method with
true as parameter, and disable it when the interaction ends. This is performed by the
startOperation and
endOperation methods:
protected void endOperation(MouseEvent evt)
{ super.endOperation(evt); swap = false; /* Disable ghost
drawing operation */ setAllowDrawGhost(false); } protected void
startOperation(MouseEvent evt) { super.startOperation(evt);
/* Enable ghost drawing operation */ setAllowDrawGhost(true);
}
NOTE When overriding one of the startOperation, endOperation or abort methods, do not forget to call the corresponding super method since it performs several required internal initializations.
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.