org.eclipse.fx.ui.controls.dnd.EFXDnDAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.fx.ui.controls Show documentation
Show all versions of org.eclipse.fx.ui.controls Show documentation
Custom JavaFX controls like a styled text component, ...
/*******************************************************************************
* Copyright (c) 2015 BestSolution.at and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Schindl - initial API and implementation
*******************************************************************************/
package org.eclipse.fx.ui.controls.dnd;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import org.eclipse.fx.ui.controls.Util;
import javafx.event.Event;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
/**
* Allows a node to be adapted to the drag and drop system
*/
public class EFXDnDAdapter {
private final Node node;
private boolean dragInProgress;
private boolean dragStartSend;
private boolean dragStartFlag;
private BiFunction dragStartValidator;
private BiConsumer dragStartConsumer;
private BiConsumer dragDoneConsumer;
private Node eventTarget;
/**
* Create a new adapter
*
* @param node
* the node itself
* @param doneEventTarget
* the target the done event is sent to
*/
public EFXDnDAdapter(Node node, Node doneEventTarget) {
this.node = node;
this.eventTarget = doneEventTarget;
}
/**
* Enable dnd for the node
*/
public void enable() {
this.node.addEventHandler(MouseEvent.MOUSE_PRESSED, this::handleMousePressed);
this.node.addEventHandler(MouseEvent.MOUSE_DRAGGED, this::handleMouseDragged);
this.node.addEventHandler(MouseEvent.MOUSE_RELEASED, this::handleMouseReleased);
}
/**
* Disable dnd for the node
*/
public void disable() {
this.node.removeEventHandler(MouseEvent.MOUSE_PRESSED, this::handleMousePressed);
this.node.removeEventHandler(MouseEvent.MOUSE_DRAGGED, this::handleMouseDragged);
this.node.removeEventHandler(MouseEvent.MOUSE_RELEASED, this::handleMouseReleased);
}
/**
* Validate that the drag can start
*
* @param dragStartValidator
* a validator who can return false to veto the start of the drag
* operation
*/
public void setDragStartValidator(BiFunction dragStartValidator) {
this.dragStartValidator = dragStartValidator;
}
/**
* A consumer who is informed that the drag has started
*
* @param dragStartConsumer
* the consumer
*/
public void setDragStartConsumer(BiConsumer dragStartConsumer) {
this.dragStartConsumer = dragStartConsumer;
}
/**
* A consumer notified that the drag has finished
*
* @param dragDoneConsumer
* the consumer
*/
public void setDragDoneConsumer(BiConsumer dragDoneConsumer) {
this.dragDoneConsumer = dragDoneConsumer;
}
private void handleMousePressed(MouseEvent e) {
this.dragStartFlag = true;
}
private void handleMouseDragged(MouseEvent e) {
// Drag was started on a different node
if( ! this.dragStartFlag ) {
return;
}
if (!this.dragStartSend) {
if (this.dragStartValidator == null || !Boolean.FALSE.equals(this.dragStartValidator.apply(this, e))) {
EFXDragEvent event = new EFXDragEvent(this.node, this.node, EFXDragEvent.DRAG_START, e.getScreenX(), e.getScreenY(), false);
Event.fireEvent(this.node, event);
this.dragStartSend = true;
this.dragInProgress = event.getDraggedContent() != null;
if (this.dragInProgress && this.dragStartConsumer != null) {
this.dragStartConsumer.accept(this, event);
}
}
}
Node node = Util.findNode(this.node.getScene().getWindow(), e.getScreenX(), e.getScreenY());
if (this.dragInProgress) {
if (node != null) {
Event.fireEvent(node, new EFXDragEvent(this.node, node, EFXDragEvent.DRAG_OVER, e.getScreenX(), e.getScreenY(), false));
} else {
EFXDragEvent.updateFeedbackLocation(e.getScreenX(), e.getScreenY());
}
}
}
private void handleMouseReleased(MouseEvent e) {
this.dragStartSend = false;
this.dragStartFlag = false;
if (this.dragInProgress) {
Node node = Util.findNode(this.node.getScene().getWindow(), e.getScreenX(), e.getScreenY());
boolean isComplete = false;
if (node != null) {
EFXDragEvent event = new EFXDragEvent(node, node, EFXDragEvent.DRAG_DROPPED, e.getScreenX(), e.getScreenY(), false);
Event.fireEvent(node, event);
isComplete = event.isComplete();
}
EFXDragEvent event = new EFXDragEvent(this.eventTarget, this.eventTarget, EFXDragEvent.DRAG_DONE, e.getScreenX(), e.getScreenY(), isComplete);
Event.fireEvent(this.eventTarget, event);
if (this.dragDoneConsumer != null) {
this.dragDoneConsumer.accept(this, event);
}
}
this.dragInProgress = false;
}
}