// License: GPL. For details, see LICENSE file. package com.innovant.josm.plugin.routing; import static org.openstreetmap.josm.tools.I18n.tr; import java.io.File; import java.util.ArrayList; import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent; import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter; import org.openstreetmap.josm.data.osm.event.DatasetEventManager; import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode; import org.openstreetmap.josm.gui.IconToggleButton; import org.openstreetmap.josm.gui.MapFrame; import org.openstreetmap.josm.gui.layer.Layer; 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.layer.OsmDataLayer; import org.openstreetmap.josm.gui.preferences.PreferenceSetting; import org.openstreetmap.josm.plugins.Plugin; import org.openstreetmap.josm.plugins.PluginInformation; import com.innovant.josm.plugin.routing.actions.AddRouteNodeAction; import com.innovant.josm.plugin.routing.actions.MoveRouteNodeAction; import com.innovant.josm.plugin.routing.actions.RemoveRouteNodeAction; import com.innovant.josm.plugin.routing.gui.RoutingDialog; import com.innovant.josm.plugin.routing.gui.RoutingMenu; import com.innovant.josm.plugin.routing.gui.RoutingPreferenceDialog; /** * The main class of the routing plugin * @author juangui * @author Jose Vidal * @author cdaller * * @version 0.3 */ public class RoutingPlugin extends Plugin implements LayerChangeListener, DataSetListenerAdapter.Listener { /** * Logger */ static Logger logger = Logger.getLogger(RoutingPlugin.class); /** * The list of routing layers */ private final ArrayList<RoutingLayer> layers; /** * The side dialog where nodes are listed */ private RoutingDialog routingDialog; /** * Preferences Settings Dialog. */ private final PreferenceSetting preferenceSettings; /** * MapMode for adding route nodes. * We use this field to enable or disable the mode automatically. */ private AddRouteNodeAction addRouteNodeAction; /** * MapMode for removing route nodes. * We use this field to enable or disable the mode automatically. */ private RemoveRouteNodeAction removeRouteNodeAction; /** * MapMode for moving route nodes. * We use this field to enable or disable the mode automatically. */ private MoveRouteNodeAction moveRouteNodeAction; /** * IconToggleButton for adding route nodes, we use this field to show or hide the button. */ private IconToggleButton addRouteNodeButton; /** * IconToggleButton for removing route nodes, we use this field to show or hide the button. */ private IconToggleButton removeRouteNodeButton; /** * IconToggleButton for moving route nodes, we use this field to show or hide the button. */ private IconToggleButton moveRouteNodeButton; /** * IconToggleButton for moving route nodes, we use this field to show or hide the button. */ private final RoutingMenu menu; /** * Reference for the plugin class (as if it were a singleton) */ private static RoutingPlugin plugin; private final DataSetListenerAdapter datasetAdapter; /** * Default Constructor */ public RoutingPlugin(PluginInformation info) { super(info); datasetAdapter = new DataSetListenerAdapter(this); plugin = this; // Assign reference to the plugin class File log4jConfigFile = new java.io.File("log4j.xml"); if (log4jConfigFile.exists()) { DOMConfigurator.configure(log4jConfigFile.getPath()); } else { System.err.println("Routing plugin warning: log4j configuration not found"); } logger.debug("Loading routing plugin..."); preferenceSettings = new RoutingPreferenceDialog(); // Initialize layers list layers = new ArrayList<>(); // Add menu menu = new RoutingMenu(); // Register this class as LayerChangeListener Main.getLayerManager().addLayerChangeListener(this); DatasetEventManager.getInstance().addDatasetListener(datasetAdapter, FireMode.IN_EDT_CONSOLIDATED); logger.debug("Finished loading plugin"); } /** * Provides static access to the plugin instance, to enable access to the plugin methods * @return the instance of the plugin */ public static RoutingPlugin getInstance() { return plugin; } /** * Get the routing side dialog * @return The instance of the routing side dialog */ public RoutingDialog getRoutingDialog() { return routingDialog; } public void addLayer() { OsmDataLayer osmLayer = Main.getLayerManager().getEditLayer(); if (osmLayer != null) { RoutingLayer layer = new RoutingLayer(tr("Routing") + " [" + osmLayer.getName() + "]", osmLayer); layers.add(layer); Main.getLayerManager().addLayer(layer); } } @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { if (newFrame != null) { // Create plugin map modes addRouteNodeAction = new AddRouteNodeAction(newFrame); removeRouteNodeAction = new RemoveRouteNodeAction(newFrame); moveRouteNodeAction = new MoveRouteNodeAction(newFrame); // Create plugin buttons and add them to the toolbar addRouteNodeButton = new IconToggleButton(addRouteNodeAction); removeRouteNodeButton = new IconToggleButton(removeRouteNodeAction); moveRouteNodeButton = new IconToggleButton(moveRouteNodeAction); addRouteNodeButton.setAutoHideDisabledButton(true); removeRouteNodeButton.setAutoHideDisabledButton(true); moveRouteNodeButton.setAutoHideDisabledButton(true); newFrame.addMapMode(addRouteNodeButton); newFrame.addMapMode(removeRouteNodeButton); newFrame.addMapMode(moveRouteNodeButton); // Enable menu menu.enableStartItem(); newFrame.addToggleDialog(routingDialog = new RoutingDialog()); } else { addRouteNodeAction = null; removeRouteNodeAction = null; moveRouteNodeAction = null; addRouteNodeButton = null; removeRouteNodeButton = null; moveRouteNodeButton = null; routingDialog = null; } } public void activeLayerChange(Layer oldLayer, Layer newLayer) { if (newLayer instanceof RoutingLayer) { /* show Routing toolbar and dialog window */ menu.enableRestOfItems(); if (routingDialog != null) { routingDialog.showDialog(); routingDialog.refresh(); } } else { /* hide Routing toolbar and dialog window */ menu.disableRestOfItems(); if (routingDialog != null) { routingDialog.hideDialog(); } } } @Override public void layerOrderChanged(LayerOrderChangeEvent e) { // Do nothing } @Override public void layerAdded(LayerAddEvent evt) { Layer newLayer = evt.getAddedLayer(); // Add button(s) to the tool bar when the routing layer is added if (newLayer instanceof RoutingLayer) { menu.enableRestOfItems(); // Set layer on top and select layer, also refresh toggleDialog to reflect selection Main.map.mapView.moveLayer(newLayer, 0); logger.debug("Added routing layer."); } } @Override public void layerRemoving(LayerRemoveEvent evt) { Layer oldLayer = evt.getRemovedLayer(); if ((oldLayer instanceof RoutingLayer) & (layers.size() == 1)) { // Remove button(s) from the tool bar when the last routing layer is removed addRouteNodeButton.setVisible(false); removeRouteNodeButton.setVisible(false); moveRouteNodeButton.setVisible(false); menu.disableRestOfItems(); layers.remove(oldLayer); logger.debug("Removed routing layer."); } else if (oldLayer instanceof OsmDataLayer) { // Remove all associated routing layers // Convert to Array to prevent ConcurrentModificationException when removing layers from ArrayList // FIXME: can't remove associated routing layers without triggering exceptions in some cases RoutingLayer[] layersArray = layers.toArray(new RoutingLayer[0]); for (int i = 0; i < layersArray.length; i++) { if (layersArray[i].getDataLayer().equals(oldLayer)) { try { // Remove layer Main.getLayerManager().removeLayer(layersArray[i]); } catch (IllegalArgumentException e) { Main.error(e); } } } } // Reload RoutingDialog table model if (routingDialog != null) { routingDialog.refresh(); } } @Override public void processDatasetEvent(AbstractDatasetChangedEvent event){ } @Override public PreferenceSetting getPreferenceSetting() { return preferenceSettings; } }