1
votes

My question is related to Pan chart using mouse - Jfreechart but I face a very specific problem. My chart shows some retrospective TimeSeries-coded data and predicted values along a DateAxis. I want the user to be able to pan the data on the chart along in time, but prevent showing any data further than my prediction time window. I know the maximum date of my data, but somehow I need during the panning event find out if my DateAxis object yet reached this maximum date yet. The source code of PanHandlerFX gives me clues about where my mouse is and about the dragging distance, but how can I know what this means in terms of the Range shown on the DateAxis? Can anyone help? Thank you in advance.

1
Why not limit the projection in the model (dataset)? - trashgod
The projection length is limited to 4 hours, but without modification it was possible just to pan into the future as long as one liked. I have a dirty solution, not nice, because it works only, if the user pans at reasonable speed. At high speed, the axis is panned beyond my last projection date. - Ulrike Pielmeier

1 Answers

1
votes

This is what I did: I checked the direction of the scroll, and if my maximum date on DateAxis is after the predefined max date of my handler class, the method just returns.

public class PanHandlerFXWithDateLimit extends PanHandlerFX {

    public PanHandlerFXWithDateLimit(String id, boolean altKey, boolean ctrlKey, boolean metaKey, boolean shiftKey) {
        super(id, altKey, ctrlKey, metaKey, shiftKey);
    }

    /** The last mouse location seen during panning. */ 
    private Point2D panLast; 

    private double panW; 
    private double panH; 


    private Date panMaxTo;

    /**
     * Handles a mouse pressed event by recording the initial mouse pointer 
     * location. 
     *  
     * @param canvas  the JavaFX canvas (<code>null</code> not permitted). 
     * @param e  the mouse event (<code>null</code> not permitted). 
     */ 
    @Override 
    public void handleMousePressed(ChartCanvas canvas, MouseEvent e) { 
        Plot plot = canvas.getChart().getPlot(); 
        if (!(plot instanceof Pannable)) { 
            canvas.clearLiveHandler(); 
            return; 
        } 
        Pannable pannable = (Pannable) plot; 
        if (pannable.isDomainPannable() || pannable.isRangePannable()) { 
            Point2D point = new Point2D.Double(e.getX(), e.getY()); 
            Rectangle2D dataArea = canvas.findDataArea(point); 
            if (dataArea != null && dataArea.contains(point)) { 
                this.panW = dataArea.getWidth(); 
                this.panH = dataArea.getHeight(); 
                this.panLast = point; 
                canvas.setCursor(javafx.scene.Cursor.MOVE); 
            } 
        } 
        // the actual panning occurs later in the mouseDragged() method 
    } 

    /**
     * Handles a mouse dragged event by calculating the distance panned and 
     * updating the axes accordingly. 
     *  
     * @param canvas  the JavaFX canvas (<code>null</code> not permitted). 
     * @param e  the mouse event (<code>null</code> not permitted). 
     */ 
    @Override
    public void handleMouseDragged(ChartCanvas canvas, MouseEvent e) { 
        if (this.panLast == null) { 
            //handle panning if we have a start point else unregister 
            canvas.clearLiveHandler(); 
            return; 
        } 

        JFreeChart chart = canvas.getChart(); 
        double dx = e.getX() - this.panLast.getX(); 
        double dy = e.getY() - this.panLast.getY(); 


        if (dx == 0.0 && dy == 0.0) { 
            return; 
        } 

        /** if dx is negative, the scroll is to the right side, 
         * therefore we must check if displayed axis end is after panMax date - then stop panning
         */
        if (dx < 0.0) {
            XYPlot p = (XYPlot) chart.getPlot();
            if (((DateAxis)p.getDomainAxis()).getMaximumDate().after(panMaxTo))
               return;
        }

        double wPercent = -dx / this.panW; 
        double hPercent = dy / this.panH; 
        boolean old = chart.getPlot().isNotify(); 
        chart.getPlot().setNotify(false); 
        Pannable p = (Pannable) chart.getPlot(); 
        PlotRenderingInfo info = canvas.getRenderingInfo().getPlotInfo(); 
        if (p.getOrientation().isVertical()) { 
            p.panDomainAxes(wPercent, info, this.panLast); 
            p.panRangeAxes(hPercent, info, this.panLast); 
        } 
        else { 
            p.panDomainAxes(hPercent, info, this.panLast); 
            p.panRangeAxes(wPercent, info, this.panLast); 
        } 
        this.panLast = new Point2D.Double(e.getX(), e.getY()); 
        chart.getPlot().setNotify(old); 
    } 

    @Override
    public void handleMouseReleased(ChartCanvas canvas, MouseEvent e) {   
        //if we have been panning reset the cursor 
        //unregister in any case 
        if (this.panLast != null) { 
            canvas.setCursor(javafx.scene.Cursor.DEFAULT); 
        } 
        this.panLast = null; 
        canvas.clearLiveHandler(); 
    } 

    /**
     * @param panMaxTo the panMaxTo to set
     */
    public final void setPanMaxTo(Date panMaxTo) {
        if (panMaxTo == null) this.panMaxTo = Date.from(Instant.now());
        else this.panMaxTo = panMaxTo;
        //System.out.println(this.panMaxTo.toString());
}