/* This program 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 3 of
the License, or (at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.visualizer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import javassist.Modifier;
import javax.swing.AbstractListModel;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.opentripplanner.common.model.GenericLocation;
import org.opentripplanner.graph_builder.annotation.GraphBuilderAnnotation;
import org.opentripplanner.graph_builder.annotation.StopUnlinked;
import org.opentripplanner.routing.algorithm.GenericAStar;
import org.opentripplanner.routing.core.OptimizeType;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.StreetEdge;
import org.opentripplanner.routing.edgetype.StreetEdge;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.Vertex;
import org.opentripplanner.routing.impl.GenericAStarFactory;
import org.opentripplanner.routing.impl.LongDistancePathService;
import org.opentripplanner.routing.impl.ParetoPathService;
import org.opentripplanner.routing.impl.SPTVisitor;
import org.opentripplanner.routing.services.GraphService;
import org.opentripplanner.routing.services.PathService;
import org.opentripplanner.routing.spt.GraphPath;
import org.opentripplanner.routing.spt.MultiShortestPathTree;
import org.opentripplanner.routing.spt.ShortestPathTree;
import org.opentripplanner.routing.vertextype.IntersectionVertex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Exit on window close.
*
*/
class ExitListener extends WindowAdapter {
public void windowClosing(WindowEvent event) {
System.exit(0);
}
}
/**
* DisplayVertex holds a vertex, but has a toString value that's a little more useful.
*/
class DisplayVertex {
public Vertex vertex;
public DisplayVertex(Vertex v) {
vertex = v;
}
public String toString() {
String label = vertex.getLabel();
if (label.contains("osm node")) {
label = vertex.getName();
}
return label;
}
}
/**
* This is a ListModel that holds Edges. It gets its edges from a PatternBoard/PatternAlight, hence the iterable.
*/
class EdgeListModel extends AbstractListModel<Edge> {
private static final long serialVersionUID = 1L;
private ArrayList<Edge> edges;
EdgeListModel(Iterable<Edge> edges) {
this.edges = new ArrayList<Edge>();
for (Edge e : edges) {
this.edges.add(e);
}
}
public int getSize() {
return edges.size();
}
public Edge getElementAt(int index) {
return edges.get(index);
}
}
/**
* A list of vertices where the internal container is exposed.
*/
class VertexList extends AbstractListModel<DisplayVertex> {
private static final long serialVersionUID = 1L;
public List<Vertex> selected;
VertexList(List<Vertex> selected) {
this.selected = selected;
}
public int getSize() {
return selected.size();
}
public DisplayVertex getElementAt(int index) {
return new DisplayVertex(selected.get(index));
}
};
/**
* A simple visualizer for graphs. It shows (using ShowGraph) a map of the graph, intersections and
* TransitStops only, and allows a user to select stops, examine incoming and outgoing edges, and
* examine trip patterns. It's meant mainly for debugging, so it's totally OK if it develops (say)
* a bunch of weird buttons designed to debug specific cases.
*/
public class GraphVisualizer extends JFrame implements VertexSelectionListener {
private final class ComparePathStatesClickListener implements ListSelectionListener {
private JList<String> outputList;
ComparePathStatesClickListener(JList<String> outputList){
this.outputList = outputList;
}
@Override
public void valueChanged(ListSelectionEvent e) {
@SuppressWarnings("unchecked")
JList<State> theList = (JList<State>)e.getSource();
State st = (State)theList.getSelectedValue();
if(st==null){
return;
}
DefaultListModel<String> stateListModel = new DefaultListModel<String>();
stateListModel.addElement( "weight:"+st.getWeight() );
stateListModel.addElement( "weightdelta:"+st.getWeightDelta() );
stateListModel.addElement( "bikeRenting:"+st.isBikeRenting() );
stateListModel.addElement( "carParked:"+st.isCarParked() );
stateListModel.addElement( "walkDistance:"+st.getWalkDistance() );
stateListModel.addElement( "elapsedTime:"+st.getElapsedTimeSeconds() );
stateListModel.addElement( "numBoardings:"+st.getNumBoardings() );
outputList.setModel( stateListModel );
lastStateClicked = st;
}
}
private final class OnPopupMenuClickListener implements ActionListener {
private final class DiffListCellRenderer extends DefaultListCellRenderer {
private final int diverge;
private final int converge;
private DiffListCellRenderer(int diverge, int converge) {
this.diverge = diverge;
this.converge = converge;
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(isSelected){
return c;
}
if(index <= diverge){
c.setBackground(new Color(196,201,255));
}
if(index >= converge){
c.setBackground(new Color(255,196,196));
}
return c;
}
}
private int[] diffPaths() {
if(firstComparePath == null || secondComparePath == null) {
int[] failboat = {-2,-2};
return failboat;
}
int l1 = firstComparePath.states.size();
int l2 = secondComparePath.states.size();
int minlen = l1 < l2 ? l1 : l2;
int divergence=-1;
int convergence=-1;
// find divergence
for(int i=0; i<minlen; i++){
Vertex v1 = firstComparePath.states.get(i).getVertex();
Vertex v2 = secondComparePath.states.get(i).getVertex();
if(!v1.equals(v2)){
divergence = i-1;
break;
}
}
// find convergence
for(int i=0; i<minlen; i++){
Vertex v1 = firstComparePath.states.get(l1-i-1).getVertex();
Vertex v2 = secondComparePath.states.get(l2-i-1).getVertex();
if(!v1.equals(v2)){
convergence = i-1;
break;
}
}
int[] ret = {divergence,convergence};
return ret;
}
@Override
public void actionPerformed(ActionEvent e) {
PathPrinter pp = ((PathPrinter) pathsList.getSelectedValue());
if(pp==null){
return;
}
GraphPath path = pp.gp;
firstComparePath = secondComparePath;
secondComparePath = path;
if(firstComparePath != null) {
DefaultListModel<State> pathModel = new DefaultListModel<State>();
for( State st : firstComparePath.states ){
pathModel.addElement( st );
}
firstComparePathStates.setModel( pathModel );
}
if(secondComparePath != null){
DefaultListModel<State> pathModel = new DefaultListModel<State>();
for( State st : secondComparePath.states ){
pathModel.addElement( st );
}
secondComparePathStates.setModel( pathModel );
}
int[] diff = diffPaths();
final int diverge = diff[0];
final int converge = diff[1];
if(diff[0]>=0){
firstComparePathStates.setCellRenderer(new DiffListCellRenderer(diverge,firstComparePath.states.size()-converge-1));
secondComparePathStates.setCellRenderer(new DiffListCellRenderer(diverge,secondComparePath.states.size()-converge-1));
}
}
}
class PathPrinter{
GraphPath gp;
PathPrinter(GraphPath gp){
this.gp=gp;
}
public String toString(){
SimpleDateFormat shortDateFormat = new SimpleDateFormat("HH:mm:ss z");
String startTime = shortDateFormat.format(new Date(gp.getStartTime()*1000));
String endTime = shortDateFormat.format(new Date(gp.getEndTime()*1000));
return "Path ("+startTime+"-"+endTime+") weight:"+gp.getWeight()+" dur:"+(gp.getDuration()/60.0)+" walk:"+gp.getWalkDistance()+" nTrips:"+gp.getTrips().size();
}
}
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(GraphVisualizer.class);
private JPanel leftPanel;
private ShowGraph showGraph;
public JList<DisplayVertex> nearbyVertices;
private JList<Edge> outgoingEdges;
private JList<Edge> incomingEdges;
private JTextField sourceVertex;
private JTextField sinkVertex;
private JCheckBox walkCheckBox;
private JCheckBox bikeCheckBox;
private JCheckBox trainCheckBox;
private JCheckBox busCheckBox;
private JCheckBox ferryCheckBox;
private JCheckBox transitCheckBox;
private JCheckBox carCheckBox;
private JCheckBox cmvCheckBox;
private JTextField searchDate;
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private JTextField boardingPenaltyField;
private DefaultListModel<GraphBuilderAnnotation> annotationMatchesModel;
private JList<GraphBuilderAnnotation> annotationMatches;
private PathService pathservice;
private GenericAStarFactory sptServiceFactory = new GenericAStarFactory();
private DefaultListModel<String> metadataModel;
private HashSet<Vertex> closed;
private Vertex tracingVertex;
private HashSet<Vertex> open;
private HashSet<Vertex> seen;
private JList<String> metadataList;
private final Graph graph;
private JRadioButton opQuick;
private JRadioButton opSafe;
private JRadioButton opFlat;
private JRadioButton opGreenways;
private ButtonGroup optimizeTypeGrp;
private JTextField maxWalkField;
private JTextField walkSpeed;
private JTextField bikeSpeed;
private JTextField heuristicWeight;
private JCheckBox softWalkLimiting;
private JTextField softWalkPenalty;
private JTextField softWalkOverageRate;
private JCheckBox arriveByCheckBox;
private JLabel searchTimeElapsedLabel;
private JCheckBox dontUseGraphicalCallbackCheckBox;
private JTextField nPaths;
private JList<PathPrinter> pathsList;
private JList<State> pathStates;
private JCheckBox showTransitCheckbox;
private JCheckBox showStreetsCheckbox;
private JCheckBox showMultistateVerticesCheckbox;
private JCheckBox showHighlightedCheckbox;
private JCheckBox showSPTCheckbox;
private ShortestPathTree spt;
private JTextField sptFlattening;
private JTextField sptThickness;
private JPopupMenu popup;
private GraphPath firstComparePath;
private GraphPath secondComparePath;
private JList<State> firstComparePathStates;
private JList<State> secondComparePathStates;
private JList<String> secondStateData;
private JList<String> firstStateData;
protected State lastStateClicked=null;
private JCheckBox longDistanceModeCheckbox;
private GraphService graphService;
public GraphVisualizer(GraphService graphService) {
super();
LOG.info("Starting up graph visualizer...");
this.graphService = graphService;
this.graph = graphService.getGraph();
this.pathservice = new ParetoPathService(graphService, sptServiceFactory);
setTitle("GraphVisualizer");
init();
}
public void run () {
this.setVisible(true);
}
public void init() {
final JTabbedPane tabbedPane = new JTabbedPane();
final Container mainTab = makeMainTab();
Container prefsPanel = makePrefsPanel();
Container diffTab = makeDiffTab();
tabbedPane.addTab("Main", null, mainTab,
"Pretty much everything");
tabbedPane.addTab("Prefs", null, prefsPanel,
"Routing preferences");
tabbedPane.addTab("Diff", null, diffTab, "multistate path diffs");
//Add the tabbed pane to this panel.
add(tabbedPane);
//The following line enables to use scrolling tabs.
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
// startup the graphical pane; ensure closing works; draw the window
showGraph.init();
addWindowListener(new ExitListener());
pack();
// make sure the showGraph quits drawing when we switch tabs
tabbedPane.addChangeListener(new ChangeListener(){
@Override
public void stateChanged(ChangeEvent e) {
if( tabbedPane.getSelectedComponent().equals(mainTab) ){
showGraph.loop();
} else{
showGraph.noLoop();
}
}
});
}
private Container makeDiffTab() {
JPanel pane = new JPanel();
pane.setLayout(new GridLayout(0, 2));
firstStateData = new JList<String>();
secondStateData = new JList<String>();
// a place to list the states of the first path
firstComparePathStates = new JList<State>();
JScrollPane stScrollPane = new JScrollPane(firstComparePathStates);
stScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.add(stScrollPane);
firstComparePathStates.addListSelectionListener(new ComparePathStatesClickListener(firstStateData));
// a place to list the states of the second path
secondComparePathStates = new JList<State>();
stScrollPane = new JScrollPane(secondComparePathStates);
stScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.add(stScrollPane);
secondComparePathStates.addListSelectionListener(new ComparePathStatesClickListener(secondStateData));
// a place to list details of a state selected from the first path
stScrollPane = new JScrollPane(firstStateData);
stScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.add(stScrollPane);
// a place to list details of a state selected from the second path
stScrollPane = new JScrollPane(secondStateData);
stScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.add(stScrollPane);
// A button that executes the 'dominates' function between the two states
// this is useful only if you have a breakpoint set up
JButton dominateButton = new JButton();
dominateButton.setText("dominates");
dominateButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
State s1 = firstComparePathStates.getSelectedValue();
State s2 = secondComparePathStates.getSelectedValue();
System.out.println("s1 dominates s2:"+MultiShortestPathTree.dominates(s1,s2));
System.out.println("s2 dominates s1:"+MultiShortestPathTree.dominates(s2,s1));
}
});
pane.add(dominateButton);
// A button that executes the 'traverse' function leading to the last clicked state
// in either window. Also only useful if you set a breakpoint.
JButton traverseButton = new JButton();
traverseButton.setText("traverse");
traverseButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
if(lastStateClicked==null){
return;
}
Edge backEdge = lastStateClicked.getBackEdge();
State backState = lastStateClicked.getBackState();
backEdge.traverse(backState);
}
});
pane.add(traverseButton);
return pane;
}
private Container makeMainTab() {
Container pane = new JPanel();
pane.setLayout(new BorderLayout());
// init center graphical panel
showGraph = new ShowGraph(this, getGraph());
pane.add(showGraph, BorderLayout.CENTER);
sptServiceFactory.setTraverseVisitor(new VisualTraverseVisitor(showGraph));
// init left panel
leftPanel = new JPanel();
leftPanel.setLayout(new BorderLayout());
pane.add(leftPanel, BorderLayout.LINE_START);
initRoutingSubpanel();
initVertexInfoSubpanel();
initControlButtons();
// init right panel
initRightPanel(pane);
return pane;
}
private JComponent makePrefsPanel(){
JPanel pane = new JPanel();
pane.setLayout(new GridLayout(0, 2));
// 2 rows: transport mode options
walkCheckBox = new JCheckBox("walk");
walkCheckBox.setSelected(true);
pane.add(walkCheckBox);
bikeCheckBox = new JCheckBox("bike");
pane.add(bikeCheckBox);
trainCheckBox = new JCheckBox("trainish");
pane.add(trainCheckBox);
busCheckBox = new JCheckBox("busish");
pane.add(busCheckBox);
ferryCheckBox = new JCheckBox("ferry");
pane.add(ferryCheckBox);
transitCheckBox = new JCheckBox("transit");
transitCheckBox.setSelected(true);
pane.add(transitCheckBox);
carCheckBox = new JCheckBox("car");
pane.add(carCheckBox);
cmvCheckBox = new JCheckBox("custom vehicle");
pane.add(cmvCheckBox);
// row: arrive by?
JLabel arriveByLabel = new JLabel("Arrive by?:");
pane.add(arriveByLabel);
arriveByCheckBox = new JCheckBox("arrive by");
pane.add(arriveByCheckBox);
// row: boarding penalty
JLabel boardPenaltyLabel = new JLabel("Boarding penalty (min):");
pane.add(boardPenaltyLabel);
boardingPenaltyField = new JTextField("5");
pane.add(boardingPenaltyField);
// row: max walk
JLabel maxWalkLabel = new JLabel("Maximum walk (meters):");
pane.add(maxWalkLabel);
maxWalkField = new JTextField("5000");
pane.add(maxWalkField);
// row: walk speed
JLabel walkSpeedLabel = new JLabel("Walk speed (m/s):");
pane.add(walkSpeedLabel);
walkSpeed = new JTextField("1.33");
pane.add(walkSpeed);
// row: bike speed
JLabel bikeSpeedLabel = new JLabel("Bike speed (m/s):");
pane.add(bikeSpeedLabel);
bikeSpeed = new JTextField("5.0");
pane.add(bikeSpeed);
// row: heuristic weight
JLabel heuristicWeightLabel = new JLabel("Heuristic weight:");
pane.add(heuristicWeightLabel);
heuristicWeight = new JTextField("1.0");
pane.add(heuristicWeight);
// row: soft walk?
JLabel softWalkLimitLabel = new JLabel("Soft walk-limit?:");
pane.add(softWalkLimitLabel);
softWalkLimiting = new JCheckBox("soft walk-limiting");
pane.add(softWalkLimiting);
// row: soft walk-limit penalty
JLabel softWalkLimitPenaltyLabel = new JLabel("Soft walk-limiting penalty:");
pane.add(softWalkLimitPenaltyLabel);
softWalkPenalty = new JTextField("60.0");
pane.add(softWalkPenalty);
// row: soft walk-limit overage
JLabel softWalkLimitOverageLabel = new JLabel("Soft walk-limiting overage:");
pane.add(softWalkLimitOverageLabel);
softWalkOverageRate = new JTextField("5.0");
pane.add(softWalkOverageRate);
// row: nPaths
JLabel nPathsLabel = new JLabel("nPaths:");
pane.add(nPathsLabel);
nPaths = new JTextField("1");
pane.add(nPaths);
//viz preferences
ItemListener onChangeVizPrefs = new ItemListener(){
@Override
public void itemStateChanged(ItemEvent e) {
showGraph.setShowTransit( showTransitCheckbox.isSelected() );
showGraph.setShowStreets( showStreetsCheckbox.isSelected() );
showGraph.setShowMultistateVertices( showMultistateVerticesCheckbox.isSelected() );
showGraph.setShowHightlights( showHighlightedCheckbox.isSelected() );
showGraph.setShowSPT( showSPTCheckbox.isSelected() );
showGraph.redraw();
}
};
showTransitCheckbox = new JCheckBox("show transit");
showTransitCheckbox.setSelected(true);
showTransitCheckbox.addItemListener( onChangeVizPrefs );
pane.add(showTransitCheckbox);
showStreetsCheckbox = new JCheckBox("show streets");
showStreetsCheckbox.setSelected(true);
showStreetsCheckbox.addItemListener( onChangeVizPrefs );
pane.add(showStreetsCheckbox);
showHighlightedCheckbox = new JCheckBox("show highlighted");
showHighlightedCheckbox.setSelected(true);
showHighlightedCheckbox.addItemListener( onChangeVizPrefs );
pane.add(showHighlightedCheckbox);
showSPTCheckbox = new JCheckBox("show SPT");
showSPTCheckbox.setSelected(true);
showSPTCheckbox.addItemListener( onChangeVizPrefs );
pane.add(showSPTCheckbox);
showMultistateVerticesCheckbox = new JCheckBox("show multistate vertices");
showMultistateVerticesCheckbox.setSelected(true);
showMultistateVerticesCheckbox.addItemListener( onChangeVizPrefs );
pane.add(showMultistateVerticesCheckbox);
// row: SPT flattening
JLabel sptFlatteningLabel = new JLabel("SPT flattening:");
pane.add(sptFlatteningLabel);
sptFlattening = new JTextField("0.3");
pane.add(sptFlattening);
// row: SPT thickness
JLabel sptThicknessLabel = new JLabel("SPT thickness:");
pane.add(sptThicknessLabel);
sptThickness = new JTextField("0.1");
pane.add(sptThickness);
// radio buttons: optimize type
JLabel optimizeTypeLabel = new JLabel("Optimize type:");
pane.add(optimizeTypeLabel);
opQuick = new JRadioButton("Quick");
opQuick.setSelected(true);
opSafe = new JRadioButton("Safe");
opFlat = new JRadioButton("Flat");
opGreenways = new JRadioButton("Greenways");
optimizeTypeGrp = new ButtonGroup();
optimizeTypeGrp.add(opQuick);
optimizeTypeGrp.add(opSafe);
optimizeTypeGrp.add(opFlat);
optimizeTypeGrp.add(opGreenways);
JPanel optimizeTypePane = new JPanel();
optimizeTypePane.add(opQuick);
optimizeTypePane.add(opSafe);
optimizeTypePane.add(opFlat);
optimizeTypePane.add(opGreenways);
pane.add(optimizeTypePane);
// long distance mode
ItemListener onChangeLongDistanceMode = new ItemListener(){
@Override
public void itemStateChanged(ItemEvent e) {
JCheckBox item = (JCheckBox) e.getItem();
setLongDistanceMode( item.isSelected() );
}
};
longDistanceModeCheckbox = new JCheckBox("long distance mode");
longDistanceModeCheckbox.setSelected(false);
longDistanceModeCheckbox.addItemListener( onChangeLongDistanceMode );
pane.add(longDistanceModeCheckbox);
return pane;
}
protected void setLongDistanceMode(boolean selected) {
if( selected ){
this.pathservice = new LongDistancePathService(graphService, sptServiceFactory);
} else {
this.pathservice = new ParetoPathService(graphService, sptServiceFactory);
}
}
OptimizeType getSelectedOptimizeType(){
if(opQuick.isSelected()){
return OptimizeType.QUICK;
}
if(opSafe.isSelected()){
return OptimizeType.SAFE;
}
if(opFlat.isSelected()){
return OptimizeType.FLAT;
}
if(opGreenways.isSelected()){
return OptimizeType.GREENWAYS;
}
return OptimizeType.QUICK;
}
protected JComponent makeTextPanel(String text) {
JPanel panel = new JPanel(false);
JLabel filler = new JLabel(text);
filler.setHorizontalAlignment(JLabel.CENTER);
panel.setLayout(new GridLayout(1, 1));
panel.add(filler);
return panel;
}
private void initRightPanel(Container pane) {
/* right panel holds trip pattern and stop metadata */
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BorderLayout());
pane.add(rightPanel, BorderLayout.LINE_END);
JTabbedPane rightPanelTabs = new JTabbedPane();
rightPanel.add(rightPanelTabs, BorderLayout.LINE_END);
// a place to print out the details of a path
pathStates = new JList<State>();
JScrollPane stScrollPane = new JScrollPane(pathStates);
stScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
rightPanelTabs.addTab("path states", stScrollPane);
// when you select a path component state, it prints the backedge's metadata
pathStates.addListSelectionListener(new ListSelectionListener(){
@Override
public void valueChanged(ListSelectionEvent e) {
outgoingEdges.clearSelection();
incomingEdges.clearSelection();
@SuppressWarnings("unchecked")
JList<State> theList = (JList<State>)e.getSource();
State st = (State)theList.getSelectedValue();
Edge edge = st.getBackEdge();
reactToEdgeSelection( edge, false );
}
});
metadataList = new JList<String>();
metadataModel = new DefaultListModel<String>();
metadataList.setModel(metadataModel);
JScrollPane mdScrollPane = new JScrollPane(metadataList);
mdScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
rightPanelTabs.addTab("metadata", mdScrollPane);
// This is where matched annotations from an annotation search go
annotationMatches = new JList<GraphBuilderAnnotation>();
annotationMatches.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
@SuppressWarnings("unchecked")
JList<GraphBuilderAnnotation> theList = (JList<GraphBuilderAnnotation>) e.getSource();
GraphBuilderAnnotation anno = theList.getSelectedValue();
if (anno == null)
return;
showGraph.drawAnotation(anno);
}
});
annotationMatchesModel = new DefaultListModel<GraphBuilderAnnotation>();
annotationMatches.setModel(annotationMatchesModel);
JScrollPane amScrollPane = new JScrollPane(annotationMatches);
amScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
rightPanelTabs.addTab("annotations", amScrollPane);
Dimension size = new Dimension(200, 1600);
amScrollPane.setMaximumSize(size);
amScrollPane.setPreferredSize(size);
stScrollPane.setMaximumSize(size);
stScrollPane.setPreferredSize(size);
mdScrollPane.setMaximumSize(size);
mdScrollPane.setPreferredSize(size);
rightPanelTabs.setMaximumSize(size);
rightPanel.setMaximumSize(size);
}
private void initControlButtons() {
/* buttons at bottom */
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 3));
leftPanel.add(buttonPanel, BorderLayout.PAGE_END);
JButton zoomDefaultButton = new JButton("Zoom to default");
zoomDefaultButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showGraph.zoomToDefault();
}
});
buttonPanel.add(zoomDefaultButton);
final JFrame frame = this;
JButton zoomToNodeButton = new JButton("Zoom to node");
zoomToNodeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String nodeName = (String) JOptionPane.showInputDialog(frame, "Node id",
JOptionPane.PLAIN_MESSAGE);
Vertex v = getGraph().getVertex(nodeName);
if (v == null) {
System.out.println("no such node " + nodeName);
} else {
showGraph.zoomToVertex(v);
}
}
});
buttonPanel.add(zoomToNodeButton);
JButton zoomToLocationButton = new JButton("Zoom to location");
zoomToLocationButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String result = JOptionPane.showInputDialog("Enter the location (lat lon)");
if (result == null || result.length() == 0)
return;
String[] tokens = result.split("[\\s,]+");
double lat = Double.parseDouble(tokens[0]);
double lon = Double.parseDouble(tokens[1]);
Coordinate c = new Coordinate(lon, lat);
showGraph.zoomToLocation(c);
}
});
buttonPanel.add(zoomToLocationButton);
JButton zoomOutButton = new JButton("Zoom out");
zoomOutButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showGraph.zoomOut();
}
});
buttonPanel.add(zoomOutButton);
JButton routeButton2 = new JButton("Route");
routeButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// String initialFrom = "";
// Object selected = nearbyVertices.getSelectedValue();
// if (selected != null) {
// initialFrom = selected.toString();
// }
// RouteDialog dlg = new RouteDialog(frame, initialFrom); // modal
String from = sourceVertex.getText();
String to = sinkVertex.getText();
route(from, to);
}
});
buttonPanel.add(routeButton2);
JButton findButton = new JButton("Find node");
findButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String nodeName = (String) JOptionPane.showInputDialog(frame, "Node id",
JOptionPane.PLAIN_MESSAGE);
Vertex v = getGraph().getVertex(nodeName);
if (v == null) {
System.out.println("no such node " + nodeName);
} else {
showGraph.highlightVertex(v);
ArrayList<Vertex> l = new ArrayList<Vertex>();
l.add(v);
verticesSelected(l);
}
}
});
buttonPanel.add(findButton);
JButton findEdgeButton = new JButton("Find edge");
findEdgeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String edgeName = (String) JOptionPane.showInputDialog(frame, "Edge name like",
JOptionPane.PLAIN_MESSAGE);
for (Vertex gv : getGraph().getVertices()) {
for (Edge edge : gv.getOutgoing()) {
if (edge.getName() != null && edge.getName().contains(edgeName)) {
showGraph.highlightVertex(gv);
ArrayList<Vertex> l = new ArrayList<Vertex>();
l.add(gv);
verticesSelected(l);
}
}
}
}
});
buttonPanel.add(findEdgeButton);
JButton checkButton = new JButton("Check graph");
checkButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
checkGraph();
}
});
buttonPanel.add(checkButton);
JButton traceButton = new JButton("Trace");
traceButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
trace();
}
});
buttonPanel.add(traceButton);
// annotation search button
JButton annotationButton = new JButton("Find annotations");
annotationButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
findAnnotation();
}
});
buttonPanel.add(annotationButton);
JButton findEdgeByIdButton = new JButton("Find edge ID");
findEdgeByIdButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String edgeIdStr = (String) JOptionPane.showInputDialog(frame, "Edge ID",
JOptionPane.PLAIN_MESSAGE);
Integer edgeId = Integer.parseInt(edgeIdStr);
Edge edge = getGraph().getEdgeById(edgeId);
if (edge != null) {
showGraph.highlightEdge(edge);
showGraph.highlightVertex(edge.getFromVertex());
} else {
System.out.println("Found no edge with ID " + edgeIdStr);
}
}
});
buttonPanel.add(findEdgeByIdButton);
JButton snapButton = new JButton("Snap location");
snapButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String locString = (String) JOptionPane.showInputDialog(frame, "Location string",
"");
GenericLocation loc = GenericLocation.fromOldStyleString(locString);
RoutingRequest rr = new RoutingRequest();
Vertex v = graph.streetIndex.getVertexForLocation(
loc, rr);
showGraph.highlightVertex(v);
}
});
buttonPanel.add(snapButton);
}
private void getMetadata(Object selected) {
Class<?> c = selected.getClass();
Field[] fields;
while (c != null && c != Object.class) {
metadataModel.addElement("Class:" + c);
fields = c.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
int modifiers = field.getModifiers();
if ((modifiers & Modifier.STATIC) != 0) {
continue;
}
field.setAccessible(true);
String name = field.getName();
String value = "(unknown -- see console for stack trace)";
try {
value = "" + field.get(selected);
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
metadataModel.addElement(name + ": " + value);
}
c = c.getSuperclass();
}
}
private void reactToEdgeSelection(Edge selected, boolean outgoing){
if (selected == null) {
return;
}
showGraph.highlightEdge(selected);
/* for turns, highlight the outgoing street's ends */
if (selected instanceof StreetEdge) {
List<Vertex> vertices = new ArrayList<Vertex>();
List<Edge> edges = new ArrayList<Edge>();
Vertex tov = selected.getToVertex();
for (Edge og : tov.getOutgoing()) {
if (og instanceof StreetEdge) {
edges.add(og);
vertices.add(og.getToVertex());
break;
}
}
Vertex fromv = selected.getFromVertex();
for (Edge ic : fromv.getIncoming()) {
if (ic instanceof StreetEdge) {
edges.add(ic);
vertices.add(ic.getFromVertex());
break;
}
}
// showGraph.setHighlightedVertices(vertices);
showGraph.setHighlightedEdges(edges);
}
/* add the connected vertices to the list of vertices */
VertexList nearbyModel = (VertexList) nearbyVertices.getModel();
List<Vertex> vertices = nearbyModel.selected;
Vertex v;
if (outgoing) {
v = selected.getToVertex();
} else {
v = selected.getFromVertex();
}
if (!vertices.contains(v)) {
vertices.add(v);
nearbyModel = new VertexList(vertices);
nearbyVertices.setModel(nearbyModel); // this should just be an event, but for
// some reason, JList doesn't implement
// the right event.
}
/* set up metadata tab */
metadataModel.clear();
getMetadata(selected);
// fromv
Vertex fromv = selected.getFromVertex();
getMetadata(fromv);
if (selected instanceof StreetEdge) {
//TODO ElevationProfileSegment do not exist anymore
//getMetadata(((StreetEdge) selected).getElevationProfileSegment());
}
metadataList.revalidate();
}
private void initVertexInfoSubpanel() {
JPanel vertexDataPanel = new JPanel();
vertexDataPanel.setLayout(new BoxLayout(vertexDataPanel, BoxLayout.PAGE_AXIS));
vertexDataPanel.setPreferredSize(new Dimension(300, 600));
leftPanel.add(vertexDataPanel, BorderLayout.CENTER);
// nearby vertices
JLabel nvLabel = new JLabel("Vertices");
vertexDataPanel.add(nvLabel);
nearbyVertices = new JList<DisplayVertex>();
nearbyVertices.setVisibleRowCount(4);
JScrollPane nvScrollPane = new JScrollPane(nearbyVertices);
vertexDataPanel.add(nvScrollPane);
nearbyVertices.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
outgoingEdges.removeAll();
incomingEdges.removeAll();
DisplayVertex selected = (DisplayVertex) nearbyVertices.getSelectedValue();
if (selected != null) {
Vertex nowSelected = selected.vertex;
showGraph.highlightVertex(nowSelected);
outgoingEdges.setModel(new EdgeListModel(nowSelected.getOutgoing()));
incomingEdges.setModel(new EdgeListModel(nowSelected.getIncoming()));
}
}
});
// listener useful for both incoming and outgoing edge list panes
// when a different edge is selected, change up the pattern pane and list of nearby nodes
ListSelectionListener edgeChanged = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
@SuppressWarnings("unchecked")
JList<Edge> edgeList = (JList<Edge>) e.getSource();
Edge selected = (Edge) edgeList.getSelectedValue();
boolean outgoing = (edgeList==outgoingEdges);
reactToEdgeSelection( selected, outgoing );
}
};
// outgoing edges
JLabel ogeLabel = new JLabel("Outgoing edges");
vertexDataPanel.add(ogeLabel);
outgoingEdges = new JList<Edge>();
outgoingEdges.setVisibleRowCount(4);
JScrollPane ogeScrollPane = new JScrollPane(outgoingEdges);
vertexDataPanel.add(ogeScrollPane);
outgoingEdges.addListSelectionListener(edgeChanged);
// incoming edges
JLabel iceLabel = new JLabel("Incoming edges");
vertexDataPanel.add(iceLabel);
incomingEdges = new JList<Edge>();
JScrollPane iceScrollPane = new JScrollPane(incomingEdges);
vertexDataPanel.add(iceScrollPane);
incomingEdges.addListSelectionListener(edgeChanged);
// paths list
JLabel pathsLabel = new JLabel("Paths");
vertexDataPanel.add(pathsLabel);
pathsList = new JList<PathPrinter>();
popup = new JPopupMenu();
JMenuItem compareMenuItem = new JMenuItem("compare");
compareMenuItem.addActionListener(new OnPopupMenuClickListener());
popup.add(compareMenuItem);
// make paths list right-clickable
pathsList.addMouseListener(new MouseListener(){
@Override
public void mouseClicked(MouseEvent e) {
if( SwingUtilities.isRightMouseButton(e) ){
@SuppressWarnings("unchecked")
JList<PathPrinter> list = (JList<PathPrinter>)e.getSource();
int row = list.locationToIndex(e.getPoint());
list.setSelectedIndex(row);
popup.show(list, e.getX(), e.getY());
}
}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
});
pathsList.addListSelectionListener(new ListSelectionListener(){
@Override
public void valueChanged(ListSelectionEvent ev) {
PathPrinter pp = ((PathPrinter) pathsList.getSelectedValue());
if(pp==null){
return;
}
GraphPath path = pp.gp;
DefaultListModel<State> pathModel = new DefaultListModel<State>();
for( State st : path.states ){
pathModel.addElement( st );
}
pathStates.setModel( pathModel );
showGraph.highlightGraphPath(path);
}
});
JScrollPane pathsScrollPane = new JScrollPane(pathsList);
vertexDataPanel.add(pathsScrollPane);
}
private void initRoutingSubpanel() {
/* ROUTING SUBPANEL */
JPanel routingPanel = new JPanel();
routingPanel.setLayout(new GridLayout(0, 2));
leftPanel.add(routingPanel, BorderLayout.NORTH);
// row: source vertex
JButton setSourceVertexButton = new JButton("set source");
setSourceVertexButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object selected = nearbyVertices.getSelectedValue();
if (selected != null) {
sourceVertex.setText(selected.toString());
}
}
});
routingPanel.add(setSourceVertexButton);
sourceVertex = new JTextField();
routingPanel.add(sourceVertex);
// row: sink vertex
JButton setSinkVertexButton = new JButton("set sink");
setSinkVertexButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object selected = nearbyVertices.getSelectedValue();
if (selected != null) {
sinkVertex.setText(selected.toString());
}
}
});
routingPanel.add(setSinkVertexButton);
sinkVertex = new JTextField();
routingPanel.add(sinkVertex);
// row: set date
JButton resetSearchDateButton = new JButton("now ->");
resetSearchDateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
searchDate.setText(dateFormat.format(new Date()));
}
});
routingPanel.add(resetSearchDateButton);
searchDate = new JTextField();
searchDate.setText(dateFormat.format(new Date()));
routingPanel.add(searchDate);
// row: launch, continue, and clear path search
JButton routeButton = new JButton("path search");
routeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String from = sourceVertex.getText();
String to = sinkVertex.getText();
route(from, to);
}
});
routingPanel.add(routeButton);
JButton continueButton = new JButton("continue");
continueButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//TODO continue search
}
});
routingPanel.add(continueButton);
JButton clearRouteButton = new JButton("clear path");
clearRouteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showGraph.highlightGraphPath(null);
showGraph.clearHighlights();
showGraph.resetSPT();
}
});
routingPanel.add(clearRouteButton);
//label: search time elapsed
searchTimeElapsedLabel = new JLabel("search time elapsed:");
routingPanel.add(searchTimeElapsedLabel);
//option: don't use graphical callback. useful for doing a quick profile
dontUseGraphicalCallbackCheckBox = new JCheckBox("no graphics");
routingPanel.add(dontUseGraphicalCallbackCheckBox);
}
protected void trace() {
DisplayVertex selected = (DisplayVertex) nearbyVertices.getSelectedValue();
if (selected == null) {
return;
}
Vertex v = selected.vertex;
if (tracingVertex != v) {
tracingVertex = v;
closed = new HashSet<Vertex>();
open = new HashSet<Vertex>();
open.add(v);
seen = new HashSet<Vertex>();
}
HashSet<Vertex> newOpen = new HashSet<Vertex>();
for (Vertex v2 : open) {
closed.add(v2);
for (Edge e : v2.getOutgoing()) {
Vertex target = e.getToVertex();
if (closed.contains(target)) {
continue;
}
newOpen.add(target);
}
}
seen.addAll(newOpen);
open = newOpen;
showGraph.setHighlightedVertices(seen);
}
protected void traceOld() {
HashSet<Vertex> seenVertices = new HashSet<Vertex>();
DisplayVertex selected = (DisplayVertex) nearbyVertices.getSelectedValue();
if (selected == null) {
System.out.println("no vertex selected");
return;
}
Vertex v = selected.vertex;
System.out.println("initial vertex: " + v);
Queue<Vertex> toExplore = new LinkedList<Vertex>();
toExplore.add(v);
seenVertices.add(v);
while (!toExplore.isEmpty()) {
Vertex src = toExplore.poll();
for (Edge e : src.getOutgoing()) {
Vertex tov = e.getToVertex();
if (!seenVertices.contains(tov)) {
seenVertices.add(tov);
toExplore.add(tov);
}
}
}
showGraph.setHighlightedVertices(seenVertices);
}
protected void checkGraph() {
HashSet<Vertex> seenVertices = new HashSet<Vertex>();
Collection<Vertex> allVertices = getGraph().getVertices();
Vertex v = allVertices.iterator().next();
System.out.println("initial vertex: " + v);
Queue<Vertex> toExplore = new LinkedList<Vertex>();
toExplore.add(v);
seenVertices.add(v);
while (!toExplore.isEmpty()) {
Vertex src = toExplore.poll();
for (Edge e : src.getOutgoing()) {
Vertex tov = e.getToVertex();
if (!seenVertices.contains(tov)) {
seenVertices.add(tov);
toExplore.add(tov);
}
}
}
System.out.println("After investigation, visited " + seenVertices.size() + " of "
+ allVertices.size());
/* now, let's find an unvisited vertex */
for (Vertex u : allVertices) {
if (!seenVertices.contains(u)) {
System.out.println("unvisited vertex" + u);
break;
}
}
}
protected void route(String from, String to) {
Date when;
// Year + 1900
try {
when = dateFormat.parse(searchDate.getText());
} catch (ParseException e) {
searchDate.setText("Format: " + dateFormat.toPattern());
return;
}
TraverseModeSet modeSet = new TraverseModeSet();
modeSet.setWalk(walkCheckBox.isSelected());
modeSet.setBicycle(bikeCheckBox.isSelected());
modeSet.setFerry(ferryCheckBox.isSelected());
modeSet.setTrainish(trainCheckBox.isSelected());
modeSet.setBusish(busCheckBox.isSelected());
modeSet.setCar(carCheckBox.isSelected());
modeSet.setCustomMotorVehicle(cmvCheckBox.isSelected());
// must set generic transit mode last, and only when it is checked
// otherwise 'false' will clear trainish and busish
if (transitCheckBox.isSelected())
modeSet.setTransit(true);
RoutingRequest options = new RoutingRequest(modeSet);
options.setArriveBy(arriveByCheckBox.isSelected());
options.setWalkBoardCost(Integer.parseInt(boardingPenaltyField.getText()) * 60); // override low 2-4 minute values
// TODO LG Add ui element for bike board cost (for now bike = 2 * walk)
options.setBikeBoardCost(Integer.parseInt(boardingPenaltyField.getText()) * 60 * 2);
// there should be a ui element for walk distance and optimize type
options.setOptimize( getSelectedOptimizeType() );
options.setMaxWalkDistance(Integer.parseInt(maxWalkField.getText()));
options.setDateTime(when);
options.setFromString(from);
options.setToString(to);
options.walkSpeed = Float.parseFloat(walkSpeed.getText());
options.bikeSpeed = Float.parseFloat(bikeSpeed.getText());
options.heuristicWeight = (Float.parseFloat(heuristicWeight.getText()));
options.softWalkLimiting = ( softWalkLimiting.isSelected() );
options.softWalkPenalty = (Float.parseFloat(softWalkPenalty.getText()));
options.softWalkOverageRate = (Float.parseFloat(this.softWalkOverageRate.getText()));
options.numItineraries = 1;
System.out.println("--------");
System.out.println("Path from " + from + " to " + to + " at " + when);
System.out.println("\tModes: " + modeSet);
System.out.println("\tOptions: " + options);
options.numItineraries = ( Integer.parseInt( this.nPaths.getText() ) );
// apply callback if the options call for it
if( dontUseGraphicalCallbackCheckBox.isSelected() ){
sptServiceFactory.setTraverseVisitor(null);
} else {
sptServiceFactory.setTraverseVisitor(new VisualTraverseVisitor(showGraph));
}
// set up a visitor to the path service so we can get the SPT as it's generated
SPTVisitor vis = new SPTVisitor();
pathservice.setSPTVisitor(vis);
long t0 = System.currentTimeMillis();
// TODO: check options properly intialized (AMB)
List<GraphPath> paths = pathservice.getPaths(options);
long dt = System.currentTimeMillis() - t0;
searchTimeElapsedLabel.setText( "search time elapsed: "+dt+"ms" );
// grab the spt from the visitor
spt = vis.spt;
showGraph.setSPT(spt);
System.out.println( "got spt:"+spt );
if (paths == null) {
System.out.println("no path");
showGraph.highlightGraphPath(null);
return;
}
// now's a convenient time to set graphical SPT weights
showGraph.simpleSPT.setWeights();
showPathsInPanel(paths);
// now's a good time to set showGraph's SPT drawing weights
showGraph.setSPTFlattening( Float.parseFloat(sptFlattening.getText()) );
showGraph.setSPTThickness( Float.parseFloat(sptThickness.getText()) );
showGraph.redraw();
options.cleanup();
}
private void showPathsInPanel(List<GraphPath> paths) {
// show paths in a list panel
DefaultListModel<PathPrinter> data = new DefaultListModel<PathPrinter>();
for(GraphPath gp : paths ){
data.addElement( new PathPrinter(gp) );
}
pathsList.setModel(data);
}
protected void findAnnotation() {
Set<Class<? extends GraphBuilderAnnotation>> gbaClasses = Sets.newHashSet();
for (GraphBuilderAnnotation gba : graph.getBuilderAnnotations()) {
gbaClasses.add(gba.getClass());
}
@SuppressWarnings("unchecked")
Class<? extends GraphBuilderAnnotation> variety = (Class<? extends GraphBuilderAnnotation>) JOptionPane
.showInputDialog(null, // parentComponent; TODO: set correctly
"Select the type of annotation to find", // question
"Select annotation", // title
JOptionPane.QUESTION_MESSAGE, // message type
null, // no icon
gbaClasses.toArray(), // options (built above)
StopUnlinked.class // default value
);
// User clicked cancel
if (variety == null)
return;
// loop over the annotations and save the ones of the requested type
annotationMatchesModel.clear();
for (GraphBuilderAnnotation anno : graph.getBuilderAnnotations()) {
if (variety.isInstance(anno)) {
annotationMatchesModel.addElement(anno);
}
}
System.out.println("Found " + annotationMatchesModel.getSize() + " annotations of type "
+ variety);
}
public void verticesSelected(final List<Vertex> selected) {
// sort vertices by name
Collections.sort(selected, new Comparator<Vertex>() {
@Override
public int compare(Vertex arg0, Vertex arg1) {
return arg0.getLabel().compareTo(arg1.getLabel());
}
});
ListModel<DisplayVertex> data = new VertexList(selected);
nearbyVertices.setModel(data);
// pick out an intersection vertex and find the path
// if the spt is already available
Vertex target=null;
for(Vertex vv : selected){
if( vv instanceof IntersectionVertex ){
target = vv;
break;
}
}
if(target!=null && spt!=null){
List<GraphPath> paths = spt.getPaths(target,true);
showPathsInPanel( paths );
}
}
public Graph getGraph() {
return graph;
}
}