package org.openstreetmap.josm.plugins.routes; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Stroke; import java.util.ArrayList; import java.util.List; import javax.swing.Action; import javax.swing.Icon; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.data.osm.RelationMember; import org.openstreetmap.josm.data.osm.Way; 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.data.osm.visitor.BoundingXYVisitor; import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.plugins.routes.paint.NarrowLinePainter; import org.openstreetmap.josm.plugins.routes.paint.PathPainter; import org.openstreetmap.josm.plugins.routes.paint.WideLinePainter; import org.openstreetmap.josm.plugins.routes.xml.RoutesXMLLayer; import org.openstreetmap.josm.plugins.routes.xml.RoutesXMLRoute; import org.openstreetmap.josm.tools.ColorHelper; import org.openstreetmap.josm.tools.ImageProvider; public class RouteLayer extends Layer implements DataSetListenerAdapter.Listener { private final PathPainter pathPainter; private final PathBuilder pathBuilder = new PathBuilder(); private final List<RouteDefinition> routes = new ArrayList<>(); private volatile boolean datasetChanged = true; public RouteLayer(RoutesXMLLayer xmlLayer) { super(xmlLayer.getName()); int index = 0; for (RoutesXMLRoute route:xmlLayer.getRoute()) { if (route.isEnabled()) { Color color = ColorHelper.html2color(route.getColor()); if (color == null) { color = Color.RED; System.err.printf("Routes plugin - unable to convert color (%s)\n", route.getColor()); } routes.add(new RouteDefinition(index++, color, route.getPattern())); } } if ("wide".equals(Main.pref.get("routes.painter"))) { pathPainter = new WideLinePainter(this); } else { pathPainter = new NarrowLinePainter(this); } DatasetEventManager.getInstance().addDatasetListener(new DataSetListenerAdapter(this), FireMode.IMMEDIATELY); } @Override public Icon getIcon() { return ImageProvider.get("layer", "osmdata_small"); } @Override public Object getInfoComponent() { return null; } @Override public Action[] getMenuEntries() { return new Action[0]; } @Override public String getToolTipText() { return "Hiking routes"; } @Override public boolean isMergable(Layer other) { return false; } @Override public void mergeFrom(Layer from) { // Merging is not supported } private void addRelation(Relation relation, RouteDefinition route) { for (RelationMember member:relation.getMembers()) { if (member.getMember() instanceof Way) { Way way = (Way)member.getMember(); pathBuilder.addWay(way, route); } } } @Override public void paint(Graphics2D g, MapView mv, Bounds bounds) { DataSet dataset = Main.getLayerManager().getEditDataSet(); if (dataset == null) { return; } if (datasetChanged) { datasetChanged = false; pathBuilder.clear(); for (Relation relation:dataset.getRelations()) { for (RouteDefinition route:routes) { if (route.matches(relation)) { addRelation(relation, route); } } } for (Way way:dataset.getWays()) { for (RouteDefinition route:routes) { if (route.matches(way)) { pathBuilder.addWay(way, route); } } } } Stroke stroke = g.getStroke(); Color color = g.getColor(); for (ConvertedWay way:pathBuilder.getConvertedWays()) { pathPainter.drawWay(way, mv, g); } g.setStroke(stroke); g.setColor(color); } @Override public void visitBoundingBox(BoundingXYVisitor v) { } public List<RouteDefinition> getRoutes() { return routes; } public void processDatasetEvent(AbstractDatasetChangedEvent event) { datasetChanged = true; } @Override public synchronized void destroy() { /* layer is reused, don't destroy it at all */ } }