package ch.rakudave.jnetmap.view.jung;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Collection;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import net.xeoh.plugins.base.util.PluginManagerUtil;
import org.apache.commons.collections15.Factory;
import ch.rakudave.jnetmap.controller.Controller;
import ch.rakudave.jnetmap.controller.Scheduler;
import ch.rakudave.jnetmap.model.Connection;
import ch.rakudave.jnetmap.model.device.Device;
import ch.rakudave.jnetmap.plugins.RightClickAction;
import ch.rakudave.jnetmap.util.Icons;
import ch.rakudave.jnetmap.util.Lang;
import ch.rakudave.jnetmap.util.logging.Logger;
import ch.rakudave.jnetmap.view.components.StatusBar;
import ch.rakudave.jnetmap.view.components.TabPanel;
import ch.rakudave.jnetmap.view.properties.ConnectionProperties;
import ch.rakudave.jnetmap.view.properties.DeviceProperties;
import ch.rakudave.jnetmap.view.properties.InterfaceProperties;
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.Pair;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin;
import edu.uci.ics.jung.visualization.picking.PickedState;
/**
* a plugin that uses popup menus to create vertices, undirected edges, and
* directed edges.
*
* @author Tom Nelson, rakudave
*
*/
public class PopupGraphMousePlugin extends AbstractPopupGraphMousePlugin {
private Frame owner;
private Factory<Device> vertexFactory;
private JMenu plugins;
private Device vertex;
@SuppressWarnings("serial")
public PopupGraphMousePlugin(Frame owner, Factory<Device> vertexFactory) {
this.owner = owner;
this.vertexFactory = vertexFactory;
plugins = new JMenu(Lang.get("preferences.plugins"));
plugins.setIcon(Icons.get("plugin"));
for (final RightClickAction p : new PluginManagerUtil(Controller.pm).getPlugins(RightClickAction.class)) {
plugins.add(new AbstractAction(p.getPluginName(), p.getIcon()) {
@Override
public void actionPerformed(ActionEvent e) {
try {
Scheduler.execute(new Runnable() {
@Override
public void run() {
p.execute(vertex);
}
});
} catch (Exception ex) {
Logger.error("An error occured in plugin '" + p.getPluginName() + "'", ex);
}
}
});
}
}
@SuppressWarnings({"unchecked", "serial" })
protected void handlePopup(MouseEvent e) {
JPopupMenu popup = new JPopupMenu();
final VisualizationViewer<Device, Connection> vv = (VisualizationViewer<Device, Connection>) e
.getSource();
final Layout<Device, Connection> layout = vv.getGraphLayout();
final Graph<Device, Connection> graph = layout.getGraph();
final Point2D p = e.getPoint();
final Point2D ivp = p;
GraphElementAccessor<Device, Connection> pickSupport = vv.getPickSupport();
if (pickSupport != null) {
vertex = pickSupport.getVertex(layout, ivp.getX(), ivp.getY());
final Connection edge = pickSupport.getEdge(layout, ivp.getX(), ivp.getY());
final PickedState<Device> pickedVertexState = vv.getPickedVertexState();
final PickedState<Connection> pickedEdgeState = vv.getPickedEdgeState();
if (vertex != null) {
pickedVertexState.pick(vertex, false);
if (plugins.getMenuComponentCount() > 0) {
popup.add(plugins);
}
popup.add(new AbstractAction(Lang.get("menu.view.refresh"), Icons.get("refresh")) {
@Override
public void actionPerformed(ActionEvent e) {
Scheduler.execute(new Runnable() {
@Override
public void run() {
StatusBar.getInstance().setBusy(true);
StatusBar.getInstance().setMessage(Lang.getNoHTML("message.status.update").replaceAll("%name%", vertex.getName()));
vertex.updateStatus();
try {
Collection<Device> neighbors = Controller.getCurrentMap().getNeighbors(vertex);
if (!neighbors.isEmpty()) for (Device d : neighbors) d.updateStatus();
} catch (Exception e) {
Logger.error("Failed to update the neighbors of "+vertex, e);
}
StatusBar.getInstance().setBusy(false);
StatusBar.getInstance().clearMessage();
TabPanel.getCurrentTab().repaint();
}
});
}
});
popup.add(new AbstractAction(Lang.get("device.properties"), Icons.get("properties")) {
@Override
public void actionPerformed(ActionEvent e) {
new DeviceProperties(owner, vertex, false);
}
});
popup.add(new AbstractAction(Lang.get("action.delete"), Icons.get("remove")) {
public void actionPerformed(ActionEvent e) {
graph.removeVertex(vertex);
vv.repaint();
}
});
} else if (edge != null) {
pickedEdgeState.pick(edge, false);
popup.add(new AbstractAction(Lang.get("connection.properties"), Icons.get("properties")) {
@Override
public void actionPerformed(ActionEvent e) {
Pair<Device> p = Controller.getCurrentMap().getEndpoints(edge);
if (p.getFirst().equals(p.getSecond())) {
new InterfaceProperties(owner, p.getFirst().getInterfaceFor(edge));
} else {
new ConnectionProperties(owner, edge);
}
}
});
popup.add(new AbstractAction(Lang.get("action.delete"), Icons.get("remove")) {
public void actionPerformed(ActionEvent e) {
graph.removeEdge(edge);
vv.repaint();
}
});
} else {
popup.add(new AbstractAction(Lang.get("action.add"), Icons.get("add")) {
public void actionPerformed(ActionEvent e) {
Device newVertex = vertexFactory.create();
new DeviceProperties(owner, newVertex, true);
graph.addVertex(newVertex);
layout.setLocation(newVertex, vv.getRenderContext()
.getMultiLayerTransformer().inverseTransform(p));
vv.repaint();
}
});
}
if (popup.getComponentCount() > 0) {
popup.show(vv, e.getX(), e.getY());
}
}
}
}