Ticket #5457: SelectAction.java.monster.patch

File SelectAction.java.monster.patch, 12.8 KB (added by cmuelle8, 16 years ago)

fixes most issues, but please test.. if you want to apply it, please take out System.out.println debug lines

  • src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

     
    1515import java.util.Collection;
    1616import java.util.Collections;
    1717import java.util.HashSet;
     18import java.util.Iterator;
    1819import java.util.LinkedList;
    19 import java.util.List;
    2020import java.util.Set;
    2121import java.util.TreeSet;
    2222
     
    202202                    "Add and move a virtual new node to {0} ways", virtualWays.size(),
    203203                    virtualWays.size());
    204204            Main.main.undoRedo.add(new SequenceCommand(text, virtualCmds));
    205             selectPrims(Collections.singleton((OsmPrimitive)virtualNode), false, false, false, false);
     205            getCurrentDataSet().setSelected(Collections.singleton((OsmPrimitive)virtualNode));
    206206            virtualWays.clear();
    207207            virtualNode = null;
    208208        } else {
     
    268268        }
    269269    }
    270270
    271     private Collection<OsmPrimitive> getNearestCollectionVirtual(Point p, boolean allSegements) {
    272         MapView c = Main.map.mapView;
     271    private Collection<OsmPrimitive> getNearestCollectionVirtual(Point p) {
    273272        int snapDistance = Main.pref.getInteger("mappaint.node.virtual-snap-distance", 8);
     273        int virtualSpace = Main.pref.getInteger("mappaint.node.virtual-space", 70);
    274274        snapDistance *= snapDistance;
     275
     276        MapView c = Main.map.mapView;
     277
     278        Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
    275279        OsmPrimitive osm = c.getNearestNode(p, OsmPrimitive.isSelectablePredicate);
    276         virtualWays.clear();
    277         virtualNode = null;
    278         Node virtualWayNode = null;
    279280
    280         if (osm == null)
    281         {
    282             Collection<WaySegment> nearestWaySegs = allSegements
    283             ? c.getNearestWaySegments(p, OsmPrimitive.isSelectablePredicate)
    284                     : Collections.singleton(c.getNearestWaySegment(p, OsmPrimitive.isSelectablePredicate));
     281        if (osm != null) {
     282            for (Node n : c.getNearestNodes(p, OsmPrimitive.isSelectablePredicate)) {
     283                if (sel.contains(n)) {
     284                    osm = n;
     285                }
     286            }
     287        } else {
     288            Node virtualWayNode = null;
     289            Way w = null;
    285290
    286             for(WaySegment nearestWS : nearestWaySegs) {
     291            Collection<WaySegment> virtualWaysInSel = new ArrayList<WaySegment>();
     292            osm = c.getNearestWay(p, OsmPrimitive.isSelectablePredicate);
     293
     294            for(WaySegment nearestWS : c.getNearestWaySegments(p, OsmPrimitive.isSelectablePredicate)) {
    287295                if (nearestWS == null) {
    288296                    continue;
    289297                }
     298                if (sel.contains(w = nearestWS.way)) {
     299                    osm = w;
     300                }
    290301
    291                 osm = nearestWS.way;
    292                 if(Main.pref.getInteger("mappaint.node.virtual-size", 8) > 0)
    293                 {
    294                     Way w = (Way)osm;
     302                if (Main.pref.getInteger("mappaint.node.virtual-size", 8) > 0) {
    295303                    Point p1 = c.getPoint(w.getNode(nearestWS.lowerIndex));
    296304                    Point p2 = c.getPoint(w.getNode(nearestWS.lowerIndex+1));
    297                     if(SimplePaintVisitor.isLargeSegment(p1, p2, Main.pref.getInteger("mappaint.node.virtual-space", 70)))
     305                    if(SimplePaintVisitor.isLargeSegment(p1, p2, virtualSpace))
    298306                    {
    299307                        Point pc = new Point((p1.x+p2.x)/2, (p1.y+p2.y)/2);
    300308                        if (p.distanceSq(pc) < snapDistance)
     
    303311                            // virtual ways list. Otherwise ways that coincidentally have their
    304312                            // virtual node at the same spot will be joined which is likely unwanted
    305313                            if(virtualWayNode != null) {
    306                                 if(  !w.getNode(nearestWS.lowerIndex+1).equals(virtualWayNode)
     314                                if(!w.getNode(nearestWS.lowerIndex+1).equals(virtualWayNode)
    307315                                        && !w.getNode(nearestWS.lowerIndex).equals(virtualWayNode)) {
    308316                                    continue;
    309317                                }
     
    311319                                virtualWayNode = w.getNode(nearestWS.lowerIndex+1);
    312320                            }
    313321
    314                             virtualWays.add(nearestWS);
     322                            (!sel.contains(w) ? virtualWays : virtualWaysInSel).add(nearestWS);
    315323                            if(virtualNode == null) {
    316324                                virtualNode = new Node(Main.map.mapView.getLatLon(pc.x, pc.y));
    317325                            }
     
    319327                    }
    320328                }
    321329            }
     330
     331            if (virtualNode != null) {
     332                virtualWays = virtualWaysInSel.isEmpty() ? virtualWays : virtualWaysInSel;
     333                osm = virtualWays.iterator().next().way;
     334            }
    322335        }
     336
    323337        if (osm == null)
    324338            return Collections.emptySet();
    325339        return Collections.singleton(osm);
     
    337351    @Override public void mousePressed(MouseEvent e) {
    338352        if(!Main.map.mapView.isActiveLayerVisible())
    339353            return;
     354
    340355        // request focus in order to enable the expected keyboard shortcuts
    341         //
    342356        Main.map.mapView.requestFocus();
    343357
    344358        cancelDrawMode = false;
     
    346360        if (e.getButton() != MouseEvent.BUTTON1)
    347361            return;
    348362        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    349         boolean alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
    350363        boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
    351364
    352365        // We don't want to change to draw tool if the user tries to (de)select
     
    359372        didMove = false;
    360373        initialMoveThresholdExceeded = false;
    361374
    362         Collection<OsmPrimitive> osmColl = getNearestCollectionVirtual(e.getPoint(), alt);
     375        Collection<OsmPrimitive> osmColl = getNearestCollectionVirtual(e.getPoint());
    363376
    364377        if (ctrl && shift) {
    365378            if (getCurrentDataSet().getSelected().isEmpty()) {
     
    382395            selectionManager.register(Main.map.mapView);
    383396            selectionManager.mousePressed(e);
    384397        }
    385         if(mode != Mode.move || shift || ctrl)
    386         {
     398
     399        if(mode != Mode.move || shift || ctrl) {
    387400            virtualNode = null;
    388401            virtualWays.clear();
    389402        }
     
    420433        if (mode == Mode.move) {
    421434            boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    422435            boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
     436            boolean alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0
     437            || Main.pref.getBoolean("selectaction.rotates", false);
     438
     439            virtualWays.clear();
     440            virtualNode = null;
     441
    423442            if (!didMove) {
    424                 selectPrims(
    425                         Main.map.mapView.getNearestCollection(e.getPoint(), OsmPrimitive.isSelectablePredicate),
    426                         shift, ctrl, true, false);
     443                Collection<OsmPrimitive> c = Main.map.mapView.getNearestCollection(e.getPoint(), OsmPrimitive.isSelectablePredicate);
     444                if (!c.isEmpty() && alt) {
     445                    if (c.iterator().next() instanceof Node) {
     446                        // there is at least one node under the cursor:
     447                        //   - make sure (first element of new list) equals (result of getNearestCollection)
     448                        //   - do not consider ways at all, but all nearest nodes
     449                        c = new ArrayList<OsmPrimitive>(Main.map.mapView.getNearestNodes(e.getPoint(), OsmPrimitive.isSelectablePredicate));
     450                    } else {
     451                        // consider all ways..
     452                        c = Main.map.mapView.getAllNearest(e.getPoint(), OsmPrimitive.isSelectablePredicate);
     453                    }
     454                }
     455                selectPrims(c, shift, ctrl, true, false);
    427456
    428457                // If the user double-clicked a node, change to draw mode
    429                 List<OsmPrimitive> sel = new ArrayList<OsmPrimitive>(getCurrentDataSet().getSelected());
    430                 if(e.getClickCount() >=2 && sel.size() == 1 && sel.get(0) instanceof Node) {
     458                c = getCurrentDataSet().getSelected();
     459                if(e.getClickCount() >=2 && c.size() == 1 && c.iterator().next() instanceof Node) {
    431460                    // We need to do it like this as otherwise drawAction will see a double
    432461                    // click and switch back to SelectMode
    433462                    Main.worker.execute(new Runnable(){
     
    500529        selectPrims(selectionManager.getObjectsInRectangle(r, alt), shift, ctrl, true, true);
    501530    }
    502531
     532    private boolean selMorePrims = false;
     533    private OsmPrimitive selCycleStart = null;
     534
    503535    public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift,
    504536            boolean ctrl, boolean released, boolean area) {
    505537        DataSet ds = getCurrentDataSet();
    506         if ((shift && ctrl) || (ctrl && !released))
     538        if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty()))
    507539            return; // not allowed together
    508540
     541        for (OsmPrimitive p : selectionList) {
     542            System.out.println("SelectAction:selectPrims(): " + p.getId());
     543        }
     544
     545        // toggle through possible objects on mouse release
     546        if (released && !area) {
     547            if (selectionList.size() > 1) {
     548                Collection<OsmPrimitive> coll = ds.getSelected();
     549
     550                OsmPrimitive first, foundInDS, node, nxt;
     551                first = nxt = selectionList.iterator().next();
     552                foundInDS = node = null;
     553
     554                for (Iterator<OsmPrimitive> i = selectionList.iterator(); i.hasNext(); ) {
     555                    if (selMorePrims && shift) {
     556                        if (!coll.contains(nxt = i.next())) {
     557                            System.out.println("SelectAction:selectPrims(): taking " + nxt.getId());
     558                            break; // take first primitive not in dsSel or last if all contained
     559                        }
     560                    } else {
     561                        if (coll.contains(nxt = i.next())) {
     562                            foundInDS = nxt;
     563                            if (selMorePrims || ctrl) {
     564                                ds.clearSelection(nxt);
     565                                nxt = i.hasNext() ? i.next() : first;
     566                            }
     567                            System.out.println("SelectAction:selectPrims(): taking " + nxt.getId());
     568                            break; // take next primitive of selList
     569                        } else if (nxt instanceof Node && node == null) {
     570                            node = nxt;
     571                        }
     572                    }
     573                }
     574
     575                if (ctrl) {
     576                    if (foundInDS != null) {
     577                        // a member of selList was foundInDS
     578                        if (!selectionList.contains(selCycleStart)) {
     579                            selCycleStart = foundInDS;
     580                            System.out.println("SelectAction:selectPrims(): cycleStart " + selCycleStart.getId());
     581                        }
     582                        // check if selCycleStart == prim (equals next(foundInDS))
     583                        if (selCycleStart.equals(nxt)) {
     584                            ds.addSelected(nxt);   // cycle complete, prim toggled below
     585                            selCycleStart = null;  // check: might do w/out ??
     586                        }
     587                    } else {
     588                        // no member of selList was foundInDS (sets were disjunct), setup for new cycle
     589                        selCycleStart = nxt = (node != null) ? node : first;
     590                        System.out.println("SelectAction:selectPrims(): cycleStart " + selCycleStart.getId());
     591                    }
     592                }
     593
     594                selectionList = new ArrayList<OsmPrimitive>(1); // do not modify the passed object..
     595                selectionList.add(nxt);
     596                System.out.println("SelectAction:selectPrims(): truncated selList to id=" + nxt.getId());
     597            }
     598        }
     599
     600        // hard-wiring to false due to performance reasons, should do w/out
     601        selMorePrims = (released || area) ? false : ds.getSelected().containsAll(selectionList);
     602
    509603        if (ctrl) {
    510604            // Ctrl on an item toggles its selection status,
    511605            // but Ctrl on an *area* just clears those items