Changeset 30491 in osm for applications/editors/josm/plugins/NanoLog/src/nanolog/NanoLogLayer.java
- Timestamp:
- 2014-06-10T00:04:18+02:00 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/NanoLog/src/nanolog/NanoLogLayer.java
r27939 r30491 1 1 package nanolog; 2 2 3 import java.awt.Color; 4 import java.awt.Graphics2D; 5 import java.awt.Point; 6 import java.awt.Rectangle; 7 import java.awt.event.ActionEvent; 8 import java.beans.PropertyChangeListener; 3 import java.awt.*; 4 import java.awt.event.*; 9 5 import java.io.*; 10 import java.util.ArrayList; 6 import java.text.ParseException; 7 import java.text.SimpleDateFormat; 8 import java.util.*; 11 9 import java.util.List; 12 import javax.swing.AbstractAction; 13 import javax.swing.Action; 14 import javax.swing.Icon; 10 import java.util.regex.*; 11 import javax.swing.*; 15 12 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.actions.RenameLayerAction; 17 import org.openstreetmap.josm.actions.SaveAction; 13 import org.openstreetmap.josm.actions.*; 18 14 import org.openstreetmap.josm.data.Bounds; 15 import org.openstreetmap.josm.data.coor.EastNorth; 16 import org.openstreetmap.josm.data.coor.LatLon; 17 import org.openstreetmap.josm.data.gpx.WayPoint; 19 18 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 20 19 import org.openstreetmap.josm.gui.MapView; 21 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 22 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 23 import org.openstreetmap.josm.gui.layer.JumpToMarkerActions; 24 import org.openstreetmap.josm.gui.layer.Layer; 20 import org.openstreetmap.josm.gui.dialogs.*; 21 import org.openstreetmap.josm.gui.layer.*; 25 22 import static org.openstreetmap.josm.tools.I18n.tr; 26 import static org.openstreetmap.josm.tools.I18n.trn;27 23 import org.openstreetmap.josm.tools.ImageProvider; 28 24 29 25 /** 26 * NanoLog layer: a set of points that can be georeferenced. 30 27 * 31 28 * @author zverik … … 35 32 private List<NanoLogEntry> log; 36 33 private int selectedEntry; 34 private final Set<NanoLogLayerListener> listeners = new HashSet<NanoLogLayerListener>(); 35 private NLLMouseAdapter mouseListener; 36 37 public NanoLogLayer( List<NanoLogEntry> entries ) { 38 super(tr("NanoLog")); 39 log = new ArrayList<NanoLogEntry>(entries); 40 selectedEntry = -1; 41 mouseListener = new NLLMouseAdapter(); 42 Main.map.mapView.addMouseListener(mouseListener); 43 Main.map.mapView.addMouseMotionListener(mouseListener); 44 } 45 46 @Override 47 public void destroy() { 48 Main.map.mapView.removeMouseListener(mouseListener); 49 Main.map.mapView.removeMouseMotionListener(mouseListener); 50 super.destroy(); 51 } 37 52 38 53 public NanoLogLayer( File file ) throws IOException { 39 super(tr("NanoLog")); 40 log = readNanoLog(file); 41 selectedEntry = -1; 54 this(readNanoLog(file)); 55 } 56 57 public void addListener( NanoLogLayerListener listener ) { 58 listeners.add(listener); 59 } 60 61 public void removeListener( NanoLogLayerListener listener ) { 62 listeners.remove(listener); 63 } 64 65 protected void fireMarkersChanged() { 66 for( NanoLogLayerListener listener : listeners ) 67 listener.markersUpdated(this); 68 } 69 70 protected void fireMarkerSelected() { 71 for( NanoLogLayerListener listener : listeners ) 72 listener.markerActivated(this, selectedEntry < 0 ? null : log.get(selectedEntry)); 73 } 74 75 public List<NanoLogEntry> getEntries() { 76 return Collections.unmodifiableList(log); 42 77 } 43 78 44 79 public static List<NanoLogEntry> readNanoLog( File file ) throws IOException { 80 final Pattern NANOLOG_LINE = Pattern.compile("(.+?)\\t(.+?)(?:\\s*\\{\\{(-?\\d+\\.\\d+),\\s*(-?\\d+\\.\\d+)(?:,\\s*(\\d+))?\\}\\})?"); 81 final SimpleDateFormat fmt = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SS"); 45 82 List<NanoLogEntry> result = new ArrayList<NanoLogEntry>(); 46 83 BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8")); … … 48 85 String line = r.readLine(); 49 86 if( line != null ) { 50 // parse it 87 Matcher m = NANOLOG_LINE.matcher(line); 88 if( m.matches() ) { 89 String time = m.group(1); 90 String message = m.group(2); 91 String lat = m.group(3); 92 String lon = m.group(4); 93 String dir = m.group(5); 94 Date timeDate = null; 95 try { 96 timeDate = fmt.parse(time); 97 } catch( ParseException e ) { 98 } 99 if( message == null || message.length() == 0 || timeDate == null ) 100 continue; 101 LatLon pos = null; 102 Integer direction = null; 103 if( lat != null && lon != null ) { 104 try { 105 pos = new LatLon(Double.parseDouble(lat), Double.parseDouble(lon)); 106 direction = new Integer(dir); 107 } catch( NumberFormatException e ) { 108 // well... 109 } 110 } 111 NanoLogEntry entry = new NanoLogEntry(timeDate, message, pos, direction); 112 result.add(entry); 113 } 51 114 } 52 115 } … … 58 121 public void paint( Graphics2D g, MapView mv, Bounds box ) { 59 122 // todo 60 int radius = 4; 61 int width = Main.map.mapView.getWidth(); 62 int height = Main.map.mapView.getHeight(); 63 Rectangle clip = g.getClipBounds(); 64 for( NanoLogEntry entry : log ) { 123 for( int i = 0; i < log.size(); i++ ) { 124 NanoLogEntry entry = log.get(i); 125 int radius = 4; 65 126 if( entry.getPos() != null ) { 66 127 Point p = mv.getPoint(entry.getPos()); 67 g.setColor( Color.green);128 g.setColor(selectedEntry == i ? Color.red : Color.yellow); 68 129 g.fillOval(p.x - radius, p.y - radius, radius * 2, radius * 2); 69 130 } 70 }71 if( selectedEntry >= 0 && selectedEntry < log.size() ) {72 Point p = mv.getPoint(log.get(selectedEntry).getPos());73 g.setColor(Color.red);74 g.fillOval(p.x - radius, p.y - radius, radius * 2, radius * 2);75 131 } 76 132 } … … 120 176 new RenameLayerAction(null, this), 121 177 SeparatorLayerAction.INSTANCE, 122 new CorrelateEntries(), 178 new CorrelateEntries(true), 179 new CorrelateEntries(false), 123 180 new SaveLayer(), 124 181 SeparatorLayerAction.INSTANCE, … … 127 184 } 128 185 186 @Override 129 187 public void jumpToNextMarker() { 130 188 selectedEntry++; … … 136 194 } 137 195 196 @Override 138 197 public void jumpToPreviousMarker() { 139 198 selectedEntry--; … … 144 203 Main.map.repaint(); 145 204 } 146 147 private class CorrelateEntries extends AbstractAction { 148 205 206 protected void setSelected( int i ) { 207 int newSelected = i >= 0 && i < log.size() ? i : -1; 208 if( newSelected != selectedEntry ) { 209 // System.out.println("selected: " + log.get(newSelected).getMessage()); 210 selectedEntry = newSelected; 211 fireMarkerSelected(); 212 Main.map.mapView.repaint(); 213 } 214 } 215 216 public void setSelected( NanoLogEntry entry ) { 217 if( entry == null ) 218 setSelected(-1); 219 else { 220 for( int i = 0; i < log.size(); i++ ) { 221 if( entry.equals(log.get(i)) ) { 222 setSelected(i); 223 break; 224 } 225 } 226 } 227 } 228 229 private class NLLMouseAdapter extends MouseAdapter { 230 private int dragging; 231 232 public int nearestEntry( MouseEvent e ) { 233 LatLon ll = Main.map.mapView.getLatLon(e.getX(), e.getY()); 234 int radius = 8; 235 if( ll != null ) { 236 LatLon lld = Main.map.mapView.getLatLon(e.getX() + radius, e.getY() + radius); 237 double distance = Math.max(lld.lat() - ll.lat(), lld.lon() - ll.lon()); 238 boolean selectedIsSelected = false; 239 int newSelected = -1; 240 for( int i = 0; i < log.size(); i++ ) { 241 if( log.get(i).getPos() != null && log.get(i).getPos().distance(ll) < distance ) { 242 newSelected = i; 243 if( i == selectedEntry ) 244 selectedIsSelected = true; 245 } 246 } 247 if( newSelected >= 0 ) 248 return selectedIsSelected ? selectedEntry : newSelected; 249 } 250 return -1; 251 } 252 253 @Override 254 public void mouseMoved( MouseEvent e ) { 255 int nearest = nearestEntry(e); 256 if( nearest > 0 ) 257 setSelected(nearest); 258 } 259 260 @Override 261 public void mouseDragged( MouseEvent e ) { 262 doDrag(e); 263 } 264 265 @Override 266 public void mouseReleased( MouseEvent e ) { 267 if( dragging > 0 ) { 268 dragging = 0; 269 } 270 } 271 272 @Override 273 public void mousePressed( MouseEvent e ) { 274 int nearest = nearestEntry(e); 275 if( nearest > 0 && Main.map.mapView.getActiveLayer() == NanoLogLayer.this ) { 276 dragging = nearest; 277 doDrag(e); 278 } 279 } 280 281 private void doDrag( MouseEvent e ) { 282 if( dragging > 0 ) 283 dragTo(dragging, e.getX(), e.getY()); 284 } 285 } 286 287 protected void dragTo( int entry, int x, int y ) { 288 GpxLayer gpx = GPXChooser.topLayer(); 289 if( gpx == null ) 290 return; 291 EastNorth eastNorth = Main.map.mapView.getEastNorth(x, y); 292 double tolerance = eastNorth.distance(Main.map.mapView.getEastNorth(x + 300, y)); 293 WayPoint wp = gpx.data.nearestPointOnTrack(eastNorth, tolerance); 294 if( wp == null ) 295 return; 296 long newTime = Correlator.getGpxDate(gpx.data, wp.getCoor()); 297 if( newTime <= 0 ) 298 return; 299 Correlator.revertPos(log); 300 Correlator.correlate(log, gpx.data, log.get(entry).getTime().getTime() - newTime); 301 Main.map.mapView.repaint(); 302 } 303 304 private class CorrelateEntries extends JosmAction { 305 private boolean toZero; 306 307 public CorrelateEntries() { 308 this(false); 309 } 310 311 public CorrelateEntries( boolean toZero ) { 312 super(toZero ? tr("Correlate with GPX...") : tr("Put on GPX..."), "nanolog/correlate", tr("Correlate entries with GPS trace"), null, false); 313 this.toZero = toZero; 314 } 315 316 @Override 317 public void actionPerformed( ActionEvent e ) { 318 // 1. Select GPX trace or display message to load one 319 // (better yet, disable when no GPX traces) 320 GpxLayer layer = GPXChooser.chooseLayer(); 321 // 2. Correlate by default, sticking by date 322 // (if does not match, shift so hours-minutes stay) 323 if( layer != null ) { 324 long offset = toZero ? 0 : Correlator.crudeMatch(log, layer.data); 325 Correlator.revertPos(log); 326 Correlator.correlate(log, layer.data, offset); 327 fireMarkersChanged(); 328 Main.map.mapView.repaint(); 329 } 330 // 3. Show non-modal (?) window with a slider and a text input 331 // (todo: better slider, like in blender) 332 } 333 } 334 335 private class SaveLayer extends JosmAction { 336 337 public SaveLayer() { 338 super(tr("Save layer..."), "nanolog/save", tr("Save NanoLog layer"), null, false); 339 } 340 341 @Override 149 342 public void actionPerformed( ActionEvent e ) { 150 343 // todo 151 } 152 } 153 154 private class SaveLayer extends AbstractAction { 155 156 public void actionPerformed( ActionEvent e ) { 157 // todo 158 } 344 JOptionPane.showMessageDialog(Main.parent, "Sorry, no saving yet", "NanoLog", JOptionPane.ERROR_MESSAGE); 345 } 346 } 347 348 public static interface NanoLogLayerListener { 349 void markersUpdated( NanoLogLayer layer ); 350 void markerActivated( NanoLogLayer layer, NanoLogEntry entry ); 159 351 } 160 352 }
Note:
See TracChangeset
for help on using the changeset viewer.
