InputEventHandlerUtil.java
package org.osate.ge.gef.ui.editor;
import org.osate.ge.gef.BaseConnectionNode;
import org.osate.ge.gef.ContainerShape;
import org.osate.ge.gef.DockedShape;
import org.osate.ge.gef.ui.diagram.GefAgeDiagram;
import org.osate.ge.internal.diagram.runtime.DiagramElement;
import org.osate.ge.internal.diagram.runtime.DiagramElementPredicates;
import org.osate.ge.internal.diagram.runtime.DiagramNode;
import javafx.event.EventTarget;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
/**
* Utility functions for implementing {@link InputEventHandler} and {@Interaction}
*/
public final class InputEventHandlerUtil {
/**
* Private constructor to prevent instantiation.
*/
private InputEventHandlerUtil() {
}
/**
* If the event target is a {@link Node}, walks up the scene graph and returns the first {@link DiagramNode} associated with the node
* or ancestors.
* @param gefDiagram is the diagram from which to get the diagram node
* @param target the event target. Returns null if the event target is not a {@link Node}
* @return the closest diagram node to the event target. Returns null if the event target is a null.
*/
public static DiagramNode getTargetDiagramNode(final GefAgeDiagram gefDiagram, final EventTarget target) {
if (!(target instanceof Node)) {
return null;
}
for (Node tmp = (Node) target; tmp != null; tmp = tmp.getParent()) {
if (tmp == gefDiagram.getSceneNode()) {
return gefDiagram.getDiagram();
}
final DiagramElement de = gefDiagram.getDiagramElement(tmp);
if (de != null
&& ((DiagramElementPredicates.isMoveableShape(de)
&& (!(de.getParent() instanceof DiagramElement)
|| !DiagramElementPredicates.isConnection((DiagramElement) de.getParent())))
|| DiagramElementPredicates.isConnection(de))) {
return de;
}
}
return null;
}
/**
* If the event target is a {@link Node}, walks up the scene graph and returns the first {@link DiagramElement} associated with the node
* or ancestors.
* @param gefDiagram is the diagram from which to get the diagram element
* @param target the event target. Returns null if the event target is not a {@link Node}
* @return the closest diagram element to the event target. Returns null if the event target is a null.
*/
public static DiagramElement getTargetDiagramElement(final GefAgeDiagram gefDiagram, final EventTarget target) {
final DiagramNode diagramNode = getTargetDiagramNode(gefDiagram, target);
return diagramNode instanceof DiagramElement ? (DiagramElement) diagramNode : null;
}
/**
* Rounds a 2D coordinate to either the editor's grid or to the nearest integer.
* @param editor the editor which defines the grid
* @param value the value to snap in diagram coordinates
* @param toGrid true to snap to the grid. If false, the value will be rounded to the nearest integer.
* @return the rounded value
*/
public static Point2D snap(final AgeEditor editor, final Point2D value, final boolean toGrid) {
return new Point2D(snapX(editor, value.getX(), toGrid), snapY(editor, value.getY(), toGrid));
}
/**
* Rounds an X value to either the editor's grid or to the nearest integer.
* @param editor the editor which defines the grid
* @param value the value to snap in diagram coordinates
* @param toGrid true to snap to the grid. If false, the value will be rounded to the nearest integer.
* @return the rounded value
*/
public static double snapX(final AgeEditor editor, final double value, final boolean toGrid) {
return snap(value, toGrid ? editor.getGridCellWidth() : 1.0);
}
/**
* Rounds an Y value to either the editor's grid or to the nearest integer.
* @param editor the editor which defines the grid
* @param value the value to snap
* @param toGrid true to snap to the grid. If false, the value will be rounded to the nearest integer.
* @return the rounded value
*/
public static double snapY(final AgeEditor editor, final double value, final boolean toGrid) {
return snap(value, toGrid ? editor.getGridCellWidth() : 1.0);
}
private static double snap(final double value, final double multiplier) {
return Math.round(value / multiplier) * multiplier;
}
/**
* Returns the specified or the closest ancestor which is an instance of {@link BaseConnectionNode}.
* @param node is the node for which to get the connection.
* @return the connection node or null if there is no such node.
*/
public static BaseConnectionNode getClosestConnection(final Node node) {
for (Node tmp = node; tmp != null; tmp = tmp.getParent()) {
if (tmp instanceof BaseConnectionNode) {
return (BaseConnectionNode) tmp;
}
}
return null;
}
/**
* Returns the closest ancestor which is a {@link ContainerShape} or {@link DockedShape}.
* Does not check the node itself.
* @param node the node for which to get the logical container.
* @return the logical container. Returns null if no ancestor meets the criteria.
*/
public static Node getLogicalShapeContainer(final Node node) {
for (Node tmp = node.getParent(); tmp != null; tmp = tmp.getParent()) {
if (tmp instanceof ContainerShape || tmp instanceof DockedShape) {
return tmp;
}
}
return null;
}
/**
* If the {@link EventTarget} is an instance of {@link Node}, walk up the node's parents
* to determine if the target is an instance of {@link ScrollBar}.
* @param target is the target
* @return whether the {@link EventTarget} is an instance of {@link ScrollBar}.
*/
public static boolean isScrollBar(final EventTarget target) {
if (target instanceof Node) {
for (Node tmp = (Node) target; tmp != null; tmp = tmp.getParent()) {
if (tmp instanceof ScrollBar) {
return true;
}
}
}
return false;
}
}