Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
nz.ac.waikato.modeljunit.gui.visualisaton.PanelJUNGVisualisation Maven / Gradle / Ivy
Go to download
Java library and GUI for supporting Model-Based Testing.
The models are extended finite state machines (EFSM) that are written in Java.
/**
Copyright (C) 2008 Jerramy Winchester
This file is part of the CZT project.
The CZT project contains free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
The CZT project 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with CZT; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nz.ac.waikato.modeljunit.gui.visualisaton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.LayoutStyle;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import nz.ac.waikato.modeljunit.GraphListener;
import nz.ac.waikato.modeljunit.Transition;
import nz.ac.waikato.modeljunit.gui.PanelAbstract;
import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.FRLayout2;
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.algorithms.layout.util.Relaxer;
import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.Pair;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.PickingGraphMousePlugin;
import edu.uci.ics.jung.visualization.control.PluggableGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingGraphMousePlugin;
import edu.uci.ics.jung.visualization.control.TranslatingGraphMousePlugin;
import edu.uci.ics.jung.visualization.decorators.AbstractEdgeShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.ConstantDirectionalEdgeValueTransformer;
import edu.uci.ics.jung.visualization.layout.LayoutTransition;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.subLayout.GraphCollapser;
import edu.uci.ics.jung.visualization.transform.MutableTransformer;
import edu.uci.ics.jung.visualization.util.Animator;
/**
* @author Jerramy Winchester
*
*/
public class PanelJUNGVisualisation extends PanelAbstract implements ActionListener, MouseListener {
/** serial version ID */
private static final long serialVersionUID = -1433533076588100620L;
//The main panels
private static PanelJUNGVisualisation m_panelGraph;
private static JUNGHelper jView_;
//variables necessary for merging of vertices and edges
private GraphCollapser collapser;
private Set exclusions;
// Transformers for the visualisation viewer
private EdgeFontTransformer e_eft;
private EdgeLabelTransformer e_elt;
private EdgePaintTransformer e_ept;
private EdgeStrokeTransformer e_est;
private EdgeDisplayPredicate e_edp;
private VertexFontTransformer v_vft;
private VertexLabelTransformer v_vlt;
private VertexGradientRenderer v_vgr;
private VertexStrokeTransformer v_vst;
private VertexShapeTransformer v_vsht;
private VertexEdgePaintTransformer v_vept;
private VertexDisplayPredicate v_vdp;
// main visualisation components
private Graph g = null;
private Layout layout;
private VisualizationViewer vv = null;
// Main containers for the various panels
private static JSplitPane treeAndViz;
private static JSplitPane vizAndControls;
private static JSplitPane vizAndInfo;
// Variables for the info panel
private JPanel infoPanel;
private StaticLayout infoLayout;
private JScrollPane infoScrollPane;
private JTextArea infoTextArea;
private DirectedSparseMultigraph infoGraph;
private VisualizationViewer infovv;
// Variables for the tree panel
private JScrollBar explScrollBar;
private JTree tree;
// Variables for control panel
private JButton mergeVerticesButton;
private JButton expandVerticesButton;
private JButton mergeEdgesButton;
private JButton expandEdgesButton;
private JButton resetButton;
private JButton captureButton;
private JCheckBox vertLabelCheckBox;
private JCheckBox edgeLabelCheckBox;
private JCheckBox showExploredCheckBox;
private JComboBox vertLabelPosComboBox;
private JComboBox layoutTypeComboBox;
private JLabel vertLabelPos;
private JPanel labelsPanel;
private JPanel layoutTypePanel;
private JPanel mergePanel;
private JPanel capturePanel;
private JButton animationButton;
private JPanel animationPanel;
private JSlider animationSlider;
private JCheckBox animationCheckBox;
private JToggleButton animationToggleButton;
// Variables for animations
protected Boolean showAnimation_;
protected Thread animationThread_;
protected int animationSleepTime_;
// End of variables declaration
/**
* The PanelGraphVisualisation constructor. This will initialise the panel and also the visualisation.
*/
public PanelJUNGVisualisation() {
jView_ = JUNGHelper.getJUNGViewInstance();
g = new DirectedSparseMultigraph();
layout = new FRLayout2(g);
vv = new VisualizationViewer(layout);
vv.setBackground(Color.white);
//TODO Fix the application-crashing problem when zooming out too far
//TODO Reset the view window to center on the model's starting node when generating new tests
//TODO find a fix for the merging of edges
//Setup the ability to compress multiple edges into one
/*final PredicatedParallelEdgeIndexFunction eif =
PredicatedParallelEdgeIndexFunction.getInstance();
exclusions = new HashSet();
eif.setPredicate(new Predicate() {
public boolean evaluate(Object e) {
return exclusions.contains(e);
}});
vv.getRenderContext().setParallelEdgeIndexFunction(eif);
*/
//A GraphCollapser to handle merging of vertices.
collapser = new GraphCollapser(jView_.getGraph());
// Initialise the animation switch
showAnimation_ = false;
// Create the custom mouse plugins to control the visualisation with the mouse
PluggableGraphMouse gm = new PluggableGraphMouse();
gm.add(new TranslatingGraphMousePlugin(MouseEvent.BUTTON3_MASK));
gm.add(new PickingGraphMousePlugin());
gm.add(new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, 0.9f, 1.1f));
vv.setGraphMouse(gm);
vv.addMouseListener(this);
// translate the layout panel down and across so that it is not hard up
// against the side of the splitPane box.
MutableTransformer modelTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(
Layer.LAYOUT);
modelTransformer.translate(25, 25);
// setup the transformers for the visualisation
e_eft = new EdgeFontTransformer();
e_elt = new EdgeLabelTransformer(vv);
e_ept = new EdgePaintTransformer(new Color(40, 40, 40), Color.black, vv);
e_est = new EdgeStrokeTransformer();
e_edp = new EdgeDisplayPredicate(false);
v_vft = new VertexFontTransformer();
v_vlt = new VertexLabelTransformer();
v_vgr = new VertexGradientRenderer(Color.white, vv.getPickedVertexState(), true);
v_vst = new VertexStrokeTransformer(g, vv.getPickedVertexState());
v_vsht = new VertexShapeTransformer();
v_vept = new VertexEdgePaintTransformer(vv.getPickedVertexState(), jView_.getVertices());
v_vdp = new VertexDisplayPredicate(false);
// Apply the transformers
vv.getRenderContext().setEdgeFontTransformer(e_eft);
vv.getRenderContext().setEdgeLabelTransformer(e_elt);
vv.getRenderContext().setEdgeDrawPaintTransformer(e_ept);
vv.getRenderContext().setEdgeStrokeTransformer(e_est);
vv.getRenderContext().setArrowDrawPaintTransformer(e_ept);
vv.getRenderContext().setArrowFillPaintTransformer(e_ept);
vv.getRenderContext().setEdgeIncludePredicate(e_edp);
vv.getRenderContext().setVertexFontTransformer(v_vft);
vv.getRenderContext().setVertexLabelTransformer(v_vlt);
vv.getRenderContext().setVertexStrokeTransformer(v_vst);
vv.getRenderContext().setVertexShapeTransformer(v_vsht);
vv.getRenderContext().setVertexDrawPaintTransformer(v_vept);
vv.getRenderer().setVertexRenderer(v_vgr);
vv.getRenderContext().setVertexIncludePredicate(v_vdp);
//Set the curvature in the edges
AbstractEdgeShapeTransformer aesf = (AbstractEdgeShapeTransformer) vv
.getRenderContext().getEdgeShapeTransformer();
aesf.setControlOffsetIncrement(30);
//Set the new size of the visualisation to allow for resizing of the panel
vv.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent arg0) {
super.componentResized(arg0);
layout.setSize(arg0.getComponent().getSize());
vv.setSize(arg0.getComponent().getSize());
}
});
// provide a scrollpane for the visualisation
GraphZoomScrollPane vvPanel = new GraphZoomScrollPane(vv);
//Setup the Splitpanes
vizAndInfo = new JSplitPane(JSplitPane.VERTICAL_SPLIT, vvPanel, getInfoPanel());
vizAndInfo.setResizeWeight(1.0);
vizAndInfo.setOneTouchExpandable(true);
vizAndControls = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, vizAndInfo, getControlPanel());
getControlPanel().setMinimumSize(new Dimension(0, 0));
getControlPanel().setPreferredSize(new Dimension(0, 0));
getControlPanel().setMaximumSize(new Dimension(0, 0));
vizAndControls.setResizeWeight(1.0);
vizAndControls.setOneTouchExpandable(true);
vizAndControls.setDividerLocation(1.0);
treeAndViz = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, getTreeControls(), vizAndControls);
treeAndViz.setResizeWeight(0.0);
treeAndViz.setOneTouchExpandable(true);
setLayout(new BorderLayout());
add(treeAndViz, BorderLayout.CENTER);
}
/**
* Return the JUNGHelper instance
*
* @return the JUNGHelper instance
*/
public JUNGHelper getJUNGHelper() {
return jView_;
}
/**
* This will show the fully explored graph
*
* @param graph
* The GraphListener which contains the explored graph.
*/
public void showEmptyExploredGraph(GraphListener graph) {
jView_.preExploredGraph(graph);
}
/**
* This is run to reset the tree view and the panel when a new graph is selected.
*/
public void resetRunTimeInformation() {
jView_.resetRunTimeInformation();
}
/**
* This should be called by the top-level program whenever the model changes.
*/
public void newModel() {
resetRunTimeInformation();
}
/**
* This method gives the controls access to the visualisation viewer.
*
* @return The visualisation viewer.
*/
public VisualizationViewer getVisualisationViewer() {
return vv;
}
/**
* This method is used to update the panel. This is used to start the animation off.
*
* @param showAnimation
*/
public void updateGUI(boolean showAnimation) {
//System.out.println("Doing update GUI");
// Reset the info panel
updateInfoPanel("Nothing Selected");
// Setup the tree
tree.setModel(new DefaultTreeModel(jView_.getRootTreeNode()));
// Setup the test sequence scroll bar
explScrollBar.setMaximum(tree.getRowCount());
explScrollBar.setMinimum(0);
explScrollBar.setVisibleAmount(1);
layout.setSize(new Dimension(vizAndInfo.getWidth() - 75, vizAndInfo.getHeight() - infoPanel.getHeight() - 75));
vv.getModel().setGraphLayout(layout,
new Dimension(vizAndInfo.getWidth() - 20, vizAndInfo.getHeight() - infoPanel.getHeight() - 32));
g = new DirectedSparseMultigraph();
// Start the animation
if (showAnimation && animationCheckBox.isSelected()) {
showAnimation_ = true;
} else {
showAnimation_ = false;
}
// Make sure the pause button is unselected
animationToggleButton.setSelected(false);
// Start the animation off
animationThread_ = new AnimateThread(tree);
animationThread_.start();
}
/**
* This will update the info panel based on what object is passed to it. The info panel is used to show information
* about the visualisation.
*
* @param obj
* The Object to show information about.
*/
@SuppressWarnings("unchecked")
public void updateInfoPanel(Object obj) {
Collection it = infoGraph.getVertices();
ArrayList vert = new ArrayList();
// make sure that the object is not null
if (null == obj) {
return;
}
for (Object v : it) {
vert.add(v);
}
//remove all the vertices. This will remove all edges by default as well.
for (Object vx : vert) {
infoGraph.removeVertex(vx);
}
//Remove all the text from the text area.
infoTextArea.setText("");
if (obj instanceof VertexInfo) {
infoGraph.addVertex((VertexInfo) obj);
infoLayout.setLocation((VertexInfo) obj, new Point(30, 50));
infoTextArea.append("State Selected: " + ((VertexInfo) obj).getName() + "\n");
infoTextArea.append("--------------------------------\n");
infoTextArea.append("Transition Pairs: "
+ (((VertexInfo) obj).getIncomingEdges() * ((VertexInfo) obj).getOutgoingEdges()) + "\n");
} else if (obj instanceof Graph) {
StringBuffer str = new StringBuffer();
for (Object i : ((Graph) obj).getVertices()) {
if (i instanceof VertexInfo) {
VertexInfo v = (VertexInfo) i;
if (str.length() % 25 > 20) {
str.append("\n");
}
str.append(v.getName() + ", ");
}
}
if (str.length() > 1) {
str.deleteCharAt(str.length() - 1);
str.deleteCharAt(str.length() - 1);
}
infoGraph.addVertex(" - Merged States");
infoLayout.setLocation(" - Merged States", new Point(30, 50));
infoTextArea.append("Merged states are:\n" + str.toString());
infoTextArea.setCaretPosition(0);
} else if (obj instanceof EdgeInfo) {
String srcVertex = "Source State: " + ((EdgeInfo) obj).getSrcVertex().getName();
String destVertex = "Destination State: " + ((EdgeInfo) obj).getDestVertex().getName();
String edge = " Action taken: "
+ ((EdgeInfo) obj).getAction();
infoGraph.addVertex(destVertex);
if (!((EdgeInfo) obj).getSrcVertex().getName().equals(((EdgeInfo) obj).getDestVertex().getName())) {
infoGraph.addVertex(srcVertex);
infoLayout.setLocation(srcVertex, new Point(30, 20));
infoLayout.setLocation(destVertex, new Point(30, 85));
infoGraph.addEdge((EdgeInfo) obj, srcVertex, destVertex);
} else {
infoGraph.addEdge((EdgeInfo) obj, destVertex, destVertex);
infoLayout.setLocation(destVertex, new Point(30, 65));
}
infoTextArea.append("Action selected: " + ((EdgeInfo) obj).getAction() + "\n");
if (null != ((EdgeInfo) obj).getFailedMsg()) {
infoTextArea.append("Failure occured: " + ((EdgeInfo) obj).getFailedMsg() + "\n");
}
if (((EdgeInfo) obj).getSequences_().size() == 0) {
infoTextArea.append("--------------------------------\nnot tested:\n");
} else {
infoTextArea.append("--------------------------------\nused in:\n");
Iterator itr = ((EdgeInfo) obj).getSequences_().keySet().iterator();
while (itr.hasNext()) {
String seq = itr.next();
infoTextArea.append(seq + " (taken " + ((EdgeInfo) obj).getSequences_().get(seq) + " times)\n");
}
}
infoTextArea.setCaretPosition(0);
} else {
infoTextArea.append(obj.toString() + "\n");
}
infovv.repaint();
}
/**
* The override required by implementing the ActionPerformed class.
*/
@SuppressWarnings({ "unchecked", "deprecation" })
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
// The show vertex labels checkbox
if (actionCommand.equals("vertLabelCheckBox")) {
if (vertLabelCheckBox.isSelected()) {
vertLabelCheckBox.setSelected(false);
} else {
vertLabelCheckBox.setSelected(true);
}
v_vlt.setShowLabels(vertLabelCheckBox.isSelected());
// The show vertex labels checkbox
} else if (actionCommand.equals("edgeLabelCheckBox")) {
if (edgeLabelCheckBox.isSelected()) {
edgeLabelCheckBox.setSelected(false);
} else {
edgeLabelCheckBox.setSelected(true);
}
e_elt.showEdgeLabels(edgeLabelCheckBox.isSelected());
// The show explored label checkbox
} else if (actionCommand.equals("showExploredCheckBox")) {
if (showExploredCheckBox.isSelected()) {
showExploredCheckBox.setSelected(false);
} else {
showExploredCheckBox.setSelected(true);
}
v_vdp.showExplored(!showExploredCheckBox.isSelected());
e_edp.showExplored(!showExploredCheckBox.isSelected());
// Merge vertices button
} else if (actionCommand.equals("mergeVerticesButton")) {
Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
if (picked.size() > 1) {
Graph inGraph = layout.getGraph();
Graph clusterGraph = collapser.getClusterGraph(inGraph, picked);
Graph graph = collapser.collapse(inGraph, clusterGraph);
double sumx = 0;
double sumy = 0;
for (Object v : picked) {
Point2D p = (Point2D) layout.transform(v);
sumx += p.getX();
sumy += p.getY();
}
//Position the new merged vertex in the center where the other vertices used to be.
Point2D cp = new Point2D.Double(sumx / picked.size(), sumy / picked.size());
vv.getRenderContext().getParallelEdgeIndexFunction().reset();
layout.setGraph(graph);
layout.setLocation(clusterGraph, cp);
g = graph;
animateLayoutChanges();
}
// Expand vertices button
} else if (actionCommand.equals("expandVerticesButton")) {
Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
for (Object v : picked) {
if (v instanceof Graph) {
Graph graph = collapser.expand(layout.getGraph(), (Graph) v);
vv.getRenderContext().getParallelEdgeIndexFunction().reset();
layout.setGraph(graph);
g = graph;
animateLayoutChanges();
}
}
// Merge Edges button
} else if (actionCommand.equals("mergeEdgesButton")) {
Collection picked = vv.getPickedVertexState().getPicked();
if (picked.size() == 2) {
Pair pair = new Pair(picked);
Graph graph = layout.getGraph();
Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst()));
edges.retainAll(graph.getIncidentEdges(pair.getSecond()));
exclusions.addAll(edges);
for (Object o : exclusions) {
EdgeInfo edge = (EdgeInfo) o;
System.out.println("edge:" + edge.getAction());
}
}
if (picked.size() == 1) {
Graph graph = layout.getGraph();
for (Object o : picked) {
if (o instanceof VertexInfo) {
VertexInfo v = (VertexInfo) o;
Collection ed = graph.getInEdges(v);
for (Object oe : ed) {
if (oe instanceof EdgeInfo) {
EdgeInfo edg = (EdgeInfo) oe;
if (edg.getDestVertex().equals(edg.getSrcVertex())) {
exclusions.add(edg);
}
}
}
}
}
for (Object o : exclusions) {
EdgeInfo edge = (EdgeInfo) o;
System.out.println("edge:" + edge.getAction());
}
}
// Expand edges button
} else if (actionCommand.equals("expandEdgesButton")) {
Collection picked = vv.getPickedVertexState().getPicked();
if (picked.size() == 2) {
Pair pair = new Pair(picked);
Graph graph = layout.getGraph();
Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst()));
edges.retainAll(graph.getIncidentEdges(pair.getSecond()));
exclusions.removeAll(edges);
} else if (picked.size() == 1) {
Graph graph = layout.getGraph();
for (Object o : picked) {
if (o instanceof VertexInfo) {
VertexInfo v = (VertexInfo) o;
Collection ed = graph.getInEdges(v);
for (Object oe : ed) {
if (oe instanceof EdgeInfo) {
EdgeInfo edg = (EdgeInfo) oe;
if (edg.getDestVertex().equals(edg.getSrcVertex())) {
exclusions.remove(edg);
}
}
}
}
}
}
// The reset button
} else if (actionCommand.equals("resetButton")) {
Collection vertices = layout.getGraph().getVertices();
for (Object v : vertices) {
if (v instanceof Graph) {
Graph graph = collapser.expand(layout.getGraph(), (Graph) v);
vv.getRenderContext().getParallelEdgeIndexFunction().reset();
layout.setGraph(graph);
g = graph;
animateLayoutChanges();
}
}
//exclusions.clear();
// The capture button
} else if (actionCommand.equals("captureButton")) {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
chooser.addChoosableFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
if (f.getName().endsWith(".png")) {
return true;
} else {
return false;
}
}
@Override
public String getDescription() {
return "*.png";
}
});
int returnVal = chooser.showSaveDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
if (!file.getName().toLowerCase().endsWith(".png")) {
// Add .png extension
file = new File(file.getAbsolutePath() + ".png");
}
System.out.println("Saving screenshot to file " + file);
int width = vv.getWidth();
int height = vv.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
vv.paint(g2);
g2.dispose();
try {
ImageIO.write(image, "png", file);
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
} else {
System.out.println("User pressed cancel, or something went wrong");
}
// The animation button used to stop the animation
} else if (actionCommand.equals("animationCheckBox")) {
if (animationCheckBox.isSelected()) {
animationCheckBox.setSelected(false);
showAnimation_ = false;
} else {
animationCheckBox.setSelected(true);
showAnimation_ = true;
}
} else if (actionCommand.equals("animationButton")) {
showAnimation_ = false;
// The pause animation toggle button
} else if (actionCommand.equals("animationToggleButton")) {
System.out.println(animationSlider.getValue());
if (animationToggleButton.isSelected()) {
animationToggleButton.setSelected(false);
animationThread_.resume();
} else {
animationToggleButton.setSelected(true);
animationThread_.suspend();
}
}
vv.repaint();
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
/**
* This is used to listen to click events within the visualisation viewer.
*/
@Override
public void mousePressed(MouseEvent e) {
GraphElementAccessor pickSupport = vv.getPickSupport();
PickedState pickedVertexState = vv.getPickedVertexState();
PickedState pickedEdgeState = vv.getPickedEdgeState();
if (pickSupport != null && e.getButton() == MouseEvent.BUTTON1) {
Layout layout = vv.getGraphLayout();
// p is the screen point for the mouse event
Point2D p = e.getPoint();
if (pickSupport.getVertex(layout, p.getX(), p.getY()) != null) {
Object vertex = pickSupport.getVertex(layout, p.getX(), p.getY());
pickedEdgeState.clear();
updateInfoPanel(vertex);
} else if (pickSupport.getEdge(layout, p.getX(), p.getY()) != null) {
EdgeInfo edge = (EdgeInfo) pickSupport.getEdge(layout, p.getX(), p.getY());
pickedVertexState.clear();
pickedVertexState.pick(edge.getSrcVertex(), true);
pickedVertexState.pick(edge.getDestVertex(), true);
updateInfoPanel(edge);
} else {
updateInfoPanel("Nothing Selected");
}
// Stop any animation that is running if the toggle button isn't
// selected.
showAnimation_ = animationToggleButton.isSelected();
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
/**
* This creates the controls panel
*
* @return The JPanel with all the controls on it.
*/
private JPanel getControlPanel() {
JPanel panel = new JPanel();
labelsPanel = new JPanel();
vertLabelCheckBox = new JCheckBox();
edgeLabelCheckBox = new JCheckBox();
showExploredCheckBox = new JCheckBox();
vertLabelPos = new JLabel();
vertLabelPosComboBox = new JComboBox();
layoutTypePanel = new JPanel();
layoutTypeComboBox = new JComboBox();
mergePanel = new JPanel();
mergeVerticesButton = new JButton();
expandVerticesButton = new JButton();
mergeEdgesButton = new JButton();
expandEdgesButton = new JButton();
resetButton = new JButton();
capturePanel = new JPanel();
captureButton = new JButton();
animationPanel = new JPanel();
animationSlider = new JSlider();
animationButton = new JButton();
animationCheckBox = new JCheckBox();
animationToggleButton = new JToggleButton();
labelsPanel.setBorder(BorderFactory.createTitledBorder("Labels"));
vertLabelCheckBox.setText("Show vertex labels");
vertLabelCheckBox.addActionListener(this);
vertLabelCheckBox.setActionCommand("vertLabelCheckBox");
vertLabelCheckBox.setSelected(true);
edgeLabelCheckBox.setText("Show edge labels");
edgeLabelCheckBox.addActionListener(this);
edgeLabelCheckBox.setActionCommand("edgeLabelCheckBox");
showExploredCheckBox.setText("Show unexplored states/actions");
showExploredCheckBox.addActionListener(this);
showExploredCheckBox.setActionCommand("showExploredCheckBox");
showExploredCheckBox.setSelected(true);
vertLabelPos.setText("Label position:");
vertLabelPosComboBox.setName("vertLabelPosComboBox");
vertLabelPosComboBox.setModel(new DefaultComboBoxModel(new Renderer.VertexLabel.Position[] {
Renderer.VertexLabel.Position.AUTO, Renderer.VertexLabel.Position.CNTR,
Renderer.VertexLabel.Position.N, Renderer.VertexLabel.Position.NE,
Renderer.VertexLabel.Position.E, Renderer.VertexLabel.Position.SE,
Renderer.VertexLabel.Position.S, Renderer.VertexLabel.Position.SW,
Renderer.VertexLabel.Position.W, Renderer.VertexLabel.Position.NW }));
vertLabelPosComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
Renderer.VertexLabel.Position position = (Renderer.VertexLabel.Position) e.getItem();
vv.getRenderer().getVertexLabelRenderer().setPosition(position);
vv.repaint();
}
});
vertLabelPosComboBox.setSelectedItem(Renderer.VertexLabel.Position.AUTO);
GroupLayout jPanel1Layout = new GroupLayout(labelsPanel);
labelsPanel.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(jPanel1Layout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout
.createSequentialGroup()
.addGroup(jPanel1Layout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(vertLabelCheckBox)
.addGroup(jPanel1Layout
.createSequentialGroup()
.addComponent(vertLabelPos)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(vertLabelPosComboBox, 0, 127,
Short.MAX_VALUE)).addComponent(
edgeLabelCheckBox).addComponent(
showExploredCheckBox)).addContainerGap()));
jPanel1Layout.setVerticalGroup(jPanel1Layout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout
.createSequentialGroup()
.addComponent(vertLabelCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(vertLabelPos)
.addComponent(vertLabelPosComboBox,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout
.createSequentialGroup()
.addGap(25, 25, 25)
.addGroup(jPanel1Layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(edgeLabelCheckBox))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 2,
Short.MAX_VALUE).addComponent(showExploredCheckBox)));
layoutTypePanel.setBorder(BorderFactory.createTitledBorder("Layout Type"));
layoutTypeComboBox.setName("layoutTypeComboBox");
layoutTypeComboBox.setModel(new DefaultComboBoxModel(new JUNGHelper.LayoutType[] { JUNGHelper.LayoutType.FR,
JUNGHelper.LayoutType.CIRCLE, JUNGHelper.LayoutType.ISOM, JUNGHelper.LayoutType.KK,
JUNGHelper.LayoutType.SPRING }));
layoutTypeComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
try {
if (e.getStateChange() == ItemEvent.SELECTED) {
Layout l = jView_.getLayout((JUNGHelper.LayoutType) e.getItem());
l.setGraph(g);
l.setInitializer(vv.getGraphLayout());
l.setSize(vv.getSize());
LayoutTransition lt = new LayoutTransition(vv, vv
.getGraphLayout(), l);
Animator animator = new Animator(lt);
animator.start();
layout = l;
vv.repaint();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
layoutTypeComboBox.setSelectedItem(JUNGHelper.LayoutType.FR);
GroupLayout layoutTypePanelLayout = new GroupLayout(layoutTypePanel);
layoutTypePanel.setLayout(layoutTypePanelLayout);
layoutTypePanelLayout.setHorizontalGroup(layoutTypePanelLayout.createParallelGroup(
GroupLayout.Alignment.LEADING).addComponent(layoutTypeComboBox, 0, 178, Short.MAX_VALUE));
layoutTypePanelLayout.setVerticalGroup(layoutTypePanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layoutTypePanelLayout.createSequentialGroup().addComponent(layoutTypeComboBox,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(
GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
mergePanel.setBorder(BorderFactory.createTitledBorder("Merge"));
mergeVerticesButton.setText("Merge states");
mergeVerticesButton.addActionListener(this);
mergeVerticesButton.setActionCommand("mergeVerticesButton");
expandVerticesButton.setText("Expand states");
expandVerticesButton.addActionListener(this);
expandVerticesButton.setActionCommand("expandVerticesButton");
mergeEdgesButton.setText("Merge transitions");
mergeEdgesButton.addActionListener(this);
mergeEdgesButton.setActionCommand("mergeEdgesButton");
expandEdgesButton.setText("Expand transitions");
expandEdgesButton.addActionListener(this);
expandEdgesButton.setActionCommand("expandEdgesButton");
resetButton.setText("Reset");
resetButton.addActionListener(this);
resetButton.setActionCommand("resetButton");
GroupLayout jPanel3Layout = new GroupLayout(mergePanel);
mergePanel.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(
expandVerticesButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE).addComponent(
mergeVerticesButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)
//TODO add these back when the merge edges has been fixed.
//.addComponent(mergeEdgesButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)
//.addComponent(expandEdgesButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)
.addComponent(resetButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE));
jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
jPanel3Layout.createSequentialGroup().addComponent(mergeVerticesButton).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(expandVerticesButton)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
// TODO add these back when the merge edges has been fixed.
//.addComponent(mergeEdgesButton)
//.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 7, Short.MAX_VALUE)
//.addComponent(expandEdgesButton)
//.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resetButton).addContainerGap()));
animationPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Animation"));
//Create the label table
Hashtable labelTable = new Hashtable();
labelTable.put(new Integer(100), new JLabel("Fast"));
labelTable.put(new Integer(1000), new JLabel("Normal"));
labelTable.put(new Integer(3000), new JLabel("Slow"));
animationSlider.setLabelTable(labelTable);
animationSlider.setPaintLabels(true);
animationSlider.setMajorTickSpacing(500);
animationSlider.setMaximum(3000);
animationSlider.setMinimum(100);
animationSlider.setValue(300);
animationSlider.setPaintTicks(true);
animationSlider.setToolTipText("Use this slider to control the speed of the animation");
animationSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
JSlider slider = (JSlider) evt.getSource();
if (!slider.getValueIsAdjusting()) {
animationSleepTime_ = slider.getValue();
}
}
});
animationSleepTime_ = animationSlider.getValue();
animationButton.setText("Stop");
animationButton.addActionListener(this);
animationButton.setActionCommand("animationButton");
animationCheckBox.setText("Show animation");
animationCheckBox.setSelected(true);
animationCheckBox.addActionListener(this);
animationCheckBox.setActionCommand("animationCheckBox");
animationToggleButton.setText("Pause");
animationToggleButton.addActionListener(this);
animationToggleButton.setActionCommand("animationToggleButton");
javax.swing.GroupLayout animationPanelLayout = new javax.swing.GroupLayout(animationPanel);
animationPanel.setLayout(animationPanelLayout);
animationPanelLayout
.setHorizontalGroup(animationPanelLayout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(animationPanelLayout
.createSequentialGroup()
.addContainerGap()
.addGroup(animationPanelLayout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(animationSlider,
javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE,
157, Short.MAX_VALUE)
.addGroup(animationPanelLayout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
false)
.addGroup(animationPanelLayout
.createSequentialGroup()
.addComponent(animationToggleButton,
GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED)
.addComponent(animationButton,
GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE))
.addComponent(animationCheckBox,
javax.swing.GroupLayout.Alignment.LEADING)))
.addContainerGap()));
animationPanelLayout.setVerticalGroup(animationPanelLayout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING).addGroup(
animationPanelLayout.createSequentialGroup().addComponent(animationCheckBox).addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(
animationPanelLayout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
animationToggleButton).addComponent(animationButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(animationSlider, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(21,
Short.MAX_VALUE)));
capturePanel.setBorder(BorderFactory.createTitledBorder("Capture"));
captureButton.setText("Save as image");
captureButton.addActionListener(this);
captureButton.setActionCommand("captureButton");
GroupLayout jPanel4Layout = new GroupLayout(capturePanel);
capturePanel.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(
captureButton, GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE));
jPanel4Layout.setVerticalGroup(jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
jPanel4Layout.createSequentialGroup().addComponent(captureButton).addContainerGap(
GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
GroupLayout layout = new GroupLayout(panel);
panel.setLayout(layout);
layout.setHorizontalGroup(layout
.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(layoutTypePanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addComponent(labelsPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(mergePanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(capturePanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(animationPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE));
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
layout.createSequentialGroup().addComponent(labelsPanel, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(layoutTypePanel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(mergePanel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(capturePanel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE).addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(
animationPanel, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(104, Short.MAX_VALUE)));
return panel;
}
/**
* This method will return the tree panel for the left side of the visualisation.
*
* @return JPanel The panel containing the tree and associated controls.
*/
private JPanel getTreeControls() {
JPanel panel = new JPanel();
JButton expandButton = new JButton();
JButton collapseButton = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JPanel jPanel2 = new JPanel();
explScrollBar = new JScrollBar();
// setup the expand button
expandButton.setText("Expand All");
expandButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
}
});
// setup the collapse button
collapseButton.setText("Collapse All");
collapseButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
for (int i = 1; i < tree.getRowCount(); i++) {
tree.collapseRow(i);
}
}
});
// setup the scrollbar so the user can quickly scroll through the test sequences
explScrollBar.setOrientation(JScrollBar.HORIZONTAL);
explScrollBar.setToolTipText("Use the slider to scroll through test sequences");
explScrollBar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent evt) {
explScrollBar.setMaximum(tree.getRowCount());
explScrollBar.setMinimum(0);
explScrollBar.setVisibleAmount(1);
tree.setSelectionPath(tree.getPathForRow(explScrollBar.getValue()));
tree.scrollPathToVisible(tree.getSelectionPath());
}
});
// setup the tree
tree = new JTree(jView_.getRootTreeNode());
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setCellRenderer(new CustomTreeCellRenderer());
tree.addTreeSelectionListener(new TreeSelectionListener() {
@SuppressWarnings("unchecked")
public void valueChanged(TreeSelectionEvent e) {
//if(!showAnimation_){
explScrollBar.setMaximum(tree.getRowCount());
explScrollBar.setValue(tree.getMinSelectionRow());
//}
ColorTreeNode node = (ColorTreeNode) tree.getLastSelectedPathComponent();
PickedState pickedVertexState = vv.getPickedVertexState();
PickedState pickedEdgeState = vv.getPickedEdgeState();
if (node == null)
return;
if (node.isLeaf() && !node.isRoot()) {
Collection checkEdges = g.getEdges();
for (Object ed : checkEdges) {
if (ed instanceof EdgeInfo) {
EdgeInfo ei = (EdgeInfo) ed;
ei.setIsDisplayed(false);
ei.getSrcVertex().setIsDisplayed(false);
ei.getDestVertex().setIsDisplayed(false);
ei.setIsCurrSeq(false);
ei.getSrcVertex().setIsCurrSeq(false);
ei.getDestVertex().setIsCurrSeq(false);
}
}
ColorTreeNode tempNode = null;
Enumeration enumt = node.getParent().children();
while (enumt.hasMoreElements()) {
tempNode = (ColorTreeNode) enumt.nextElement();
tempNode.setInCurrentSeq(true);
Transition nodeInfo = (Transition) tempNode.getUserObject();
EdgeInfo edgeInfo = jView_.getEdge(nodeInfo);
edgeInfo.setIsCurrSeq(true);
edgeInfo.getSrcVertex().setIsCurrSeq(true);
edgeInfo.getDestVertex().setIsCurrSeq(true);
if (tempNode.getUserObject() instanceof Transition
&& node.getParent().getIndex(tempNode) <= node.getParent().getIndex(node)) {
jView_.setEdgeDisplayed(nodeInfo, true);
pickedEdgeState.clear();
pickedVertexState.clear();
pickedEdgeState.pick(edgeInfo, true);
pickedVertexState.pick(edgeInfo.getDestVertex(), true);
pickedVertexState.pick(edgeInfo.getSrcVertex(), true);
updateInfoPanel(edgeInfo);
}
}
tree.treeDidChange();
vv.repaint();
} else if (node.isRoot()) {
Collection checkEdges = g.getEdges();
for (Object ed : checkEdges) {
if (ed instanceof EdgeInfo) {
EdgeInfo ei = (EdgeInfo) ed;
if (ei.getIsVisited()) {
ei.setIsDisplayed(true);
ei.getSrcVertex().setIsDisplayed(true);
ei.getDestVertex().setIsDisplayed(true);
ei.setIsCurrSeq(false);
ei.getSrcVertex().setIsCurrSeq(false);
ei.getDestVertex().setIsCurrSeq(false);
}
}
}
pickedEdgeState.clear();
pickedVertexState.clear();
updateInfoPanel("Nothing Selected");
tree.treeDidChange();
vv.repaint();
} else {
Collection checkEdges = g.getEdges();
for (Object ed : checkEdges) {
if (ed instanceof EdgeInfo) {
EdgeInfo ei = (EdgeInfo) ed;
ei.setIsDisplayed(false);
ei.getSrcVertex().setIsDisplayed(false);
ei.getDestVertex().setIsDisplayed(false);
ei.setIsCurrSeq(false);
ei.getSrcVertex().setIsCurrSeq(false);
ei.getDestVertex().setIsCurrSeq(false);
}
}
DefaultMutableTreeNode tempNode = null;
Enumeration enumt = node.children();
while (enumt.hasMoreElements()) {
tempNode = (DefaultMutableTreeNode) enumt.nextElement();
if (tempNode.getUserObject() instanceof Transition) {
Transition nodeInfo = (Transition) tempNode.getUserObject();
jView_.setEdgeDisplayed(nodeInfo, true);
}
}
pickedEdgeState.clear();
pickedVertexState.clear();
updateInfoPanel("Nothing Selected");
tree.treeDidChange();
vv.repaint();
}
}
});
tree.addTreeExpansionListener(new TreeExpansionListener() {
@Override
public void treeCollapsed(TreeExpansionEvent arg0) {
explScrollBar.setMaximum(tree.getRowCount());
explScrollBar.setMinimum(0);
explScrollBar.setValue(tree.getMinSelectionRow());
}
@Override
public void treeExpanded(TreeExpansionEvent arg0) {
explScrollBar.setMaximum(tree.getRowCount());
explScrollBar.setMinimum(0);
explScrollBar.setValue(tree.getMinSelectionRow());
}
});
// add the tree into a scrollpane.
jScrollPane1.setViewportView(tree);
jPanel2.setBorder(BorderFactory.createTitledBorder("Test Sequences"));
GroupLayout jPanel2Layout = new GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
jPanel2Layout.createSequentialGroup().addContainerGap().addComponent(explScrollBar,
GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE).addContainerGap()));
jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
jPanel2Layout.createSequentialGroup().addComponent(explScrollBar, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addContainerGap(
GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
GroupLayout layout = new GroupLayout(panel);
panel.setLayout(layout);
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup().addComponent(expandButton, GroupLayout.DEFAULT_SIZE, 94,
Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(collapseButton, GroupLayout.DEFAULT_SIZE, 98, Short.MAX_VALUE))
.addComponent(jPanel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE));
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
layout.createSequentialGroup().addGroup(
layout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(
collapseButton).addComponent(expandButton)).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(jPanel2,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE).addPreferredGap(
LayoutStyle.ComponentPlacement.RELATED).addComponent(jScrollPane1,
GroupLayout.DEFAULT_SIZE, 524, Short.MAX_VALUE)));
return panel;
}
/**
* Create the Info Panel to display information about various parts of the visualisation
*
* @return The panel with the various controls on it.
*/
private JPanel getInfoPanel() {
infoGraph = new DirectedSparseMultigraph();
infoLayout = new StaticLayout(infoGraph);
infovv = new VisualizationViewer(infoLayout, new Dimension(200, 100));
infovv.getRenderContext().setVertexLabelTransformer(new InfoLabelTransformer());
infovv.getRenderContext().setEdgeLabelTransformer(new InfoLabelTransformer());
infovv.getRenderContext().getEdgeLabelRenderer().setRotateEdgeLabels(false);
infovv.getRenderContext().setEdgeDrawPaintTransformer(e_ept);
infovv.getRenderContext().setArrowDrawPaintTransformer(e_ept);
infovv.getRenderContext().setArrowFillPaintTransformer(e_ept);
infovv.getRenderContext().setEdgeLabelClosenessTransformer(
new ConstantDirectionalEdgeValueTransformer(.2, .2));
infovv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.E);
infovv.getRenderer().setVertexRenderer(
new GradientVertexRenderer(Color.white, Color.green, Color.white, Color.green,
vv.getPickedVertexState(), true));
infoPanel = new JPanel();
infoPanel.setMinimumSize(new Dimension(300, 100));
infoScrollPane = new javax.swing.JScrollPane();
infoTextArea = new javax.swing.JTextArea();
infoTextArea.setEditable(false);
infoTextArea.setLineWrap(true);
infoTextArea.append("Nothing Selected");
javax.swing.GroupLayout vvPanelLayout = new javax.swing.GroupLayout(infovv);
infovv.setLayout(vvPanelLayout);
vvPanelLayout.setHorizontalGroup(vvPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 201, Short.MAX_VALUE));
vvPanelLayout.setVerticalGroup(vvPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 120, Short.MAX_VALUE));
infoTextArea.setColumns(20);
infoTextArea.setRows(4);
infoScrollPane.setViewportView(infoTextArea);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(infoPanel);
infoPanel.setLayout(layout);
layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
layout.createSequentialGroup().addComponent(infovv, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(infoScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 362,
Short.MAX_VALUE)));
layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(
infovv, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE).addComponent(infoScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 110,
Short.MAX_VALUE));
return infoPanel;
}
/**
* This method will animate the transition between two layouts.
*
*/
private void animateLayoutChanges() {
if (!(layout instanceof CircleLayout)) {
Relaxer relaxer = new VisRunner((IterativeContext) layout);
relaxer.stop();
relaxer.prerelax();
StaticLayout staticLayout = new StaticLayout(g, layout);
LayoutTransition lt = new LayoutTransition(vv, vv.getGraphLayout(),
staticLayout);
Animator animator = new Animator(lt);
animator.start();
}
}
/**
* This inner class is used to control the animation of new states being added to the visualisation.
*
* @author Jerramy Winchester
*
*/
public class AnimateThread extends Thread {
DefaultMutableTreeNode rootNode_;
/** The thread constructor */
public AnimateThread(JTree tree_) {
rootNode_ = (DefaultMutableTreeNode) tree_.getModel().getRoot();
}
@SuppressWarnings("deprecation")
public void run() {
// Expand out all the rows of the tree
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
Enumeration enumRoot = rootNode_.children();
try {
// Start the animation
while (showAnimation_ && enumRoot.hasMoreElements()) {
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) enumRoot.nextElement();
Enumeration enumChild = childNode.children();
while (showAnimation_ && enumChild.hasMoreElements()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumChild.nextElement();
if (node.isLeaf()) {
vv.getRenderContext().getPickedVertexState().clear();
vv.getRenderContext().getPickedEdgeState().clear();
// TODO this has some strange effects on the repaint
// of the tree and ModelJUnit. Fix this later.
//tree.scrollPathToVisible(new TreePath(node.getPath()));
//tree.setSelectionPath(new TreePath(node.getPath()));
Transition nodeInfo = (Transition) node.getUserObject();
EdgeInfo edge = jView_.getEdge(nodeInfo);
g.addVertex(edge.getSrcVertex());
g.addVertex(edge.getDestVertex());
g.addEdge(edge, edge.getSrcVertex(), edge.getDestVertex());
vv.getRenderContext().getPickedEdgeState().pick(edge, true);
vv.getRenderContext().getPickedVertexState().pick(edge.getDestVertex(), true);
layout.setGraph(g);
layout.initialize();
animateLayoutChanges();
}
if (animationToggleButton.isSelected()) {
suspend();
} else {
Thread.sleep(animationSleepTime_);
}
}
}
vv.getRenderContext().getPickedVertexState().clear();
vv.getRenderContext().getPickedEdgeState().clear();
// Collapse all the rows of the tree
for (int i = 1; i < tree.getRowCount(); i++) {
tree.collapseRow(i);
}
showAnimation_ = false;
tree.setSelectionPath(tree.getPathForRow(0));
g = jView_.getGraph();
layout.setGraph(g);
layout.initialize();
animateLayoutChanges();
} catch (Exception ex) {
//Ignore
}
}
}
}