All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.piccolo2d.event.PDragSequenceEventHandler Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2019, Piccolo2D project, http://piccolo2d.org
 * Copyright (c) 1998-2008, University of Maryland
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions
 * and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 * and the following disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its
 * contributors may be used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.piccolo2d.event;

import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;

import org.piccolo2d.activities.PActivity;
import org.piccolo2d.util.PUtil;


/**
 * PDragSequenceEventHandler is designed to support mouse pressed,
 * dragged, and released interaction sequences. Support is also provided for
 * running a continuous activity during the drag sequence.
 * 

* PDragSequenceEventHandler should be subclassed by a concrete event handler * that implements a particular interaction. See PPanEventHandler, * PZoomEventHandler, and PDragEventHandler for examples. *

* * @version 1.0 * @author Jesse Grosjean */ public abstract class PDragSequenceEventHandler extends PBasicInputEventHandler { private double minDragStartDistance = 0; private transient boolean isDragging = false; private transient Point2D mousePressedCanvasPoint; private transient PActivity dragActivity; private transient PInputEvent dragEvent; private transient int sequenceInitiatedButton = MouseEvent.NOBUTTON; /** Constructs a drag sequence event handler instance. */ public PDragSequenceEventHandler() { } /** * Returns true if this event handler is in the process of handling a drag. * * @return true if handling a drag */ public boolean isDragging() { return isDragging; } /** * Used to inform this handler that it is in the process of handling a drag. * * @param isDragging true if handler is processing a drag */ public void setIsDragging(final boolean isDragging) { this.isDragging = isDragging; } /** * Returns the minimum distance (in screen coordinates) before a pressed * mouse movement is registered as a drag event. The smaller this value the * more clicks will be incorrectly recognized as drag events. * * @return minimum distance a pressed mouse must move before it is * registered as a drag */ public double getMinDragStartDistance() { return minDragStartDistance; } /** * Set the minimum distance that the mouse should be dragged (in screen * coordinates) before a new drag sequence is initiate. * * @param minDistance in screen coordinates */ public void setMinDragStartDistance(final double minDistance) { minDragStartDistance = minDistance; } /** * Return the point in canvas coordinates where the mouse was last pressed. * * @return point in canvas coordinates of last mouse press */ public Point2D getMousePressedCanvasPoint() { if (mousePressedCanvasPoint == null) { mousePressedCanvasPoint = new Point2D.Double(); } return mousePressedCanvasPoint; } // **************************************************************** // Dragging - Methods to indicate the stages of the drag sequence. // **************************************************************** /** * Subclasses should override this method to get notified of the start of a * new drag sequence. Note that that overriding methods must still call * super.startDrag() for correct behavior. * * @param event event that started the drag sequence */ protected void startDrag(final PInputEvent event) { dragEvent = event; startDragActivity(event); setIsDragging(true); event.getComponent().setInteracting(true); } /** * Subclasses should override this method to get notified of the drag events * in a drag sequence. Note that that overriding methods must still call * super.startDrag() for correct behavior. * * @param event event that caused the drag */ protected void drag(final PInputEvent event) { dragEvent = event; } /** * Subclasses should override this method to get notified of the end event * in a drag sequence. Note that that overriding methods must still call * super.startDrag() for correct behavior. * * @param event event that ended the drag sequence */ protected void endDrag(final PInputEvent event) { stopDragActivity(event); dragEvent = null; event.getComponent().setInteracting(false); setIsDragging(false); } /** * Returns true if the provided event represents a valid start for a drag * sequence. * * Subclasses should override this method to add criteria for the start of a * drag sequence. Subclasses are still responsible for calling * super.shouldStartDragInteraction() * * @param event event being tested * @return true if provided event is a good start to a drag sequence */ protected boolean shouldStartDragInteraction(final PInputEvent event) { return getMousePressedCanvasPoint().distance(event.getCanvasPosition()) >= getMinDragStartDistance(); } // **************************************************************** // Drag Activity - Used for scheduling an activity during a drag // sequence. For example zooming and auto panning are implemented // using this. // **************************************************************** /** * Returns the scheduled activity that's updating the scene as a result to * the current drag activity (if any). * * @return scheduled activity that's updating the scene as a result to the * drag activity */ protected PActivity getDragActivity() { return dragActivity; } /** * Schedules the "infinite" drag activity so that auto-panning and zooming * will continue to update the scene even if there are no further drag * events fired. For example, if the mouse is dragged to the right while * pressing the right mouse button and then paused for a while, the scene * should continue to zoom in. * * @param event the event that's responsible for the start of the activity */ protected void startDragActivity(final PInputEvent event) { dragActivity = new PActivity(-1, PUtil.DEFAULT_ACTIVITY_STEP_RATE); dragActivity.setDelegate(new PActivity.PActivityDelegate() { public void activityStarted(final PActivity activity) { dragActivityFirstStep(dragEvent); } public void activityStepped(final PActivity activity) { dragActivityStep(dragEvent); } public void activityFinished(final PActivity activity) { dragActivityFinalStep(dragEvent); } }); event.getCamera().getRoot().addActivity(dragActivity); } /** * Stops the activity responsible for updating the scene. * * @param event The event responsible for stopping the drag activity */ protected void stopDragActivity(final PInputEvent event) { dragActivity.terminate(); dragActivity = null; } /** * Subclasses override this method to get notified when the drag activity * starts stepping. * * @param event the event responsible for the first step in the drag * activity */ protected void dragActivityFirstStep(final PInputEvent event) { } /** * During a drag sequence an activity is scheduled that runs continuously * while the drag sequence is active. This can be used to support some * additional behavior that is not driven directly by mouse events. For * example PZoomEventHandler uses it for zooming and PPanEventHandler uses * it for auto panning. * * @param event the event encapsulating the callback context for the * activity step */ protected void dragActivityStep(final PInputEvent event) { } /** * Subclasses should override this method to get notified when the drag * activity stops stepping. * * @param aEvent the event responsible for ending the activity */ protected void dragActivityFinalStep(final PInputEvent aEvent) { } /** * Subclasses should not override this method, instead they should * override the appropriate drag callbacks. * * @param event The event to be queried about the details of the mouse press */ public void mousePressed(final PInputEvent event) { super.mousePressed(event); if (sequenceInitiatedButton == MouseEvent.NOBUTTON) { sequenceInitiatedButton = event.getButton(); getMousePressedCanvasPoint().setLocation(event.getCanvasPosition()); if (!isDragging() && shouldStartDragInteraction(event)) { startDrag(event); } } } /** * Subclasses should not override this method, instead they should * override the appropriate drag method. * * @param event The event to be queried about the details of the mouse press */ public void mouseDragged(final PInputEvent event) { super.mouseDragged(event); if (sequenceInitiatedButton != MouseEvent.NOBUTTON) { if (!isDragging()) { if (shouldStartDragInteraction(event)) { startDrag(event); } return; } drag(event); } } /** * Subclasses should not override this method, instead they should * override the appropriate drag method. * * @param event The event to be queried about the details of the mouse release */ public void mouseReleased(final PInputEvent event) { super.mouseReleased(event); if (sequenceInitiatedButton == event.getButton()) { if (isDragging()) { endDrag(event); } sequenceInitiatedButton = MouseEvent.NOBUTTON; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy