// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.graphview.plugin; import static org.openstreetmap.josm.tools.I18n.tr; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Collection; import java.util.LinkedList; import java.util.Observable; import java.util.Observer; import javax.swing.JOptionPane; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.gui.MapFrame; import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; import org.openstreetmap.josm.gui.preferences.PreferenceSetting; import org.openstreetmap.josm.plugins.Plugin; import org.openstreetmap.josm.plugins.PluginInformation; import org.openstreetmap.josm.plugins.graphview.core.access.AccessRuleset; import org.openstreetmap.josm.plugins.graphview.core.access.AccessRulesetReader; import org.openstreetmap.josm.plugins.graphview.core.access.AccessRulesetReader.AccessRulesetSyntaxException; import org.openstreetmap.josm.plugins.graphview.core.graph.TSBasedWayGraph; import org.openstreetmap.josm.plugins.graphview.core.graph.WayGraph; import org.openstreetmap.josm.plugins.graphview.core.property.RoadIncline; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxaxleload; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxheight; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxlength; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxspeed; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxweight; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMaxwidth; import org.openstreetmap.josm.plugins.graphview.core.property.RoadMinspeed; import org.openstreetmap.josm.plugins.graphview.core.property.RoadPropertyType; import org.openstreetmap.josm.plugins.graphview.core.property.RoadSurface; import org.openstreetmap.josm.plugins.graphview.core.property.RoadTracktype; import org.openstreetmap.josm.plugins.graphview.core.property.RoadWidth; import org.openstreetmap.josm.plugins.graphview.core.visualisation.DefaultNodePositioner; import org.openstreetmap.josm.plugins.graphview.plugin.data.JOSMTransitionStructure; import org.openstreetmap.josm.plugins.graphview.plugin.dialogs.GraphViewDialog; import org.openstreetmap.josm.plugins.graphview.plugin.dialogs.GraphViewPreferenceEditor; import org.openstreetmap.josm.plugins.graphview.plugin.layer.GraphViewLayer; import org.openstreetmap.josm.plugins.graphview.plugin.preferences.GraphViewPreferences; import org.openstreetmap.josm.plugins.graphview.plugin.preferences.InternalRuleset; /** * A routing graph visualization tool for JOSM */ public class GraphViewPlugin extends Plugin implements LayerChangeListener, Observer { private static final Collection<RoadPropertyType<?>> PROPERTIES; static { PROPERTIES = new LinkedList<>(); PROPERTIES.add(new RoadIncline()); PROPERTIES.add(new RoadMaxaxleload()); PROPERTIES.add(new RoadMaxheight()); PROPERTIES.add(new RoadMaxlength()); PROPERTIES.add(new RoadMaxspeed()); PROPERTIES.add(new RoadMaxweight()); PROPERTIES.add(new RoadMaxwidth()); PROPERTIES.add(new RoadMinspeed()); PROPERTIES.add(new RoadSurface()); PROPERTIES.add(new RoadTracktype()); PROPERTIES.add(new RoadWidth()); } private final GraphViewPreferences preferences; private JOSMTransitionStructure transitionStructure; private GraphViewLayer graphViewLayer; /** creates the plugin */ public GraphViewPlugin(PluginInformation info) { super(info); preferences = GraphViewPreferences.getInstance(); this.preferences.addObserver(this); } /** allows creation/update of GraphViewLayer */ public void createGraphViewLayer() { try { if (graphViewLayer != null) { AccessRuleset accessRuleset = getAccessRuleset(); if (accessRuleset == null) { JOptionPane.showMessageDialog(Main.parent, tr("No ruleset has been selected!"), tr("No ruleset"), JOptionPane.ERROR_MESSAGE); } else { transitionStructure.setAccessParametersAndRuleset(preferences.getCurrentParameterBookmark(), accessRuleset); transitionStructure.forceUpdate(); } } else { AccessRuleset accessRuleset = getAccessRuleset(); if (accessRuleset == null) { JOptionPane.showMessageDialog(Main.parent, tr("No ruleset has been selected!"), tr("No ruleset"), JOptionPane.ERROR_MESSAGE); } else { transitionStructure = new JOSMTransitionStructure( preferences.getCurrentParameterBookmark(), accessRuleset, PROPERTIES); WayGraph graph = new TSBasedWayGraph(transitionStructure); graphViewLayer = new GraphViewLayer(); graphViewLayer.setWayGraph(graph); graphViewLayer.setColorScheme(preferences.getCurrentColorScheme()); graphViewLayer.setArrowheadPlacement(preferences.getArrowheadPlacement()); graphViewLayer.setNodePositioner(new DefaultNodePositioner()); Main.getLayerManager().addLayer(graphViewLayer); } } } catch (AccessRulesetSyntaxException e) { JOptionPane.showMessageDialog(Main.parent, tr("Syntax exception in access ruleset:\n{0}", e)); Main.error(e); } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(Main.parent, tr("File not found:\n{0}", e)); Main.error(e); } catch (IOException e) { JOptionPane.showMessageDialog(Main.parent, tr("Problem when accessing a file:\n{0}", e)); Main.error(e); } } /** allows update of GraphViewLayer */ public void updateGraphViewLayer() { try { if (graphViewLayer != null) { AccessRuleset accessRuleset = getAccessRuleset(); if (accessRuleset == null) { JOptionPane.showMessageDialog(Main.parent, tr("No ruleset has been selected!"), tr("No ruleset"), JOptionPane.ERROR_MESSAGE); } else { transitionStructure.setAccessParametersAndRuleset( preferences.getCurrentParameterBookmark(), accessRuleset); transitionStructure.forceUpdate(); } } } catch (AccessRulesetSyntaxException e) { JOptionPane.showMessageDialog(Main.parent, tr("Syntax exception in access ruleset:\n{0}", e)); Main.error(e); } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(Main.parent, tr("File not found:\n", e)); Main.error(e); } catch (IOException e) { JOptionPane.showMessageDialog(Main.parent, tr("Problem when accessing a file:\n{0}", e)); Main.error(e); } } /** repaints the GraphViewLayer without recalculating the graph (visual update) */ public void repaintGraphViewLayer() { if (graphViewLayer != null) { graphViewLayer.invalidate(); } } /** * @return ruleset read from a source as specified by preferences, null if the preferences * don't specify a ruleset source */ private AccessRuleset getAccessRuleset() throws AccessRulesetSyntaxException, IOException, FileNotFoundException { InputStream rulesetInputStream; if (preferences.getUseInternalRulesets()) { InternalRuleset ruleset = preferences.getCurrentInternalRuleset(); if (ruleset == null) { return null; } ClassLoader classLoader = this.getClass().getClassLoader(); URL rulesetURL = classLoader.getResource(ruleset.getResourceName()); if (rulesetURL != null) { rulesetInputStream = rulesetURL.openStream(); } else { throw new FileNotFoundException(tr("Couldn''t find built-in ruleset {0}", ruleset)); } } else { File rulesetFile = preferences.getCurrentRulesetFile(); if (rulesetFile == null) { return null; } rulesetInputStream = new FileInputStream(rulesetFile); } return AccessRulesetReader.readAccessRuleset(rulesetInputStream); } @Override public PreferenceSetting getPreferenceSetting() { return new GraphViewPreferenceEditor(); } @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { if (newFrame != null) { if (oldFrame == null) { final GraphViewDialog laneDialog = new GraphViewDialog(this); newFrame.addToggleDialog(laneDialog); } Main.getLayerManager().addLayerChangeListener(this); } else { Main.getLayerManager().removeLayerChangeListener(this); } } @Override public void layerRemoving(LayerRemoveEvent e) { if (e.getRemovedLayer() == graphViewLayer) { graphViewLayer = null; } else if (e.getRemovedLayer() == Main.getLayerManager().getEditLayer()) { //data layer removed if (graphViewLayer != null) { Main.getLayerManager().removeLayer(graphViewLayer); graphViewLayer = null; } } } @Override public void layerOrderChanged(LayerOrderChangeEvent e) { //do nothing } @Override public void layerAdded(LayerAddEvent e) { //do nothing } @Override public void update(Observable arg0, Object arg1) { if (arg0 == preferences && graphViewLayer != null) { graphViewLayer.setColorScheme(preferences.getCurrentColorScheme()); graphViewLayer.setArrowheadPlacement(preferences.getArrowheadPlacement()); } } }