package aimax.osm.gui.swing.applications;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JToolBar;
import aimax.osm.data.DataResource;
import aimax.osm.data.MapEvent;
import aimax.osm.data.MapEventListener;
import aimax.osm.data.OsmMap;
import aimax.osm.data.Position;
import aimax.osm.routing.RouteCalculator;
import aimax.osm.gui.swing.viewer.MapViewFrame;
/**
* Implements a simple route planning tool. It extends the OSM map viewer by a
* little search engine for shortest paths using the A* algorithm. Set two
* markers (mouse left) before starting route calculation!
*
* @author Ruediger Lunde
*/
public class RoutePlannerApp implements ActionListener {
public final static String ROUTE_TRACK_NAME = "Route";
protected MapViewFrame frame;
protected JComboBox<String> taskSelection;
protected JButton calcButton;
protected RouteCalculator routeCalculator;
public RoutePlannerApp() {
this(new String[0]);
}
public RoutePlannerApp(String[] args) {
frame = new MapViewFrame(args);
frame.setTitle("OSM Route Planner");
routeCalculator = createRouteCalculator();
JToolBar toolbar = frame.getToolbar();
toolbar.addSeparator();
taskSelection = new JComboBox<String>(
routeCalculator.getTaskSelectionOptions());
toolbar.add(taskSelection);
toolbar.addSeparator();
calcButton = new JButton("Calculate Route");
calcButton.addActionListener(this);
toolbar.add(calcButton);
frame.getMap().addMapDataEventListener(new MapDataEventHandler());
updateEnabledState();
}
/**
* Factory method for the routing component. Subclasses can override it and
* provide more advanced routing algorithms.
*/
protected RouteCalculator createRouteCalculator() {
return new RouteCalculator();
}
public MapViewFrame getFrame() {
return frame;
}
public void showFrame() {
frame.setSize(800, 600);
frame.setVisible(true);
}
/**
* Loads the default map if necessary and returns the frame (useful for
* integration into an AIMA demo application).
*/
public MapViewFrame constructApplicationFrame() {
if (frame.getMap().isEmpty())
frame.readMap(DataResource.getULMFileResource());
return frame;
}
/** Starts route generation after the calculate button has been pressed. */
public void actionPerformed(ActionEvent e) {
if (e.getSource() == calcButton) {
OsmMap map = frame.getMap();
List<Position> positions = routeCalculator.calculateRoute(
map.getMarkers(), map, taskSelection.getSelectedIndex());
frame.getMap().createTrack(ROUTE_TRACK_NAME, positions);
}
}
/**
* Enables the Calculate button if at least two markers are set.
*/
protected void updateEnabledState() {
calcButton.setEnabled(frame.getMap().getMarkers().size() > 1);
}
/**
* Updates the enabled state of the GUI.
*
* @author Ruediger Lunde
*/
class MapDataEventHandler implements MapEventListener {
@Override
public void eventHappened(MapEvent event) {
updateEnabledState();
}
}
/**
* Start application with program arg <code>-screenwidth=xx</code> (with xx
* the width in cm) or <code>-screensize=yy</code> (with yy measured
* diagonally in inch).
*/
public static void main(String[] args) {
// indicates progress when reading large maps (for testing only)
// Logger.getLogger("aimax.osm").setLevel(Level.FINEST);
// Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
Locale.setDefault(Locale.US);
RoutePlannerApp demo = new RoutePlannerApp(args);
demo.getFrame().readMap(DataResource.getULMFileResource());
demo.showFrame();
}
}