/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> Website : http://www.gephi.org This file is part of Gephi. Gephi is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gephi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Gephi. If not, see <http://www.gnu.org/licenses/>. */ package org.gephi.visualization.bridge; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.gephi.data.attributes.api.AttributeController; import org.gephi.data.attributes.api.AttributeModel; import org.gephi.desktop.project.api.ProjectControllerUI; import org.gephi.graph.api.Graph; import org.gephi.graph.api.GraphController; import org.gephi.graph.api.GraphModel; import org.gephi.graph.api.GroupData; import org.gephi.graph.api.HierarchicalGraph; import org.gephi.graph.api.Model; import org.gephi.graph.api.Node; import org.gephi.graph.api.NodeData; import org.gephi.project.api.ProjectController; import org.gephi.project.api.Workspace; import org.gephi.visualization.VizArchitecture; import org.gephi.visualization.VizController; import org.gephi.visualization.apiimpl.GraphIO; import org.gephi.visualization.apiimpl.ModelImpl; import org.gephi.visualization.api.objects.ModelClass; import org.gephi.visualization.hull.ConvexHull; import org.gephi.visualization.opengl.AbstractEngine; import org.gephi.visualization.opengl.compatibility.objects.ConvexHullModel; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.Lookup; /** * * @author Mathieu Bastian */ public class DHNSEventBridge implements EventBridge, VizArchitecture { //Architecture private AbstractEngine engine; private HierarchicalGraph graph; private GraphIO graphIO; private GraphController graphController; @Override public void initArchitecture() { this.engine = VizController.getInstance().getEngine(); this.graphIO = VizController.getInstance().getGraphIO(); this.graphController = Lookup.getDefault().lookup(GraphController.class); initEvents(); } @Override public void initEvents() { } //GROUPING public boolean canExpand() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null && graph.getDescendantCount(node) > 0) { return true; } } return false; } public boolean canContract() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null && graph.getParent(node) != null) { return true; } } return false; } public boolean canGroup() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); int nodesReallyPresent = 0; for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null) { nodesReallyPresent++; } } return nodesReallyPresent >= 1; } public boolean canUngroup() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); return selectedNodeModels.length >= 1; } public void expand() { this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); final ModelImpl[] models = Arrays.copyOf(selectedNodeModels, selectedNodeModels.length); new Thread(new Runnable() { public void run() { try { for (ModelImpl metaModelImpl : models) { Node node = ((NodeData) metaModelImpl.getObj()).getNode(graph.getView().getViewId()); if (node != null && graph.getDescendantCount(node) > 0) { expandPositioning(node); graph.expand(node); } } } catch (Exception e) { e.printStackTrace(); graph.readUnlockAll(); } } }, "Expand nodes").start(); } public void contract() { this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); final ModelImpl[] models = Arrays.copyOf(selectedNodeModels, selectedNodeModels.length); new Thread(new Runnable() { public void run() { try { Set<Node> parents = new HashSet<Node>(); for (ModelImpl metaModelImpl : models) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null) { Node nodeParent = graph.getParent(node); if (nodeParent != null) { parents.add(nodeParent); } } } for (Node parent : parents) { GroupData gd = (GroupData) parent.getNodeData(); if (gd.getHullModel() != null) { ConvexHull hull = ((ConvexHullModel) gd.getHullModel()).getObj(); contractPositioning(hull); } graph.retract(parent); } } catch (Exception e) { e.printStackTrace(); graph.readUnlockAll(); } } }, "Contract nodes").start(); } public void group() { this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); final List<Node> newGroup = new ArrayList<Node>(); for (int i = 0; i < selectedNodeModels.length; i++) { Node node = ((NodeData) selectedNodeModels[i].getObj()).getNode(graph.getView().getViewId()); if (node != null) { newGroup.add(node); } } new Thread(new Runnable() { public void run() { try { float centroidX = 0; float centroidY = 0; int len = 0; float sizes = 0; float r = 0; float g = 0; float b = 0; Node group = graph.groupNodes(newGroup.toArray(new Node[0])); group.getNodeData().setLabel("Group (" + newGroup.size() + " nodes)"); group.getNodeData().setSize(10f); for (Node child : newGroup) { centroidX += child.getNodeData().x(); centroidY += child.getNodeData().y(); len++; sizes += child.getNodeData().getSize() / 10f; r += child.getNodeData().r(); g += child.getNodeData().g(); b += child.getNodeData().b(); } centroidX /= len; centroidY /= len; group.getNodeData().setSize(sizes); group.getNodeData().setColor(r / len, g / len, b / len); group.getNodeData().setX(centroidX); group.getNodeData().setY(centroidY); } catch (Exception e) { graph.readUnlockAll(); NotifyDescriptor.Message nd = new NotifyDescriptor.Message(e.getMessage()); DialogDisplayer.getDefault().notifyLater(nd); } } }, "Group nodes").start(); } public void ungroup() { this.graph = graphController.getModel().getHierarchicalGraph(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); final ModelImpl[] models = Arrays.copyOf(selectedNodeModels, selectedNodeModels.length); new Thread(new Runnable() { public void run() { try { Set<Node> parents = new HashSet<Node>(); for (ModelImpl metaModelImpl : models) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null && graph.getDescendantCount(node) > 0) { parents.add(node); } else if (node != null && graph.getParent(node) != null) { parents.add(graph.getParent(node)); } } for (Node parent : parents) { graph.ungroupNodes(parent); } } catch (Exception e) { graph.readUnlockAll(); NotifyDescriptor.Message nd = new NotifyDescriptor.Message(e.getMessage()); DialogDisplayer.getDefault().notifyLater(nd); } } }, "Ungroup nodes").start(); } private void expandPositioning(Node node) { NodeData nodeData = node.getNodeData(); float centroidX = 0; float centroidY = 0; int len = 0; Node[] children = graph.getChildren(node).toArray(); for (Node child : children) { centroidX += child.getNodeData().x(); centroidY += child.getNodeData().y(); len++; } centroidX /= len; centroidY /= len; float diffX = nodeData.x() - centroidX; float diffY = nodeData.y() - centroidY; for (Node child : children) { NodeData nd = child.getNodeData(); nd.setX(nd.x() + diffX); nd.setY(nd.y() + diffY); } } private void contractPositioning(ConvexHull hull) { NodeData metaNode = hull.getMetaNode().getNodeData(); metaNode.setX(hull.x()); metaNode.setY(hull.y()); ConvexHullModel model = (ConvexHullModel) hull.getModel(); model.setScale(0.9f); model.setScaleQuantum(-0.1f); } //SETTLE AND FREE public boolean canSettle() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); if (!nodeData.isFixed()) { return true; } } return false; } public boolean canFree() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); if (nodeData.isFixed()) { return true; } } return false; } public void settle() { this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); nodeData.setFixed(true); } } public void free() { this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); nodeData.setFixed(false); } } //DELETE public boolean canDelete() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } this.graph = graphController.getModel().getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); int nodesReallyPresent = 0; for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null) { nodesReallyPresent++; } } return nodesReallyPresent >= 1; } public void delete() { this.graph = graphController.getModel().getHierarchicalGraph(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); for (ModelImpl model : selectedNodeModels) { NodeData nodeData = (NodeData) model.getObj(); Node node = nodeData.getRootNode(); if (node != null) { graph.removeNode(node); } } } //MOVE & COPY WORKSPACE public boolean canMoveOrCopyWorkspace() { GraphModel graphModel = graphController.getModel(); if (graphModel == null) { return false; } ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); int nodesReallyPresent = 0; for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(graph.getView().getViewId()); if (node != null) { nodesReallyPresent++; } } return nodesReallyPresent >= 1; } public void moveToWorkspace(Workspace workspace) { copyToWorkspace(workspace); delete(); } public void moveToNewWorkspace() { Workspace workspace = Lookup.getDefault().lookup(ProjectControllerUI.class).newWorkspace(); moveToWorkspace(workspace); } public void copyToWorkspace(Workspace workspace) { AttributeController attributeController = Lookup.getDefault().lookup(AttributeController.class); ProjectController projectController = Lookup.getDefault().lookup(ProjectController.class); Workspace currentWorkspace = projectController.getCurrentWorkspace(); AttributeModel sourceAttributeModel = attributeController.getModel(currentWorkspace); AttributeModel destAttributeModel = attributeController.getModel(workspace); destAttributeModel.mergeModel(sourceAttributeModel); GraphModel sourceModel = graphController.getModel(currentWorkspace); GraphModel destModel = graphController.getModel(workspace); Graph destGraph = destModel.getHierarchicalGraphVisible(); Graph sourceGraph = sourceModel.getHierarchicalGraphVisible(); ModelImpl[] selectedNodeModels = engine.getSelectedObjects(AbstractEngine.CLASS_NODE); List<Node> nodes = new ArrayList<Node>(); for (ModelImpl metaModelImpl : selectedNodeModels) { NodeData nodeData = (NodeData) metaModelImpl.getObj(); Node node = nodeData.getNode(sourceGraph.getView().getViewId()); if (node != null && destGraph.getNode(node.getNodeData().getId()) == null) { nodes.add(node); } } destModel.pushNodes(sourceGraph, nodes.toArray(new Node[0])); } public void copyToNewWorkspace() { Workspace workspace = Lookup.getDefault().lookup(ProjectControllerUI.class).newWorkspace(); copyToWorkspace(workspace); } public void mouseClick(ModelClass objectClass, Model[] clickedObjects) { } }