// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.canvec_helper; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.Color; import java.awt.Component; import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JMenu; import javax.swing.JMenuItem; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.dialogs.LayerListDialog; import org.openstreetmap.josm.gui.dialogs.LayerListPopup; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.io.CachedFile; // most of the layout was copied from the openstreetbugs plugin to get things started class CanvecLayer extends Layer { private Icon layerIcon = null; private int maxZoom = 4; final CanvecHelper plugin; private List<CanVecTile> tiles = new ArrayList<>(); List<CanVecTile> downloadable = new ArrayList<>(); List<CanVecTile> openable = new ArrayList<>(); CanvecLayer(String name, CanvecHelper self) { super(name); plugin = self; this.setBackgroundLayer(true); layerIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/images/layericon.png"))); long start = System.currentTimeMillis(); try ( InputStream index = new CachedFile("http://ftp2.cits.rncan.gc.ca/OSM/pub/ZippedOsm.txt").getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(index, StandardCharsets.UTF_8)); ) { Pattern p = Pattern.compile("(\\d\\d\\d)([A-Z]\\d\\d).*"); String line; int lastCell = -1; List<String> list = new ArrayList<>(); while ((line = br.readLine()) != null) { Matcher m = p.matcher(line); if (m.find()) { int cell = Integer.parseInt(m.group(1)); if (cell == lastCell) { list.add(m.group(0)); } else if (lastCell != -1) { CanVecTile tile = new CanVecTile(lastCell, "", 0, "", this, list); if (tile.isValid()) tiles.add(tile); list = new ArrayList<>(); list.add(m.group(0)); } lastCell = cell; } else if (!line.contains("Metadata.txt")) { Main.warn("bad line '" + line + "'\n"); } } CanVecTile tile = new CanVecTile(lastCell, "", 0, "", this, list); if (tile.isValid()) tiles.add(tile); if (Main.isDebugEnabled()) { long end = System.currentTimeMillis(); Main.debug((end-start)+"ms spent"); } } catch (IOException e) { Main.error("exception getting index"); Main.error(e); } } @Override public Action[] getMenuEntries() { return new Action[]{ LayerListDialog.getInstance().createShowHideLayerAction(), LayerListDialog.getInstance().createDeleteLayerAction(), SeparatorLayerAction.INSTANCE, new LayerListPopup.InfoAction(this), new MaxZoomAction(this), new DownloadCanvecAction(this), new OpenOsmAction(this)}; } private static final class MaxZoomAction extends AbstractAction implements LayerAction { private final CanvecLayer parent; private MaxZoomAction(CanvecLayer parent) { this.parent = parent; } @Override public void actionPerformed(ActionEvent e) { // Do nothing } @Override public boolean supportLayers(List<Layer> layers) { return false; } @Override public Component createMenuComponent() { JMenu maxZoomMenu = new JMenu("max zoom"); maxZoomMenu.add(new JMenuItem(new SetMaxZoom(parent, 1))); maxZoomMenu.add(new JMenuItem(new SetMaxZoom(parent, 2))); maxZoomMenu.add(new JMenuItem(new SetMaxZoom(parent, 3))); maxZoomMenu.add(new JMenuItem(new SetMaxZoom(parent, 4))); return maxZoomMenu; } } private static final class AllowDownload extends AbstractAction { private final CanVecTile tile; private AllowDownload(CanVecTile tile) { super(tile.tileid); this.tile = tile; } @Override public void actionPerformed(ActionEvent arg0) { tile.canDownload = true; } } private static final class OpenOsmAction extends AbstractAction implements LayerAction { private CanvecLayer layer; private OpenOsmAction(CanvecLayer layer) { this.layer = layer; } @Override public void actionPerformed(ActionEvent e) { // Do nothing } @Override public Component createMenuComponent() { JMenu openOsm = new JMenu("Open tile"); for (int i = 0; i < layer.openable.size(); i++) { openOsm.add(new JMenuItem(new DoOpenOsm(layer.openable.get(i)))); } return openOsm; } @Override public boolean supportLayers(List<Layer> layers) { return false; } } private static final class DoOpenOsm extends AbstractAction { private final CanVecTile tile; private DoOpenOsm(CanVecTile tile) { super(tile.tileid); this.tile = tile; } @Override public void actionPerformed(ActionEvent e) { tile.loadRawOsm(); } } private static final class DownloadCanvecAction extends AbstractAction implements LayerAction { private CanvecLayer parent; private DownloadCanvecAction(CanvecLayer parent) { this.parent = parent; } @Override public void actionPerformed(ActionEvent e) { // Do nothing } @Override public boolean supportLayers(List<Layer> layers) { return false; } @Override public Component createMenuComponent() { JMenu downloadCanvec = new JMenu("Download zip's"); for (int i = 0; i < parent.downloadable.size(); i++) { downloadCanvec.add(new JMenuItem(new AllowDownload(parent.downloadable.get(i)))); } return downloadCanvec; } } void setMaxZoom(int maxZoom) { this.maxZoom = maxZoom; } @Override public Object getInfoComponent() { return getToolTipText(); } @Override public String getToolTipText() { return tr("canvec tile helper"); } @Override public void visitBoundingBox(BoundingXYVisitor v) { // Do nothing } @Override public boolean isMergable(Layer other) { return false; } @Override public void mergeFrom(Layer from) { // Do nothing } @Override public Icon getIcon() { return layerIcon; } @Override public void paint(Graphics2D g, MapView mv, Bounds bounds) { downloadable = new ArrayList<>(); openable = new ArrayList<>(); // loop over each canvec tile in the db and check bounds.intersects(Bounds) g.setColor(Color.red); for (int i = 0; i < tiles.size(); i++) { CanVecTile tile = tiles.get(i); tile.paint(g, mv, bounds, maxZoom); } } }