source: osm/applications/editors/josm/plugins/NanoLog/src/nanolog/NanoLogLayer.java@ 30701

Last change on this file since 30701 was 30701, checked in by donvip, 11 years ago

[josm_plugins] fix various compilation warnings

File size: 11.7 KB
Line 
1package nanolog;
2
3import java.awt.*;
4import java.awt.event.*;
5import java.io.*;
6import java.text.ParseException;
7import java.text.SimpleDateFormat;
8import java.util.*;
9import java.util.List;
10import java.util.regex.*;
11import javax.swing.*;
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.actions.*;
14import org.openstreetmap.josm.data.Bounds;
15import org.openstreetmap.josm.data.coor.EastNorth;
16import org.openstreetmap.josm.data.coor.LatLon;
17import org.openstreetmap.josm.data.gpx.WayPoint;
18import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
19import org.openstreetmap.josm.gui.MapView;
20import org.openstreetmap.josm.gui.dialogs.*;
21import org.openstreetmap.josm.gui.layer.*;
22import static org.openstreetmap.josm.tools.I18n.tr;
23import org.openstreetmap.josm.tools.ImageProvider;
24
25/**
26 * NanoLog layer: a set of points that can be georeferenced.
27 *
28 * @author zverik
29 */
30public class NanoLogLayer extends Layer implements JumpToMarkerActions.JumpToMarkerLayer {
31
32 private List<NanoLogEntry> log;
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 }
52
53 public NanoLogLayer( File file ) throws IOException {
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);
77 }
78
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");
82 List<NanoLogEntry> result = new ArrayList<NanoLogEntry>();
83 BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
84 while( r.ready() ) {
85 String line = r.readLine();
86 if( line != null ) {
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 }
114 }
115 }
116 r.close();
117 return result;
118 }
119
120 @Override
121 public void paint( Graphics2D g, MapView mv, Bounds box ) {
122 // todo
123 for( int i = 0; i < log.size(); i++ ) {
124 NanoLogEntry entry = log.get(i);
125 int radius = 4;
126 if( entry.getPos() != null ) {
127 Point p = mv.getPoint(entry.getPos());
128 g.setColor(selectedEntry == i ? Color.red : Color.yellow);
129 g.fillOval(p.x - radius, p.y - radius, radius * 2, radius * 2);
130 }
131 }
132 }
133
134 @Override
135 public Icon getIcon() {
136 return ImageProvider.get("nanolog.png");
137 }
138
139 @Override
140 public String getToolTipText() {
141 return tr("NanoLog of {0} entries", log.size());
142 }
143
144 @Override
145 public void mergeFrom( Layer from ) {
146 // todo
147 }
148
149 @Override
150 public boolean isMergable( Layer other ) {
151 return other instanceof NanoLogLayer;
152 }
153
154 @Override
155 public void visitBoundingBox( BoundingXYVisitor v ) {
156 for( NanoLogEntry entry : log )
157 v.visit(entry.getPos());
158 }
159
160 @Override
161 public Object getInfoComponent() {
162 StringBuilder b = new StringBuilder();
163 int cnt = 0;
164 for( NanoLogEntry e : log )
165 if( e.getPos() != null )
166 cnt++;
167 b.append(tr("NanoLog of {0} lines, {1} of them with coordinates.", log.size(), cnt));
168 return b.toString();
169 }
170
171 @Override
172 public Action[] getMenuEntries() {
173 return new Action[] {
174 LayerListDialog.getInstance().createShowHideLayerAction(),
175 LayerListDialog.getInstance().createDeleteLayerAction(),
176 new RenameLayerAction(null, this),
177 SeparatorLayerAction.INSTANCE,
178 new CorrelateEntries(true),
179 new CorrelateEntries(false),
180 new SaveLayer(),
181 SeparatorLayerAction.INSTANCE,
182 new LayerListPopup.InfoAction(this)
183 };
184 }
185
186 @Override
187 public void jumpToNextMarker() {
188 selectedEntry++;
189 if( selectedEntry < 0 )
190 selectedEntry = 0;
191 else if( selectedEntry >= log.size() )
192 selectedEntry = log.size() - 1;
193 Main.map.repaint();
194 }
195
196 @Override
197 public void jumpToPreviousMarker() {
198 selectedEntry--;
199 if( selectedEntry < 0 )
200 selectedEntry = 0;
201 else if( selectedEntry >= log.size() )
202 selectedEntry = log.size() - 1;
203 Main.map.repaint();
204 }
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( boolean toZero ) {
308 super(toZero ? tr("Correlate with GPX...") : tr("Put on GPX..."), "nanolog/correlate", tr("Correlate entries with GPS trace"), null, false);
309 this.toZero = toZero;
310 }
311
312 @Override
313 public void actionPerformed( ActionEvent e ) {
314 // 1. Select GPX trace or display message to load one
315 // (better yet, disable when no GPX traces)
316 GpxLayer layer = GPXChooser.chooseLayer();
317 // 2. Correlate by default, sticking by date
318 // (if does not match, shift so hours-minutes stay)
319 if( layer != null ) {
320 long offset = toZero ? 0 : Correlator.crudeMatch(log, layer.data);
321 Correlator.revertPos(log);
322 Correlator.correlate(log, layer.data, offset);
323 fireMarkersChanged();
324 Main.map.mapView.repaint();
325 }
326 // 3. Show non-modal (?) window with a slider and a text input
327 // (todo: better slider, like in blender)
328 }
329 }
330
331 private class SaveLayer extends JosmAction {
332
333 public SaveLayer() {
334 super(tr("Save layer..."), "nanolog/save", tr("Save NanoLog layer"), null, false);
335 }
336
337 @Override
338 public void actionPerformed( ActionEvent e ) {
339 // todo
340 JOptionPane.showMessageDialog(Main.parent, "Sorry, no saving yet", "NanoLog", JOptionPane.ERROR_MESSAGE);
341 }
342 }
343
344 public static interface NanoLogLayerListener {
345 void markersUpdated( NanoLogLayer layer );
346 void markerActivated( NanoLogLayer layer, NanoLogEntry entry );
347 }
348}
Note: See TracBrowser for help on using the repository browser.