// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.osmarender; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.HashSet; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.gui.MainMenu; import org.openstreetmap.josm.gui.MapFrame; import org.openstreetmap.josm.gui.preferences.PreferenceSetting; import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane; import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting; import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting; import org.openstreetmap.josm.io.OsmWriter; import org.openstreetmap.josm.io.OsmWriterFactory; import org.openstreetmap.josm.plugins.Plugin; import org.openstreetmap.josm.plugins.PluginInformation; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.PlatformHookWindows; public class OsmarenderPlugin extends Plugin { private class Action extends JosmAction { public Action() { super(tr("Osmarender"), (String)null, tr("Osmarender"), null, true, "osmarender", true); } @Override public void actionPerformed(ActionEvent e) { DataSet ds = Main.getLayerManager().getEditDataSet(); if (ds == null) { return; } // get all stuff visible on screen LatLon bottomLeft = Main.map.mapView.getLatLon(0,Main.map.mapView.getHeight()); LatLon topRight = Main.map.mapView.getLatLon(Main.map.mapView.getWidth(), 0); Bounds b = new Bounds(bottomLeft, topRight); try { writeGenerated(b); } catch (IOException ex) { // how handle the exception? Main.error(ex); } String firefox = Main.pref.get("osmarender.firefox", "firefox"); try (OsmWriter w = OsmWriterFactory.createOsmWriter(new PrintWriter(new OutputStreamWriter( new FileOutputStream(getPluginDir()+File.separator+"data.osm"), "UTF-8")), false, "0.6")) { // write to plugin dir w.header(); // Write nodes, make list of ways and relations Set<OsmPrimitive> parents = new HashSet<>(); for (Node n : ds.getNodes()) { if (n.isUsable() && n.getCoor() != null && n.getCoor().isWithin(b)) { parents.addAll(n.getReferrers()); w.visit(n); } } // I'm not sure why (if) is this usefull for (OsmPrimitive p : new HashSet<>(parents)) { if (p instanceof Way) { for (Node n : ((Way) p).getNodes()) { if (n.getCoor() != null && n.getCoor().isWithin(b)) parents.add(n); } } } // Write ways for (OsmPrimitive p: parents) { if (p instanceof Way) { w.visit((Way)p); } } // Write relations (should be parent relation also written?) for (OsmPrimitive p: parents) { if (p instanceof Relation) { w.visit((Relation)p); } } w.footer(); w.close(); // get the exec line String argument; if (Main.platform instanceof PlatformHookWindows) argument = "file:///"+getPluginDir().replace('\\','/').replace(" ","%20")+File.separator+"generated.xml\""; else argument = getPluginDir()+File.separator+"generated.xml"; // launch up the viewer Runtime.getRuntime().exec(new String[]{firefox, argument}); } catch (IOException e1) { JOptionPane.showMessageDialog(Main.parent, tr("Firefox not found. Please set firefox executable in the Map Settings page of the preferences.")); } } } private JMenuItem osmarenderMenu; /** * Constructs a new {@code OsmarenderPlugin}. * @param info plugin info * @throws IOException if files cannot be copied */ public OsmarenderPlugin(PluginInformation info) throws IOException { super(info); osmarenderMenu = MainMenu.add(Main.main.menu.viewMenu, new Action()); osmarenderMenu.setVisible(false); // install the xsl and xml file copy("/osmarender.xsl", "osmarender.xsl"); copy("/osm-map-features.xml", "osm-map-features.xml"); } @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { if (oldFrame != null && newFrame == null) { // disable osmarenderMenu.setVisible(false); } else if (oldFrame == null && newFrame != null) { // enable osmarenderMenu.setVisible(true); } } @Override public PreferenceSetting getPreferenceSetting() { return new OsmarenderPreferenceSetting(); } private static class OsmarenderPreferenceSetting implements SubPreferenceSetting { private JTextField firefox = new JTextField(10); @Override public void addGui(PreferenceTabbedPane gui) { final JPanel panel = new JPanel(new GridBagLayout()); panel.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 )); panel.add(new JLabel(tr("Firefox executable")), GBC.std().insets(10,5,5,0)); panel.add(firefox, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); firefox.setText(Main.pref.get("osmarender.firefox")); gui.getMapPreference().getTabPane().addTab(tr("Osmarender"), panel); } @Override public boolean ok() { Main.pref.put("osmarender.firefox", firefox.getText()); return false; } @Override public boolean isExpert() { return false; } @Override public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) { return gui.getMapPreference(); } } private void writeGenerated(Bounds b) throws IOException { String boundsTag = "<bounds " + "minlat=\"" + b.getMin().lat() + "\" " + "maxlat=\"" + b.getMax().lat() + "\" " + "minlon=\"" + b.getMin().lon() + "\" " + "maxlon=\"" + b.getMax().lon() + "\" " + "/>"; try ( BufferedReader reader = new BufferedReader( new FileReader( getPluginDir() + File.separator + "osm-map-features.xml") ); PrintWriter writer = new PrintWriter( getPluginDir() + File.separator + "generated.xml", "UTF-8"); ) { // osm-map-features.xml contain two placemark // (bounds_mkr1 and bounds_mkr2). We write the bounds tag between the two String str; while( (str = reader.readLine()) != null ) { if(str.contains("<!--bounds_mkr1-->")) { writer.println(str); writer.println(" " + boundsTag); while(!str.contains("<!--bounds_mkr2-->")) { str = reader.readLine(); } writer.println(str); } else { writer.println(str); } } } } }