/*
* CCVisu is a tool for visual graph clustering
* and general force-directed graph layout.
* This file is part of CCVisu.
*
* Copyright (C) 2005-2012 Dirk Beyer
*
* CCVisu is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* CCVisu 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CCVisu; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please find the GNU Lesser General Public License in file
* license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
*
* Dirk Beyer (firstname.lastname@uni-passau.de)
* University of Passau, Bavaria, Germany
*/
package org.sosy_lab.ccvisu.ui;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import org.sosy_lab.ccvisu.Options.OptionsEnum;
import org.sosy_lab.ccvisu.graph.GraphData;
import org.sosy_lab.ccvisu.graph.GraphEdge;
import org.sosy_lab.ccvisu.graph.GraphVertex;
import org.sosy_lab.ccvisu.ui.FrameDisplay.GraphCanvas;
import org.sosy_lab.util.Colors;
public class FrameDisplayMenu implements ActionListener {
private GraphCanvas frameDisplayCanvas;
private GraphData graph;
private JPopupMenu featureMenu;
private JMenuItem menuItemZoomOut;
private JMenuItem menuItemVertexColor;
private JMenuItem menuItemVertexToBackground;
private JMenuItem menuItemHideUnrelatedVertices;
private JMenuItem menuItemResetHighlighting;
private List<JComponent> menuItemsRelations = new ArrayList<JComponent>();
private Map<Integer, Color> edgeColors = new HashMap<Integer, Color>();
private Map<Integer, Color> vertexColors = new HashMap<Integer, Color>();
private GraphVertex featureVertex = null;
public FrameDisplayMenu(GraphCanvas frameDisplay, GraphData graph) {
this.frameDisplayCanvas = frameDisplay;
this.graph = graph;
}
// Handle action on the MenuItems
@Override
public void actionPerformed(ActionEvent actionevent) {
if (actionevent.getSource() == menuItemZoomOut) {
frameDisplayCanvas.zoomOut();
} else if (actionevent.getSource() == menuItemVertexColor) {
Color selectedColor = JColorChooser.showDialog(frameDisplayCanvas, "Select Color", Color.black);
featureVertex.setColor(selectedColor);
for (GraphEdge e : frameDisplayCanvas.getWriter().getGraphData().getAdjacent(featureVertex, "Introduces")) {
e.getTarget().setColor(selectedColor);
}
} else if (actionevent.getSource() == menuItemHideUnrelatedVertices) {
hideEdges();
for (GraphEdge e : frameDisplayCanvas.getWriter().getGraphData().getEdges()) {
e.setShowEdge(false);
}
Set<GraphVertex> visibleVertices = new HashSet<GraphVertex>();
visibleVertices.add(featureVertex);
for (GraphEdge e : frameDisplayCanvas.getWriter().getGraphData().getAdjacent(featureVertex, ".*")) {
visibleVertices.add(e.getTarget());
e.setShowEdge(true);
}
for (GraphVertex vertex : frameDisplayCanvas.getWriter().getGraphData().getVertices()) {
if (!visibleVertices.contains(vertex)) {
vertex.setShowVertex(false);
}
}
} else if (actionevent.getSource() == menuItemVertexToBackground) {
// TODO: ??
System.out.println("move vertex to background");
} else if (actionevent.getSource() == menuItemResetHighlighting) {
for (GraphEdge e : frameDisplayCanvas.getWriter().getGraphData().getEdges()) {
e.setShowEdge(false);
}
for (Integer id : edgeColors.keySet()) {
GraphEdge edge = frameDisplayCanvas.getWriter().getGraphData().getEdgeById(id);
if (edge != null) {
edge.setColor(edgeColors.get(id));
}
}
for (Integer id : vertexColors.keySet()) {
GraphVertex vertex = frameDisplayCanvas.getWriter().getGraphData().getVertexById(id);
if (vertex != null) {
vertex.setColor(vertexColors.get(id));
}
}
resetHighlightingCache();
} else {
// Highlight chosen relation
if (actionevent.getSource() instanceof JMenuItem) {
String relName = ((JMenuItem) actionevent.getSource()).getName();
hideEdges();
for (GraphEdge e : frameDisplayCanvas.getWriter().getGraphData().getAdjacent(featureVertex, relName)) {
e.setShowEdge(true);
if (!edgeColors.containsKey(e.getId())) {
edgeColors.put(e.getId(), e.getColor());
}
e.setColor(Colors.get("red"));
if (!vertexColors.containsKey(e.getTarget().getId())) {
vertexColors.put(e.getTarget().getId(), e.getTarget().getColor());
}
e.getTarget().setColor(Colors.get("red"));
}
}
}
graph.notifyAboutLayoutChange(new EventObject(this));
}
public void resetHighlightingCache() {
edgeColors.clear();
vertexColors.clear();
}
private void hideEdges() {
frameDisplayCanvas.getWriter().getOptions().getOption(OptionsEnum.showEdges).set(false);
}
public JPopupMenu createMenu() {
featureMenu = new JPopupMenu();
menuItemZoomOut = new JMenuItem("Zoom out / Reset vertex restrictions");
menuItemZoomOut.addActionListener(this);
featureMenu.add(menuItemZoomOut);
menuItemVertexColor = new JMenuItem("Select vertex color");
menuItemVertexColor.addActionListener(this);
featureMenu.add(menuItemVertexColor);
menuItemHideUnrelatedVertices = new JMenuItem("Hide unrelated vertices");
menuItemHideUnrelatedVertices.addActionListener(this);
featureMenu.add(menuItemHideUnrelatedVertices);
menuItemVertexToBackground = new JMenuItem("Move vertex to background");
menuItemVertexToBackground.addActionListener(this);
featureMenu.add(menuItemVertexToBackground);
JSeparator separator = new JSeparator();
featureMenu.add(separator);
menuItemResetHighlighting = new JMenuItem("Reset highlighting");
menuItemResetHighlighting.addActionListener(this);
featureMenu.add(menuItemResetHighlighting);
return featureMenu;
}
public void updateAndShowMenu(MouseEvent evt, Set<String> vertexRelations, GraphVertex featureVertex) {
// Remove out-dated menu items
for (JComponent menuItem : menuItemsRelations) {
featureMenu.remove(menuItem);
}
if (vertexRelations.size() > 0) {
for (String relName : vertexRelations) {
JMenuItem relMenuItem = new JMenuItem("Highlight " + relName + " relations");
relMenuItem.setName(relName);
relMenuItem.addActionListener(this);
menuItemsRelations.add(relMenuItem);
featureMenu.add(relMenuItem);
}
}
menuItemVertexColor.setEnabled(featureVertex != null);
menuItemHideUnrelatedVertices.setEnabled((featureVertex != null)
&& (frameDisplayCanvas.getWriter().getGraphData().isEdgesAvailable()));
menuItemVertexToBackground.setEnabled(featureVertex != null);
menuItemResetHighlighting.setEnabled((edgeColors.size() > 0) && (vertexColors.size() > 0));
this.featureVertex = featureVertex;
featureMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
}