Ignore:
Timestamp:
2014-06-10T00:04:18+02:00 (12 years ago)
Author:
zverik
Message:

wow, it works

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/NanoLog/src/nanolog/NanoLogLayer.java

    r27939 r30491  
    11package nanolog;
    22
    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;
     3import java.awt.*;
     4import java.awt.event.*;
    95import java.io.*;
    10 import java.util.ArrayList;
     6import java.text.ParseException;
     7import java.text.SimpleDateFormat;
     8import java.util.*;
    119import java.util.List;
    12 import javax.swing.AbstractAction;
    13 import javax.swing.Action;
    14 import javax.swing.Icon;
     10import java.util.regex.*;
     11import javax.swing.*;
    1512import org.openstreetmap.josm.Main;
    16 import org.openstreetmap.josm.actions.RenameLayerAction;
    17 import org.openstreetmap.josm.actions.SaveAction;
     13import org.openstreetmap.josm.actions.*;
    1814import 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;
    1918import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    2019import 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;
     20import org.openstreetmap.josm.gui.dialogs.*;
     21import org.openstreetmap.josm.gui.layer.*;
    2522import static org.openstreetmap.josm.tools.I18n.tr;
    26 import static org.openstreetmap.josm.tools.I18n.trn;
    2723import org.openstreetmap.josm.tools.ImageProvider;
    2824
    2925/**
     26 * NanoLog layer: a set of points that can be georeferenced.
    3027 *
    3128 * @author zverik
     
    3532    private List<NanoLogEntry> log;
    3633    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    }
    3752   
    3853    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);
    4277    }
    4378   
    4479    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");
    4582        List<NanoLogEntry> result = new ArrayList<NanoLogEntry>();
    4683        BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
     
    4885            String line = r.readLine();
    4986            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                }
    51114            }
    52115        }
     
    58121    public void paint( Graphics2D g, MapView mv, Bounds box ) {
    59122        // 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;
    65126            if( entry.getPos() != null ) {
    66127                Point p = mv.getPoint(entry.getPos());
    67                 g.setColor(Color.green);
     128                g.setColor(selectedEntry == i ? Color.red : Color.yellow);
    68129                g.fillOval(p.x - radius, p.y - radius, radius * 2, radius * 2);
    69130            }
    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);
    75131        }
    76132    }
     
    120176            new RenameLayerAction(null, this),
    121177            SeparatorLayerAction.INSTANCE,
    122             new CorrelateEntries(),
     178            new CorrelateEntries(true),
     179            new CorrelateEntries(false),
    123180            new SaveLayer(),
    124181            SeparatorLayerAction.INSTANCE,
     
    127184    }
    128185
     186    @Override
    129187    public void jumpToNextMarker() {
    130188        selectedEntry++;
     
    136194    }
    137195
     196    @Override
    138197    public void jumpToPreviousMarker() {
    139198        selectedEntry--;
     
    144203        Main.map.repaint();
    145204    }
    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
    149342        public void actionPerformed( ActionEvent e ) {
    150343            // 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 );
    159351    }
    160352}
Note: See TracChangeset for help on using the changeset viewer.