diff --git a/README.md b/README.md index a0fc79c..8b9a136 100644 --- a/README.md +++ b/README.md @@ -228,6 +228,14 @@ graphView.setEdgeDoubleClickAction(graphEdge -> { These actions will be performed whenever you *double-click* a vertex and/or an edge. +Other available actions are: +- `setVertexSingleClickAction` +- `setVertexRightClickAction` +- `setEdgeSingleClickAction` +- `setEdgeRightClickAction` +- `setCanvasSingleClickAction` + + ## Configuration and Styling ### SmartGraph Properties diff --git a/src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java b/src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java index 1b54457..c638b17 100644 --- a/src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java +++ b/src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java @@ -34,6 +34,7 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.geometry.BoundingBox; import javafx.geometry.Bounds; +import javafx.geometry.Point2D; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Tooltip; @@ -115,11 +116,22 @@ public class SmartGraphPanel extends Pane { /* * INTERACTION WITH VERTICES AND EDGES */ - + /** Function to be executed when a vertex is clicked twice. */ + private Consumer> vertexDoubleClickConsumer; /** Function to be executed when a vertex is clicked. */ - private Consumer> vertexClickConsumer; - /** Function to be executed when an edge is clicked. */ - private Consumer> edgeClickConsumer; + private Consumer> vertexSingleClickConsumer; + /** Function to be executed when a vertex is right clicked. */ + private Consumer> vertexRightClickConsumer; + /** Function to be executed when the canvas is clicked */ + private Consumer canvasSingleClickConsumer; + + /** Function to be executed when an edge is clicked twice */ + private Consumer> edgeDoubleClickConsumer; + /** Function to be executed when an edge is clicked */ + private Consumer> edgeSingleClickConsumer; + /** Function to be executed when an edge is right clicked */ + private Consumer> edgeRightClickConsumer; + /* * OPTIONAL PROVIDERS FOR LABELS, RADII AND SHAPE TYPES OF NODES. @@ -197,15 +209,19 @@ public SmartGraphPanel(@NamedArg("graph") Graph theGraph, // consumers initially are not set. This initialization is not necessary, but we make it explicit // for the sake of readability - this.vertexClickConsumer = null; - this.edgeClickConsumer = null; + this.vertexDoubleClickConsumer = null; + this.vertexSingleClickConsumer = null; + this.vertexRightClickConsumer = null; + this.edgeDoubleClickConsumer = null; + this.edgeSingleClickConsumer = null; + this.edgeRightClickConsumer = null; //set stylesheet and class loadAndApplyStylesheet(cssFile); initNodes(); - enableDoubleClickListener(); + enableClickListener(); //automatic layout initializations timer = new AnimationTimer() { @@ -1513,13 +1529,61 @@ private boolean areAdjacent(SmartGraphVertexNode v, SmartGraphVertexNode u return v.isAdjacentTo(u); } + /* + * INTERACTION WITH VERTICES AND EDGES + */ /** * Sets the action that should be performed when a vertex is double-clicked. * * @param action action to be performed */ public void setVertexDoubleClickAction(Consumer> action) { - this.vertexClickConsumer = action; + this.vertexDoubleClickConsumer = action; + } + + /** + * Sets the action that should be performed when canvas is single-clicked + * + * @param action action to be performed + */ + public void setCanvasSingleClickAction(Consumer action) { + this.canvasSingleClickConsumer = action; + } + + /** + * Sets the action that should be performed when a vertex is single-clicked. + * + * @param action action to be performed + */ + public void setVertexSingleClickAction(Consumer> action) { + this.vertexSingleClickConsumer = action; + } + + /** + * Sets the action that should be performed when a vertex is right-clicked. + * + * @param action action to be performed + */ + public void setVertexRightClickAction(Consumer> action) { + this.vertexRightClickConsumer = action; + } + + /** + * Sets the action that should be performed when an edge is double-clicked. + * + * @param action action to be performed + */ + public void setEdgeSingleClickAction(Consumer> action) { + this.edgeSingleClickConsumer = action; + } + + /** + * Sets the action that should be performed when an edge is right-clicked. + * + * @param action action to be performed + */ + public void setEdgeRightClickAction(Consumer> action) { + this.edgeRightClickConsumer = action; } /** @@ -1528,9 +1592,11 @@ public void setVertexDoubleClickAction(Consumer> action) { * @param action action to be performed */ public void setEdgeDoubleClickAction(Consumer> action) { - this.edgeClickConsumer = action; + this.edgeDoubleClickConsumer = action; } + + /** * Sets the vertex label provider for this SmartGraphPanel. *
@@ -1673,38 +1739,77 @@ private void loadAndApplyStylesheet(URI cssFile) { } /** - * Enables the double click action on this pane. + * Enables the click action on this pane. *
* This method identifies the node that was clicked and, if any, calls the * appropriate consumer, i.e., vertex or edge consumers. */ @SuppressWarnings("unchecked") - private void enableDoubleClickListener() { + private void enableClickListener() { setOnMouseClicked((MouseEvent mouseEvent) -> { if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) { - if (mouseEvent.getClickCount() == 2) { + if (mouseEvent.getClickCount() == 1) { + Node node = pick(SmartGraphPanel.this, mouseEvent.getSceneX(), mouseEvent.getSceneY()); + if (node == SmartGraphPanel.this) { + // transform from scene to local to prevent wrong coordinate on zooming + Point2D localPoint = this.sceneToLocal(mouseEvent.getSceneX(), mouseEvent.getSceneY()); + if(this.canvasSingleClickConsumer != null) { + this.canvasSingleClickConsumer.accept(localPoint); + } + } + if (node == null) { + return; + } + if (node instanceof SmartGraphVertex) { + SmartGraphVertex v = (SmartGraphVertex) node; + if (vertexSingleClickConsumer != null) { // Only if the consumer is set + vertexSingleClickConsumer.accept(v); + } + } else if (node instanceof SmartGraphEdge) { + SmartGraphEdge e = (SmartGraphEdge) node; + if (edgeSingleClickConsumer != null) { // Only if the consumer is set + edgeSingleClickConsumer.accept(e); + } + } + }else if (mouseEvent.getClickCount() == 2) { Node node = pick(SmartGraphPanel.this, mouseEvent.getSceneX(), mouseEvent.getSceneY()); if (node == null) { return; } - if (node instanceof SmartGraphVertex) { SmartGraphVertex v = (SmartGraphVertex) node; - if(vertexClickConsumer != null) { // Only if the consumer is set - vertexClickConsumer.accept(v); + if (vertexDoubleClickConsumer != null) { // Only if the consumer is set + vertexDoubleClickConsumer.accept(v); } } else if (node instanceof SmartGraphEdge) { - SmartGraphEdge e = (SmartGraphEdge) node; - if(edgeClickConsumer != null) { // Only if the consumer is set - edgeClickConsumer.accept(e); + SmartGraphEdge e = (SmartGraphEdge) node; + if (edgeDoubleClickConsumer != null) { // Only if the consumer is set + edgeDoubleClickConsumer.accept(e); } } } + } else if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) { + Node node = pick(SmartGraphPanel.this, mouseEvent.getSceneX(), mouseEvent.getSceneY()); + if (node == null) { + return; + } + if (node instanceof SmartGraphVertex) { + SmartGraphVertex v = (SmartGraphVertex) node; + if (vertexRightClickConsumer != null) { // Only if the consumer is set + vertexRightClickConsumer.accept(v); + } + } else if (node instanceof SmartGraphEdge) { + SmartGraphEdge e = (SmartGraphEdge) node; + if (edgeRightClickConsumer != null) { // Only if the consumer is set + edgeRightClickConsumer.accept(e); + } + } } }); } + /** * Represents a tuple in Java. *