From f7e401d981ce4eb68a63f2d29ca69132392bd2c7 Mon Sep 17 00:00:00 2001 From: David Bohn <davbohn@googlemail.com> Date: Fri, 8 Jul 2016 21:23:44 +0200 Subject: [PATCH] Implemented functionality to handle node click --- .../configurations/AbstractConfiguration.java | 31 +++++++++ .../configurations/GephiConfiguration.java | 64 +++---------------- .../configurations/internal/GephiLoader.java | 50 +++++++++++++++ .../internal/NodeClickHandler.java | 12 ++++ .../java/fucoin/gui/gephi/GraphWindow.java | 34 +++++++++- .../gui/gephi/MouseListenerTemplate.java | 13 ++-- .../fucoin/gui/gephi/NodeMouseListener.java | 10 +++ 7 files changed, 149 insertions(+), 65 deletions(-) create mode 100644 src/main/java/fucoin/configurations/internal/GephiLoader.java create mode 100644 src/main/java/fucoin/configurations/internal/NodeClickHandler.java create mode 100644 src/main/java/fucoin/gui/gephi/NodeMouseListener.java diff --git a/src/main/java/fucoin/configurations/AbstractConfiguration.java b/src/main/java/fucoin/configurations/AbstractConfiguration.java index 07fcb48..2672665 100644 --- a/src/main/java/fucoin/configurations/AbstractConfiguration.java +++ b/src/main/java/fucoin/configurations/AbstractConfiguration.java @@ -5,6 +5,7 @@ import akka.actor.Props; import akka.pattern.Patterns; import akka.util.Timeout; import fucoin.AbstractNode; +import fucoin.actions.control.ActionAddOverlayNeighbours; import fucoin.actions.control.ActionAnnounceWalletCreation; import fucoin.actions.control.ActionWalletSendMoney; import fucoin.actions.join.ActionTellSupervisor; @@ -14,6 +15,8 @@ import fucoin.actions.transaction.ActionNotifyObserver; import fucoin.configurations.internal.ConfigurationCreator; import fucoin.supervisor.SuperVisorImpl; import fucoin.wallet.WalletImpl; +import org.gephi.graph.api.Edge; +import org.gephi.graph.api.Graph; import org.gephi.graph.api.Node; import scala.concurrent.Await; import scala.concurrent.Future; @@ -21,6 +24,7 @@ import scala.concurrent.duration.Duration; import java.util.*; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; /** * @@ -192,4 +196,31 @@ public abstract class AbstractConfiguration extends AbstractNode { } public abstract void run(); + + protected void createOverlayNetwork(Graph g) { + Collection<Node> nodes = g.getNodes().toCollection(); + + try { + spawnWalletsFromNodes(nodes, false); + } catch (Exception e) { + e.printStackTrace(); + } + + nodes.stream().forEach(node -> { + ActorRef wallet = walletByName(node.getLabel()); + Edge[] edges = g.getEdges(node).toArray(); + + // Search for all reachable neighbours of the node + // by filtering the list of incident edges of the node + // and retrieve the respective ActorRef instance + List<ActorRef> overlayNeighbours = Arrays.stream(edges).filter(edge -> !edge.isDirected() || edge.getSource() == node).map(edge -> { + if (edge.getSource() == node) { + return edge.getTarget(); + } + return edge.getSource(); + }).map(target -> walletByName(target.getLabel())).collect(Collectors.toList()); + + wallet.tell(new ActionAddOverlayNeighbours(overlayNeighbours), self()); + }); + } } diff --git a/src/main/java/fucoin/configurations/GephiConfiguration.java b/src/main/java/fucoin/configurations/GephiConfiguration.java index cc01d89..0e035f1 100644 --- a/src/main/java/fucoin/configurations/GephiConfiguration.java +++ b/src/main/java/fucoin/configurations/GephiConfiguration.java @@ -1,25 +1,12 @@ package fucoin.configurations; -import akka.actor.ActorRef; -import fucoin.actions.control.ActionAddOverlayNeighbours; import fucoin.configurations.internal.ConfigurationName; +import fucoin.configurations.internal.GephiLoader; import fucoin.gui.gephi.GraphWindow; -import org.gephi.graph.api.Edge; import org.gephi.graph.api.Graph; -import org.gephi.graph.api.GraphController; -import org.gephi.graph.api.Node; -import org.gephi.io.importer.api.Container; -import org.gephi.io.importer.api.ImportController; -import org.gephi.io.processor.plugin.DefaultProcessor; -import org.gephi.project.api.ProjectController; -import org.gephi.project.api.Workspace; -import org.openide.util.Lookup; -import java.io.File; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; +import java.io.FileNotFoundException; +import java.net.URISyntaxException; @ConfigurationName("Gephi Test Configuration") public class GephiConfiguration extends AbstractConfiguration { @@ -27,51 +14,20 @@ public class GephiConfiguration extends AbstractConfiguration { public void run() { initSupervisor(); - ProjectController pc = Lookup.getDefault().lookup(ProjectController.class); + GephiLoader gephiLoader = new GephiLoader(); - pc.newProject(); - Workspace workspace = pc.getCurrentWorkspace(); - - Container container; - ImportController importController = Lookup.getDefault().lookup(ImportController.class); + Graph g; try { - File file = new File(getClass().getResource("/topology2.gexf").toURI()); - container = importController.importFile(file); - } catch (Exception ex) { - ex.printStackTrace(); - return; - } - - importController.process(container, new DefaultProcessor(), workspace); - - Graph g = Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace).getGraph(); - - Collection<Node> nodes = g.getNodes().toCollection(); - - try { - spawnWalletsFromNodes(nodes, false); - } catch (Exception e) { + g = gephiLoader.loadFileFromResources("/topology2.gexf"); + } catch (URISyntaxException | FileNotFoundException e) { e.printStackTrace(); + return; } - nodes.stream().forEach(node -> { - ActorRef wallet = walletByName(node.getLabel()); - Edge[] edges = g.getEdges(node).toArray(); - - // Search for all reachable neighbours of the node - // by filtering the list of incident edges of the node - // and retrieve the respective ActorRef instance - List<ActorRef> overlayNeighbours = Arrays.stream(edges).filter(edge -> !edge.isDirected() || edge.getSource() == node).map(edge -> { - if (edge.getSource() == node) { - return edge.getTarget(); - } - return edge.getSource(); - }).map(target -> walletByName(target.getLabel())).collect(Collectors.toList()); - - wallet.tell(new ActionAddOverlayNeighbours(overlayNeighbours), self()); - }); + createOverlayNetwork(g); GraphWindow graphWindow = new GraphWindow(); + graphWindow.addNodeClickHandler((node, event) -> System.out.println(node.getLabel() + " wurde angeklickt!")); graphWindow.setVisible(true); } diff --git a/src/main/java/fucoin/configurations/internal/GephiLoader.java b/src/main/java/fucoin/configurations/internal/GephiLoader.java new file mode 100644 index 0000000..67f1644 --- /dev/null +++ b/src/main/java/fucoin/configurations/internal/GephiLoader.java @@ -0,0 +1,50 @@ +package fucoin.configurations.internal; + +import org.gephi.graph.api.Graph; +import org.gephi.graph.api.GraphController; +import org.gephi.graph.api.Node; +import org.gephi.io.importer.api.Container; +import org.gephi.io.importer.api.ImportController; +import org.gephi.io.processor.plugin.DefaultProcessor; +import org.gephi.project.api.ProjectController; +import org.gephi.project.api.Workspace; +import org.openide.util.Lookup; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; + +/** + * @author davidbohn + */ +public class GephiLoader { + + Workspace workspace; + + public Graph loadFileFromResources(String path) throws URISyntaxException, FileNotFoundException { + return loadFile(getClass().getResource(path).toURI()); + } + + public Graph loadFile(URI filename) throws FileNotFoundException { + ProjectController pc = Lookup.getDefault().lookup(ProjectController.class); + + pc.newProject(); + workspace = pc.getCurrentWorkspace(); + + Container container; + ImportController importController = Lookup.getDefault().lookup(ImportController.class); + File file = new File(filename); + container = importController.importFile(file); + + + importController.process(container, new DefaultProcessor(), workspace); + + return Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace).getGraph(); + } + + public Workspace getWorkspace() { + return workspace; + } +} diff --git a/src/main/java/fucoin/configurations/internal/NodeClickHandler.java b/src/main/java/fucoin/configurations/internal/NodeClickHandler.java new file mode 100644 index 0000000..01a207c --- /dev/null +++ b/src/main/java/fucoin/configurations/internal/NodeClickHandler.java @@ -0,0 +1,12 @@ +package fucoin.configurations.internal; + +import org.gephi.graph.api.Node; +import org.gephi.preview.api.PreviewMouseEvent; + +import java.util.function.BiConsumer; + +/** + * @author davidbohn + */ +public interface NodeClickHandler extends BiConsumer<Node, PreviewMouseEvent> { +} diff --git a/src/main/java/fucoin/gui/gephi/GraphWindow.java b/src/main/java/fucoin/gui/gephi/GraphWindow.java index e2d1a85..d4e1a20 100644 --- a/src/main/java/fucoin/gui/gephi/GraphWindow.java +++ b/src/main/java/fucoin/gui/gephi/GraphWindow.java @@ -1,14 +1,24 @@ package fucoin.gui.gephi; +import fucoin.configurations.internal.NodeClickHandler; +import org.gephi.graph.api.Node; import org.gephi.preview.api.*; import org.gephi.preview.types.DependantOriginalColor; +import org.gephi.project.api.Workspace; import org.openide.util.Lookup; import javax.swing.*; import java.awt.*; import java.lang.reflect.Field; +import java.util.*; +import java.util.List; + +public class GraphWindow extends JFrame implements NodeMouseListener { + + protected List<NodeClickHandler> clickHandlers = new ArrayList<>(); + private final PreviewController previewController; + private final PreviewSketch previewSketch; -public class GraphWindow extends JFrame { public GraphWindow() { super(); @@ -16,7 +26,7 @@ public class GraphWindow extends JFrame { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - PreviewController previewController = Lookup.getDefault().lookup(PreviewController.class); + previewController = Lookup.getDefault().lookup(PreviewController.class); PreviewModel previewModel = previewController.getModel(); previewModel.getProperties().putValue(PreviewProperty.SHOW_NODE_LABELS, Boolean.TRUE); previewModel.getProperties().putValue(PreviewProperty.NODE_LABEL_COLOR, new DependantOriginalColor(Color.BLACK)); @@ -26,9 +36,10 @@ public class GraphWindow extends JFrame { previewModel.getProperties().putValue(PreviewProperty.EDGE_CURVED, Boolean.FALSE); previewModel.getProperties().putValue(PreviewProperty.EDGE_OPACITY, 50); previewModel.getProperties().putValue(PreviewProperty.EDGE_RADIUS, 10f); + previewModel.getProperties().putValue("graphWindow.mouse.handler", this); G2DTarget target = (G2DTarget) previewController.getRenderTarget(RenderTarget.G2D_TARGET); - PreviewSketch previewSketch = new PreviewSketch(target, isRetina()); + previewSketch = new PreviewSketch(target, isRetina()); this.add(previewSketch, BorderLayout.CENTER); @@ -58,4 +69,21 @@ public class GraphWindow extends JFrame { } return false; } + + @Override + public void mouseClicked(Node node, PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) { + clickHandlers.stream().forEach(nodeClickHandler -> nodeClickHandler.accept(node, event)); + } + + public void addNodeClickHandler(NodeClickHandler handler) { + clickHandlers.add(handler); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + + previewController.refreshPreview(); + previewSketch.repaint(); + } } diff --git a/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java b/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java index 99af506..5e5d39a 100644 --- a/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java +++ b/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java @@ -9,23 +9,20 @@ import org.gephi.project.api.Workspace; import org.openide.util.Lookup; import org.openide.util.lookup.ServiceProvider; -import javax.swing.*; - @ServiceProvider(service = PreviewMouseListener.class) public class MouseListenerTemplate implements PreviewMouseListener { @Override public void mouseClicked(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) { for (Node node : Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace).getGraph().getNodes()) { if (clickingInNode(node, event)) { - properties.putValue("display-label.node.id", node.getId()); - System.err.println("Node " + node.getLabel() + " clicked!");//System.out is ignored in Netbeans platform applications!! - JOptionPane.showMessageDialog(null, "Node " + node.getLabel() + " clicked!"); - event.setConsumed(true);//So the renderer is executed and the graph repainted + if (properties.hasProperty("graphWindow.mouse.handler")) { + NodeMouseListener listener = properties.getValue("graphWindow.mouse.handler"); + listener.mouseClicked(node, event, properties, workspace); + } + event.setConsumed(true); return; } } - - properties.removeSimpleValue("display-label.node.id"); event.setConsumed(true);//So the renderer is executed and the graph repainted } diff --git a/src/main/java/fucoin/gui/gephi/NodeMouseListener.java b/src/main/java/fucoin/gui/gephi/NodeMouseListener.java new file mode 100644 index 0000000..348028b --- /dev/null +++ b/src/main/java/fucoin/gui/gephi/NodeMouseListener.java @@ -0,0 +1,10 @@ +package fucoin.gui.gephi; + +import org.gephi.graph.api.Node; +import org.gephi.preview.api.PreviewMouseEvent; +import org.gephi.preview.api.PreviewProperties; +import org.gephi.project.api.Workspace; + +public interface NodeMouseListener { + public void mouseClicked(Node node, PreviewMouseEvent event, PreviewProperties properties, Workspace workspace); +} -- GitLab