/* Copyright 2014 Malcolm Herring * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>. */ package scedit; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.Collection; import java.util.Map.Entry; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.SelectionChangedListener; 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.OsmPrimitiveType; 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.DataChangedEvent; import org.openstreetmap.josm.data.osm.event.DataSetListener; import org.openstreetmap.josm.data.osm.event.NodeMovedEvent; import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent; import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent; import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent; import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; import org.openstreetmap.josm.gui.layer.OsmDataLayer; import panels.PanelMain; import panels.PanelS57; import panels.ShowFrame; import s57.S57map; import s57.S57map.Feature; public class SCeditAction extends JosmAction implements ActiveLayerChangeListener, SelectionChangedListener { private static String title = tr("SeaChart Editor"); public static JFrame editFrame = null; public static ShowFrame showFrame = null; private boolean isOpen = false; public static PanelMain panelMain = null; public static PanelS57 panelS57 = null; public static S57map map = null; public DataSet data = null; private final DataSetListener dataSetListener = new DataSetListener() { @Override public void dataChanged(DataChangedEvent e) { makeMap(); } @Override public void nodeMoved(NodeMovedEvent e) { makeMap(); } @Override public void otherDatasetChange(AbstractDatasetChangedEvent e) { makeMap(); } @Override public void primitivesAdded(PrimitivesAddedEvent e) { makeMap(); } @Override public void primitivesRemoved(PrimitivesRemovedEvent e) { makeMap(); } @Override public void relationMembersChanged(RelationMembersChangedEvent e) { makeMap(); } @Override public void tagsChanged(TagsChangedEvent e) { makeMap(); } @Override public void wayNodesChanged(WayNodesChangedEvent e) { makeMap(); } }; public SCeditAction() { super(title, "SC", title, null, true); } @Override public void actionPerformed(ActionEvent arg0) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (!isOpen) createFrame(); else editFrame.toFront(); isOpen = true; } }); } protected void createFrame() { editFrame = new JFrame(title); editFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); editFrame.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent e) { closeDialog(); } }); editFrame.setSize(new Dimension(480, 480)); editFrame.setLocation(100, 200); editFrame.setResizable(true); editFrame.setAlwaysOnTop(true); editFrame.setVisible(true); panelMain = new PanelMain(); editFrame.add(panelMain); panelS57 = new PanelS57(); editFrame.add(panelS57); showFrame = new ShowFrame(tr("Seamark Inspector")); showFrame.setSize(new Dimension(300, 300)); showFrame.setLocation(50, 400); showFrame.setResizable(false); showFrame.setAlwaysOnTop(true); showFrame.setEnabled(true); showFrame.setVisible(false); Main.getLayerManager().addAndFireActiveLayerChangeListener(this); DataSet.addSelectionListener(this); } public void closeDialog() { if (isOpen) { Main.getLayerManager().removeActiveLayerChangeListener(this); editFrame.setVisible(false); editFrame.dispose(); data = null; map = null; } isOpen = false; } @Override public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { if (e.getPreviousEditLayer() != null) { e.getPreviousEditLayer().data.removeDataSetListener(dataSetListener); } OsmDataLayer newLayer = Main.getLayerManager().getEditLayer(); if (newLayer != null) { newLayer.data.addDataSetListener(dataSetListener); data = newLayer.data; makeMap(); } else { data = null; map = null; } } @Override public void selectionChanged(Collection<? extends OsmPrimitive> selection) { OsmPrimitive nextFeature = null; OsmPrimitive feature = null; showFrame.setVisible(false); panelMain.clearMark(); if (map != null) { for (OsmPrimitive osm : selection) { nextFeature = osm; if (selection.size() == 1) { if (nextFeature.compareTo(feature) != 0) { feature = nextFeature; Feature id = map.index.get(feature.getUniqueId()); if (id != null) { panelMain.parseMark(id); showFrame.setVisible(true); showFrame.showFeature(feature, map); } } } else { showFrame.setVisible(false); PanelMain.setStatus(tr("Select only one object"), Color.orange); } } if (nextFeature == null) { feature = null; panelMain.clearMark(); showFrame.setVisible(false); PanelMain.setStatus(tr("Select a map object"), Color.yellow); } } } void makeMap() { map = new S57map(true); if (data != null) { double minlat = 90; double maxlat = -90; double minlon = 180; double maxlon = -180; for (Bounds bounds : data.getDataSourceBounds()) { if (bounds.getMinLat() < minlat) { minlat = bounds.getMinLat(); } if (bounds.getMaxLat() > maxlat) { maxlat = bounds.getMaxLat(); } if (bounds.getMinLon() < minlon) { minlon = bounds.getMinLon(); } if (bounds.getMaxLon() > maxlon) { maxlon = bounds.getMaxLon(); } } map.addNode(1, maxlat, minlon); map.addNode(2, minlat, minlon); map.addNode(3, minlat, maxlon); map.addNode(4, maxlat, maxlon); map.bounds.minlat = Math.toRadians(minlat); map.bounds.maxlat = Math.toRadians(maxlat); map.bounds.minlon = Math.toRadians(minlon); map.bounds.maxlon = Math.toRadians(maxlon); for (Node node : data.getNodes()) { LatLon coor = node.getCoor(); if (coor != null) { map.addNode(node.getUniqueId(), coor.lat(), coor.lon()); for (Entry<String, String> entry : node.getKeys().entrySet()) { map.addTag(entry.getKey(), entry.getValue()); } map.tagsDone(node.getUniqueId()); } } for (Way way : data.getWays()) { if (way.getNodesCount() > 0) { map.addEdge(way.getUniqueId()); for (Node node : way.getNodes()) { map.addToEdge((node.getUniqueId())); } for (Entry<String, String> entry : way.getKeys().entrySet()) { map.addTag(entry.getKey(), entry.getValue()); } map.tagsDone(way.getUniqueId()); } } for (Relation rel : data.getRelations()) { if (rel.isMultipolygon() && (rel.getMembersCount() > 0)) { map.addArea(rel.getUniqueId()); for (RelationMember mem : rel.getMembers()) { if (mem.getType() == OsmPrimitiveType.WAY) map.addToArea(mem.getUniqueId(), (mem.getRole().equals("outer"))); } for (Entry<String, String> entry : rel.getKeys().entrySet()) { map.addTag(entry.getKey(), entry.getValue()); } map.tagsDone(rel.getUniqueId()); } } map.mapDone(); } } }