source: subversion/applications/editors/josm/plugins/FastDraw/src/org/openstreetmap/josm/plugins/fastdraw/FastDrawingMode.java

Last change on this file was 34510, checked in by donvip, 8 months ago

update to JOSM 14153

File size: 25.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins.fastdraw;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Cursor;
8import java.awt.Graphics2D;
9import java.awt.Point;
10import java.awt.event.KeyEvent;
11import java.awt.event.MouseEvent;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.Iterator;
16import java.util.LinkedList;
17import java.util.List;
18import java.util.Map;
19
20import javax.swing.JOptionPane;
21
22import org.openstreetmap.josm.actions.mapmode.MapMode;
23import org.openstreetmap.josm.command.AddCommand;
24import org.openstreetmap.josm.command.ChangeCommand;
25import org.openstreetmap.josm.command.Command;
26import org.openstreetmap.josm.command.DeleteCommand;
27import org.openstreetmap.josm.command.SequenceCommand;
28import org.openstreetmap.josm.data.Bounds;
29import org.openstreetmap.josm.data.UndoRedoHandler;
30import org.openstreetmap.josm.data.coor.LatLon;
31import org.openstreetmap.josm.data.osm.DataSet;
32import org.openstreetmap.josm.data.osm.Node;
33import org.openstreetmap.josm.data.osm.OsmPrimitive;
34import org.openstreetmap.josm.data.osm.Way;
35import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
36import org.openstreetmap.josm.gui.MainApplication;
37import org.openstreetmap.josm.gui.MapFrame;
38import org.openstreetmap.josm.gui.MapView;
39import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler;
40import org.openstreetmap.josm.gui.layer.Layer;
41import org.openstreetmap.josm.gui.layer.MapViewPaintable;
42import org.openstreetmap.josm.gui.layer.OsmDataLayer;
43import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
44import org.openstreetmap.josm.gui.util.ModifierExListener;
45import org.openstreetmap.josm.tools.ImageProvider;
46import org.openstreetmap.josm.tools.Shortcut;
47import org.openstreetmap.josm.tools.TextTagParser;
48
49class FastDrawingMode extends MapMode implements MapViewPaintable, KeyPressReleaseListener, ModifierExListener {
50    // CHECKSTYLE.OFF: LineLength
51    private static final String SIMPLIFYMODE_MESSAGE =
52            tr("Q=Options, Enter=save, Ctrl-Enter=save with tags, Up/Down=tune");
53    private static final String DRAWINGMODE_MESSAGE =
54            tr("Click or Click&drag to continue, Ctrl-Click to add fixed node, Shift-Click to delete, Enter to simplify or save, Ctrl-Shift-Click to start new line");
55    // CHECKSTYLE.ON: LineLength
56
57    private FDSettings settings;
58
59    private final DrawnPolyLine line;
60    private MapView mv;
61    private String statusText;
62    private boolean drawing;
63    private double eps;
64    private final Cursor cursorDraw;
65    private final Cursor cursorCtrl;
66    private final Cursor cursorShift;
67    private final Cursor cursorReady;
68    //private final Cursor cursorNode;
69    private final Cursor cursorDrawing;
70    private boolean nearSomeNode;
71    private LatLon highlightedFragmentStart;
72    private int nearestPointIndex;
73    private int dragNode = -1;
74    private List<Node> oldNodes;
75
76    private boolean lineWasSaved;
77    private boolean deltaChanged;
78    private Way oldWay;
79
80    FastDrawingMode(MapFrame mapFrame) {
81        super(tr("FastDrawing"), "turbopen.png", tr("Fast drawing mode"),
82                Shortcut.registerShortcut("mapmode:fastdraw", tr("Mode: {0}", tr("Fast drawing mode")), KeyEvent.VK_F, Shortcut.SHIFT),
83                Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
84        line = new DrawnPolyLine();
85        cursorDraw = ImageProvider.getCursor("crosshair", null);
86        cursorCtrl = ImageProvider.getCursor("crosshair", "fixed");
87        cursorShift = ImageProvider.getCursor("crosshair", "new");
88        cursorReady = ImageProvider.getCursor("crosshair", "ready");
89        //cursorNode = ImageProvider.getCursor("crosshair", "joinnode");
90        cursorDrawing = ImageProvider.getCursor("crosshair", "mode");
91        //loadPrefs();
92    }
93
94    // <editor-fold defaultstate="collapsed" desc="Event listeners">
95
96    @Override
97    public void enterMode() {
98        super.enterMode();
99        lineWasSaved = false;
100        settings = new FDSettings();
101        settings.loadPrefs();
102        settings.savePrefs();
103
104        MapFrame map = MainApplication.getMap();
105        eps = settings.startingEps;
106        mv = map.mapView;
107        line.setMv(mv);
108
109        if (getLayerManager().getEditDataSet() == null) return;
110
111        map.mapView.addMouseListener(this);
112        map.mapView.addMouseMotionListener(this);
113        map.mapView.addTemporaryLayer(this);
114
115        map.keyDetector.addKeyListener(this);
116        map.keyDetector.addModifierExListener(this);
117    }
118
119    @Override
120    public void exitMode() {
121        super.exitMode();
122        if (line.wasSimplified() && !lineWasSaved) saveAsWay(false);
123        MapFrame map = MainApplication.getMap();
124
125        map.mapView.removeMouseListener(this);
126        map.mapView.removeMouseMotionListener(this);
127
128        map.mapView.removeTemporaryLayer(this);
129
130        map.keyDetector.removeKeyListener(this);
131        map.keyDetector.removeModifierExListener(this);
132
133        settings.savePrefs();
134        map.mapView.setCursor(cursorDraw);
135        repaint();
136    }
137
138    @Override
139    public boolean layerIsSupported(Layer l) {
140        return l instanceof OsmDataLayer;
141    }
142
143    @Override
144    protected void updateEnabledState() {
145        setEnabled(getLayerManager().getEditLayer() != null);
146    }
147
148    private final ArrayList<Point> fixedPoints = new ArrayList<>(3000); // temporary storate for paint
149
150    //////////    Event listener methods
151    @Override
152    public void paint(Graphics2D g, MapView mv, Bounds bbox) {
153        LinkedList<LatLon> pts = line.getPoints();
154        if (pts.isEmpty()) return;
155
156        if (line.wasSimplified()) {
157            // we are drawing simplified version, that exists
158            g.setStroke(settings.simplifiedStroke);
159        } else {
160            g.setStroke(settings.normalStroke);
161        }
162
163        int bigDotSize = settings.bigDotSize;
164
165        Point p1, p2;
166        LatLon pp1, pp2;
167        p1 = line.getPoint(pts.get(0));
168        g.setColor(settings.COLOR_FIXED.get());
169        g.fillOval(p1.x - bigDotSize/2, p1.y - bigDotSize/2, bigDotSize, bigDotSize);
170        Color lineColor, initLineColor;
171        initLineColor = line.wasSimplified() ? settings.COLOR_SIMPLIFIED.get() : settings.COLOR_NORMAL.get();
172        lineColor = initLineColor;
173        int rp, dp;
174        dp = line.wasSimplified() ? settings.bigDotSize : settings.dotSize; rp = dp/2;
175        if (pts.size() > 1) {
176            Iterator<LatLon> it1, it2;
177            it1 = pts.listIterator(0);
178            it2 = pts.listIterator(1);
179            fixedPoints.clear();
180            for (int i = 0; i < pts.size() - 1; i++) {
181                pp1 = it1.next();
182                p1 = line.getPoint(pp1);
183                pp2 = it2.next();
184                p2 = line.getPoint(pp2);
185                if (shift && highlightedFragmentStart == pp1 && nearestPointIndex < 0) {
186                    lineColor = settings.COLOR_SELECTEDFRAGMENT.get();
187                }
188                if (!shift && line.isLastPoint(i)) {
189                    lineColor = settings.COLOR_EDITEDFRAGMENT.get();
190                }
191                g.setColor(lineColor);
192                g.drawLine(p1.x, p1.y, p2.x, p2.y);
193                if (line.isFixed(pp2)) {
194                    lineColor = initLineColor;
195                    fixedPoints.add(p2);
196                } else {
197                    g.fillRect(p2.x - rp, p2.y - rp, dp, dp);
198                }
199                if (!drawing) {
200                    if (!line.wasSimplified() && nearestPointIndex == i+1) {
201                        if (shift) {
202                            // highlight node to delete
203                            g.setStroke(settings.deleteStroke);
204                            g.setColor(settings.COLOR_DELETE.get());
205                            g.drawLine(p2.x - 5, p2.y - 5, p2.x + 5, p2.y + 5);
206                            g.drawLine(p2.x - 5, p2.y + 5, p2.x + 5, p2.y - 5);
207                            g.setStroke(settings.normalStroke);
208                        } else if (ctrl) {
209                            // highlight node to toggle fixation
210                            g.setStroke(settings.deleteStroke);
211                            g.setColor(line.isFixed(pp2) ? settings.COLOR_NORMAL.get() : settings.COLOR_FIXED.get());
212                            g.fillOval(p2.x - bigDotSize/2-2, p2.y - bigDotSize/2-2, bigDotSize+4, bigDotSize+4);
213                            g.setStroke(settings.normalStroke);
214                        }
215                    }
216                }
217            }
218            g.setColor(settings.COLOR_FIXED.get());
219            for (Point p: fixedPoints) {
220                g.fillOval(p.x - bigDotSize/2, p.y - bigDotSize/2, bigDotSize, bigDotSize);
221            }
222        }
223        if (settings.drawLastSegment && !drawing && dragNode < 0 && !shift &&
224                nearestPointIndex <= 0 && !line.wasSimplified()) {
225            // draw line to current point
226            g.setColor(lineColor);
227            Point lp = line.getLastPoint();
228            Point mp = mv.getMousePosition();
229            if (lp != null && mp != null) g.drawLine(lp.x, lp.y, mp.x, mp.y);
230        }
231        if (deltaChanged) {
232            g.setColor(lineColor);
233            Point lp = line.getLastPoint();
234            int r = (int) settings.minPixelsBetweenPoints;
235            if (lp != null) g.drawOval(lp.x-r, lp.y-r, 2*r, 2*r);
236        }
237    }
238
239    @Override
240    public void mousePressed(MouseEvent e) {
241        if (!isEnabled()) return;
242        if (e.getButton() != MouseEvent.BUTTON1) return;
243        updateKeyModifiers(e);
244
245        requestFocusInMapView();
246
247        int idx = line.findClosestPoint(e.getPoint(), settings.maxDist);
248        if (idx == 0 && !line.isClosed()) {
249            line.closeLine();
250            // the way should become closed
251            drawing = false;
252            dragNode = 0;
253            updateCursor();
254            return;
255        }
256        autoCloseIfNeeded();
257
258        if (ctrl && shift) {
259            newDrawing();
260            repaint();
261            return;
262        }
263        if (!ctrl && shift) {
264            if (idx >= 0) {
265                line.deleteNode(idx);
266                nearestPointIndex = -1;
267            } else
268                line.tryToDeleteSegment(e.getPoint());
269            return;
270        }
271        if (idx >= 0) {
272            if (ctrl) {
273                // toggle fixed point
274                line.toggleFixed(idx);
275            }
276            // node dragging
277            dragNode = idx;
278            return;
279        }
280        startDrawing(e.getPoint(), settings.fixedClick);
281    }
282
283    private void startDrawing(Point point, boolean fixFlag) {
284        //if (line.isClosed()) { setStatusLine(tr(SIMPLIFYMODE_MESSAGE));return;  }
285        drawing = true;
286        if (line.wasSimplified()) {
287            // new line started after simplification
288            // we need to save old line
289            saveAsWay(false);
290            newDrawing();
291            //line.clearSimplifiedVersion();
292        }
293
294        LatLon p = mv.getLatLon(point.x, point.y);
295        if (settings.snapNodes) { // find existing node near point and use it
296            Node nd1 = getNearestNode(point, settings.maxDist);
297            if (nd1 != null) {
298                // found node, make it fixed point of the line
299                //System.out.println("node "+nd1);
300                p = nd1.getCoor();
301                line.fixPoint(p);
302            }
303        }
304
305        line.addLast(p);
306        if (ctrl || fixFlag) line.fixPoint(p);
307
308        setStatusLine(tr("Please move the mouse to draw new way"));
309        repaint();
310    }
311
312    @Override
313    public void mouseReleased(MouseEvent e) {
314        if (e.getButton() != MouseEvent.BUTTON1) return;
315        stopDrawing();
316    }
317
318    private void stopDrawing() {
319        if (!isEnabled()) return;
320        dragNode = -1;
321        drawing = false;
322        highlightedFragmentStart = null;
323        if (!line.isClosed()) setStatusLine(DRAWINGMODE_MESSAGE);
324        updateCursor();
325        repaint();
326    }
327
328    @Override
329    public void mouseDragged(MouseEvent e) {
330        mouseMoved(e);
331    }
332
333    @Override
334    public void mouseMoved(MouseEvent e) {
335        if (!isEnabled()) return;
336        updateKeyModifiers(e);
337        deltaChanged = false;
338        Node nd1 = getNearestNode(e.getPoint(), settings.maxDist);
339        boolean nearSomeNode2 = nd1 != null;
340        boolean needRepaint = false;
341        if (nearSomeNode != nearSomeNode2) {
342            nearSomeNode = nearSomeNode2;
343            updateCursor();
344            needRepaint = true;
345        }
346
347        int nearestIdx2 = line.findClosestPoint(e.getPoint(), settings.maxDist);
348        if (nearestPointIndex != nearestIdx2) {
349            nearestPointIndex = nearestIdx2;
350            updateCursor();
351            needRepaint = true;
352        }
353        if (settings.drawLastSegment) {
354            needRepaint = true;
355        }
356
357        if (!drawing) {
358            if (dragNode >= 0) {
359                line.moveNode(dragNode, getLatLon(e));
360                repaint();
361                return;
362            }
363
364            if (shift && nearestPointIndex == -1) {
365                // find line fragment to highlight
366                LatLon h2 = line.findBigSegment(e.getPoint());
367                if (highlightedFragmentStart != h2) {
368                    highlightedFragmentStart = h2;
369                    needRepaint = true;
370                }
371            }
372
373            if (needRepaint) {
374                repaint();
375            }
376            return;
377        }
378        if (line.isClosed()) setStatusLine(SIMPLIFYMODE_MESSAGE);
379
380        // do not draw points close to existing points - we do not want self-intersections
381        if (nearestPointIndex >= 0) {
382            return;
383        }
384
385        Point lastP = line.getLastPoint(); // last point of line fragment being edited
386
387        // free mouse-drawing
388        if (nearSomeNode) {
389            if (settings.snapNodes && lastP != null && Math.hypot(e.getX() - lastP.x, e.getY() - lastP.y) > 1e-2) {
390                line.addFixed(nd1.getCoor()); // snap to node coords
391                repaint();
392                return;
393            }
394        } else {
395            if (lastP != null && Math.hypot(e.getX() - lastP.x, e.getY() - lastP.y) > settings.minPixelsBetweenPoints) {
396                line.addLast(getLatLon(e)); // add new point
397                repaint();
398                return;
399            }
400        }
401        autoCloseIfNeeded();
402    }
403
404    @Override
405    public void doKeyPressed(KeyEvent e) {
406        if (getShortcut().isEvent(e)) { // repeated press
407            tryToLoadWay();
408            return;
409        }
410        switch(e.getKeyCode()) {
411        case KeyEvent.VK_BACK_SPACE:
412            if (line.wasSimplified()) {
413                // return to line editing
414                line.clearSimplifiedVersion();
415                repaint();
416                eps = settings.startingEps;
417            }
418            back();
419            break;
420        case KeyEvent.VK_ENTER:
421            e.consume();
422            // first Enter = simplify, second = save the way
423            if (!line.wasSimplified()) {
424                //line.simplify(eps);
425                switch(settings.simplifyMode) {
426                case 0: //case 1:
427                    eps = line.autoSimplify(settings.startingEps, settings.epsilonMult,
428                            settings.pkmBlockSize, settings.maxPointsPerKm);
429                    break;
430                case 1: //case 2: case 3:
431                    line.simplify(eps);
432                    break;
433                }
434                if (settings.simplifyMode == 2) {
435                    // autosave
436                    saveAsWay(true);
437                } else {
438                    repaint();
439                    showSimplifyHint();
440                }
441            } else {
442                saveAsWay(true);
443            }
444            break;
445        case KeyEvent.VK_DOWN:
446            if (ctrl || shift || alt) return;
447            // more details
448            e.consume();
449            if (line.wasSimplified()) changeEpsilon(settings.epsilonMult);
450            else changeDelta(1/1.1);
451            break;
452        case KeyEvent.VK_UP:
453            if (ctrl || shift || alt) return;
454            // less details
455            e.consume();
456            if (line.wasSimplified()) changeEpsilon(1/settings.epsilonMult);
457            else changeDelta(1.1);
458            break;
459        case KeyEvent.VK_ESCAPE:
460            e.consume();
461            Point lastPoint = line.getLastPoint();
462            if (!line.isClosed()) line.moveToTheEnd();
463            if (lastPoint == null || lastPoint.equals(line.getLastPoint())) {
464                if (line.getPoints().size() > 5) {
465                    boolean answer = ConditionalOptionPaneUtil.showConfirmationDialog(
466                            "delete_drawn_line", MainApplication.getMainFrame(),
467                            tr("Are you sure you do not want to save the line containing {0} points?",
468                                    line.getPoints().size()), tr("Delete confirmation"),
469                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_OPTION);
470                    if (!answer) break;
471                }
472                newDrawing(); // stop drawing
473                MainApplication.getMap().selectSelectTool(false);
474            }
475            break;
476
477        case KeyEvent.VK_I:
478            JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
479                    tr("{0} m - length of the line\n{1} nodes\n{2} points per km (maximum)\n{3} points per km (average)",
480                            line.getLength(), line.getPoints().size(), line.getNodesPerKm(settings.pkmBlockSize),
481                            line.getNodesPerKm(1000000)),
482                    tr("Line information"), JOptionPane.INFORMATION_MESSAGE);
483            break;
484        case KeyEvent.VK_Q:
485            // less details
486            e.consume();
487            new FastDrawConfigDialog(settings).showDialog();
488            if (line.wasSimplified()) {
489                eps = line.autoSimplify(settings.startingEps, settings.epsilonMult, settings.pkmBlockSize, settings.maxPointsPerKm);
490                showSimplifyHint();
491            }
492            repaint();
493            break;
494        case KeyEvent.VK_SPACE:
495            e.consume();
496            if (!drawing) {
497                Point p = MainApplication.getMap().mapView.getMousePosition();
498                if (p != null) startDrawing(p, settings.fixedSpacebar);
499            }
500            break;
501        }
502    }
503
504    @Override
505    public void doKeyReleased(KeyEvent keyEvent) {
506        //System.out.println("released "+keyEvent);
507        if (keyEvent.getKeyCode() == KeyEvent.VK_SPACE) stopDrawing();
508        updateCursor();
509    }
510
511    @Override
512    public void modifiersExChanged(int modifiers) {
513        updateKeyModifiersEx(modifiers);
514        updateCursor();
515    }
516
517    @Override
518    protected void updateStatusLine() {
519        MainApplication.getMap().statusLine.setHelpText(statusText);
520        MainApplication.getMap().statusLine.repaint();
521    }
522    // </editor-fold>
523
524    // <editor-fold defaultstate="collapsed" desc="Different action helper methods">
525    public void newDrawing() {
526        oldWay = null; oldNodes = null;
527        eps = settings.startingEps;
528        line.clear();
529    }
530
531    private void saveAsWay(boolean autoExit) {
532        List<LatLon> pts = line.getPoints();
533        int n = pts.size();
534        if (n < 2) return; //do not save oversimplified lines
535        if (line.isClosed() && n == 2) return;
536        if (line.isClosed() && n == 3) pts.remove(2); // two-point way can not be closed
537
538        DataSet ds = getLayerManager().getEditDataSet();
539        Collection<Command> cmds = new LinkedList<>();
540        int i = 0;
541
542        Way w;
543        if (oldWay == null) {
544            w = new Way();
545        } else {
546            w = new Way(oldWay);
547            w.setNodes(new ArrayList<Node>()); // nodes will be created frosm scratch
548        }
549
550        LatLon first = pts.get(0);
551        Node firstNode = null;
552
553        for (LatLon p : pts) {
554            Node nd = MainApplication.getMap().mapView.getNearestNode(line.getPoint(p), OsmPrimitive::isSelectable);
555            // there may be a node with the same coords!
556
557            if (nd != null && p.greatCircleDistance(nd.getCoor()) > 0.01) nd = null;
558            if (nd == null) {
559                if (i > 0 && p.equals(first)) {
560                    nd = firstNode;
561                } else {
562                    nd = new Node(p);
563                    cmds.add(new AddCommand(ds, nd));
564                }
565            }
566            if (nd.getCoor().isOutSideWorld()) {
567                JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
568                        tr("Cannot place node outside of the world."));
569                return;
570            }
571            if (i == 0) {
572                firstNode = nd;
573            }
574            w.addNode(nd);
575            i++;
576        }
577        if (ctrl) {
578            // paste tags - from ctrl-shift-v
579            new OsmTransferHandler().pasteTags(Collections.singleton(w));
580        }
581        if (!settings.autoTags.isEmpty()) {
582            Map<String, String> tags = TextTagParser.readTagsFromText(settings.autoTags);
583            for (String k: tags.keySet()) {
584                w.put(k, tags.get(k));
585            }
586        }
587        if (oldWay != null) {
588            List<Node> nodes = w.getNodes();
589            cmds.add(new ChangeCommand(oldWay, w));
590            for (Node nd: oldNodes) {
591                // node from old way but not in new way
592                if (!nodes.contains(nd)) {
593                    List<OsmPrimitive> refs = nd.getReferrers();
594                    // does someone need this node? if no-delete it.
595                    if (refs.size() == 1 && !nd.isDeleted() && nd.isUsable() && !nd.isTagged()) cmds.add(new DeleteCommand(nd));
596                }
597            }
598            oldWay = null; // that is all with this command
599        } else cmds.add(new AddCommand(ds, w));
600        Command c = new SequenceCommand(tr("Draw the way by mouse"), cmds);
601        UndoRedoHandler.getInstance().add(c);
602        lineWasSaved = true;
603        newDrawing(); // stop drawing
604        if (autoExit) {
605            // Select this way and switch drawing mode off
606            ds.setSelected(w);
607            MainApplication.getMap().selectSelectTool(false);
608        }
609    }
610
611    public void back() {
612        line.undo();
613        repaint();
614    }
615
616    void changeEpsilon(double k) {
617        //System.out.println(tr("Eps={0}", eps));
618        eps *= k;
619        line.simplify(eps);
620        /* I18N: Eps = Epsilon, the tolerance parameter */
621        showSimplifyHint();
622        repaint();
623    }
624
625    void changeDelta(double k) {
626        settings.minPixelsBetweenPoints *= k;
627        deltaChanged = true;
628
629        setStatusLine(tr("min distance={0} px ({1} m)", (int) settings.minPixelsBetweenPoints,
630                mv.getDist100Pixel()/100*settings.minPixelsBetweenPoints));
631        repaint();
632    }
633
634    /*private Node findClosestNode(LatLon p, double d) {
635        Node nn=null;
636        double dist,minD=1e10,x,y;
637        Point pscreen=getPoint(p);   x=pscreen.x; y=pscreen.y;
638        BBox b=new BBox(new LatLon(p.lat()-deltaLatLon,p.lon()-deltaLatLon),
639                new LatLon(p.lat()+deltaLatLon,p.lon()+deltaLatLon));
640        List<Node> nodes = getCurrentDataSet().searchNodes(b);
641        for (Node n: nodes) {
642            dist = Math.sqrt(getPoint(n.getCoor()).distanceSq(x,y));
643            if (dist<d && dist<minD) {
644                nn=n;
645                minD=dist;
646            };
647        }
648        return nn;
649    }*/
650
651    private void loadFromWay(Way w) {
652
653        Object[] nodes = w.getNodes().toArray();
654        int n = nodes.length;
655        if (w.isClosed()) n--;
656        for (int i = 0; i < n; i++) {
657            Node nd = (Node) nodes[i];
658            List<OsmPrimitive> refs = nd.getReferrers();
659            if (refs.size() > 1 || nd.isTagged()) {
660                line.addFixed(nd.getCoor());
661            } else {
662                line.addLast(nd.getCoor());
663            }
664        }
665        if (w.isClosed()) line.closeLine();
666        oldNodes = w.getNodes();
667        oldWay = w;
668    }
669
670    private void setStatusLine(String tr) {
671        statusText = tr;
672        updateStatusLine();
673    }
674
675    private void showSimplifyHint() {
676        setStatusLine(tr("Eps={0}, {1} points, {2} p/km",
677                eps, line.getSimplePointsCount(), line.getNodesPerKm(settings.pkmBlockSize))+" "
678                +SIMPLIFYMODE_MESSAGE);
679    }
680
681    private void updateCursor() {
682        MapView mapView = MainApplication.getMap().mapView;
683        if (shift) mapView.setCursor(cursorShift); else
684            if (line.isClosed() || (nearestPointIndex == 0)) mapView.setCursor(cursorReady); else
685                if (ctrl) mapView.setCursor(cursorCtrl); else
686                    if (nearSomeNode && settings.snapNodes) mapView.setCursor(cursorCtrl); else
687                        if (drawing) mapView.setCursor(cursorDrawing); else
688                            mapView.setCursor(cursorDraw);
689    }
690
691    private void repaint() {
692        MainApplication.getMap().mapView.repaint();
693    }
694
695    private void tryToLoadWay() {
696        updateCursor();
697        Collection<Way> selectedWays = MainApplication.getLayerManager().getEditDataSet().getSelectedWays();
698        if (selectedWays != null // if there is a selection
699                && selectedWays.size() == 1 // and one way is selected
700                && line.getPoints().size() == 0) /* and ther is no already drawn line */ {
701            // we can start drawing new way starting from old one
702            Way w = selectedWays.iterator().next();
703
704            if (w.isNew() || settings.allowEditExistingWays) loadFromWay(w);
705        }
706    }
707
708    private void autoCloseIfNeeded() {
709        if (settings.drawClosed && line.getPointCount() > 1 && !line.isClosed()) {
710            line.closeLine();
711        }
712    }
713    // </editor-fold>
714
715    // <editor-fold defaultstate="collapsed" desc="Helper functions">
716
717    private Node getNearestNode(Point point, double maxDist) {
718        Node nd = MainApplication.getMap().mapView.getNearestNode(point, OsmPrimitive::isSelectable);
719        if (nd != null && line.getPoint(nd.getCoor()).distance(point) <= maxDist) return nd;
720        else return null;
721    }
722
723    LatLon getLatLon(MouseEvent e) {
724        return mv.getLatLon(e.getX(), e.getY());
725    }
726    // </editor-fold>
727}
Note: See TracBrowser for help on using the repository browser.