Changeset 12828 in josm for trunk/src


Ignore:
Timestamp:
2017-09-12T16:50:56+02:00 (7 years ago)
Author:
Don-vip
Message:

see #15229 - see #15182 - see #13036 - convert SplitWayAction to SplitWayCommand to remove dependence of DeleteCommand on actions package

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java

    r12749 r12828  
    2525import org.openstreetmap.josm.Main;
    2626import org.openstreetmap.josm.actions.ReverseWayAction.ReverseWayResult;
    27 import org.openstreetmap.josm.actions.SplitWayAction.SplitWayResult;
    2827import org.openstreetmap.josm.command.AddCommand;
    2928import org.openstreetmap.josm.command.ChangeCommand;
     
    3130import org.openstreetmap.josm.command.DeleteCommand;
    3231import org.openstreetmap.josm.command.SequenceCommand;
     32import org.openstreetmap.josm.command.SplitWayCommand;
    3333import org.openstreetmap.josm.data.UndoRedoHandler;
    3434import org.openstreetmap.josm.data.coor.EastNorth;
     
    10191019
    10201020        if (chunks.size() > 1) {
    1021             SplitWayResult split = SplitWayAction.splitWay(way, chunks,
    1022                     Collections.<OsmPrimitive>emptyList(), SplitWayAction.Strategy.keepFirstChunk());
     1021            SplitWayCommand split = SplitWayCommand.splitWay(way, chunks,
     1022                    Collections.<OsmPrimitive>emptyList(), SplitWayCommand.Strategy.keepFirstChunk());
    10231023
    10241024            if (split != null) {
    10251025                //execute the command, we need the results
    1026                 cmds.add(split.getCommand());
     1026                cmds.add(split);
    10271027                commitCommands(marktr("Split ways into fragments"));
    10281028
  • trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java

    r12726 r12828  
    1111import java.awt.event.KeyEvent;
    1212import java.util.ArrayList;
    13 import java.util.Arrays;
    1413import java.util.Collection;
    1514import java.util.Collections;
    16 import java.util.HashSet;
    1715import java.util.Iterator;
    18 import java.util.LinkedList;
    1916import java.util.List;
    20 import java.util.Optional;
    21 import java.util.Set;
    2217import java.util.concurrent.atomic.AtomicInteger;
    2318
     
    3025
    3126import org.openstreetmap.josm.Main;
    32 import org.openstreetmap.josm.command.AddCommand;
    33 import org.openstreetmap.josm.command.ChangeCommand;
    3427import org.openstreetmap.josm.command.Command;
    35 import org.openstreetmap.josm.command.SequenceCommand;
     28import org.openstreetmap.josm.command.SplitWayCommand;
    3629import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    3730import org.openstreetmap.josm.data.osm.Node;
     
    3932import org.openstreetmap.josm.data.osm.PrimitiveId;
    4033import org.openstreetmap.josm.data.osm.Relation;
    41 import org.openstreetmap.josm.data.osm.RelationMember;
    4234import org.openstreetmap.josm.data.osm.Way;
    4335import org.openstreetmap.josm.data.osm.WaySegment;
     
    4739import org.openstreetmap.josm.gui.Notification;
    4840import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    49 import org.openstreetmap.josm.tools.CheckParameterUtil;
    5041import org.openstreetmap.josm.tools.GBC;
    5142import org.openstreetmap.josm.tools.Shortcut;
     
    6354     * @see SplitWayAction#splitWay
    6455     * @see SplitWayAction#split
    65      */
     56     * @deprecated To be removed end of 2017. Use {@link SplitWayCommand} instead
     57     */
     58    @Deprecated
    6659    public static class SplitWayResult {
    6760        private final Command command;
     
    8174            this.originalWay = originalWay;
    8275            this.newWays = newWays;
     76        }
     77
     78        /**
     79         * @param command The command to be performed to split the way (which is saved for later retrieval with {@link #getCommand})
     80         * @since 12828
     81         */
     82        protected SplitWayResult(SplitWayCommand command) {
     83            this.command = command;
     84            this.newSelection = command.getNewSelection();
     85            this.originalWay = command.getOriginalWay();
     86            this.newWays = command.getNewWays();
    8387        }
    8488
     
    194198        // Finally, applicableWays contains only one perfect way
    195199        final Way selectedWay = applicableWays.get(0);
    196         final List<List<Node>> wayChunks = buildSplitChunks(selectedWay, selectedNodes);
     200        final List<List<Node>> wayChunks = SplitWayCommand.buildSplitChunks(selectedWay, selectedNodes);
    197201        if (wayChunks != null) {
    198202            List<Relation> selectedRelations = OsmPrimitive.getFilteredList(selection, Relation.class);
     
    202206
    203207            final List<Way> newWays = createNewWaysFromChunks(selectedWay, wayChunks);
    204             final Way wayToKeep = Strategy.keepLongestChunk().determineWayToKeep(newWays);
     208            final Way wayToKeep = SplitWayCommand.Strategy.keepLongestChunk().determineWayToKeep(newWays);
    205209
    206210            if (ExpertToggleAction.isExpert() && !selectedWay.isNew()) {
     
    214218            }
    215219            if (wayToKeep != null) {
    216                 final SplitWayResult result = doSplitWay(selectedWay, wayToKeep, newWays, sel);
    217                 MainApplication.undoRedo.add(result.getCommand());
    218                 if (!result.getNewSelection().isEmpty()) {
    219                     getLayerManager().getEditDataSet().setSelected(result.getNewSelection());
    220                 }
     220                doSplitWay(selectedWay, wayToKeep, newWays, sel);
    221221            }
    222222        }
     
    294294            toggleSaveState(); // necessary since #showDialog() does not handle it due to the non-modal dialog
    295295            if (getValue() == 1) {
    296                 SplitWayResult result = doSplitWay(selectedWay, list.getSelectedValue(), newWays, selection);
    297                 MainApplication.undoRedo.add(result.getCommand());
    298                 if (!result.getNewSelection().isEmpty()) {
    299                     MainApplication.getLayerManager().getEditDataSet().setSelected(result.getNewSelection());
    300                 }
     296                doSplitWay(selectedWay, list.getSelectedValue(), newWays, selection);
    301297            }
    302298        }
     
    322318     * @since 8954
    323319     * @since 10599 (functional interface)
    324      */
     320     * @deprecated to be removed end of 2017. Use {@link org.openstreetmap.josm.command.SplitWayCommand.Strategy} instead
     321     */
     322    @Deprecated
    325323    @FunctionalInterface
    326324    public interface Strategy {
     
    339337         */
    340338        static Strategy keepLongestChunk() {
    341             return wayChunks -> {
    342                     Way wayToKeep = null;
    343                     for (Way i : wayChunks) {
    344                         if (wayToKeep == null || i.getNodesCount() > wayToKeep.getNodesCount()) {
    345                             wayToKeep = i;
    346                         }
    347                     }
    348                     return wayToKeep;
    349                 };
     339            return SplitWayCommand.Strategy.keepLongestChunk()::determineWayToKeep;
    350340        }
    351341
     
    355345         */
    356346        static Strategy keepFirstChunk() {
    357             return wayChunks -> wayChunks.iterator().next();
     347            return SplitWayCommand.Strategy.keepFirstChunk()::determineWayToKeep;
    358348        }
    359349    }
     
    406396     * @param splitPoints the nodes where the way is split. Must not be null.
    407397     * @return the list of chunks
    408      */
     398     * @deprecated To be removed end of 2017. Use {@link SplitWayCommand#buildSplitChunks} instead
     399     */
     400    @Deprecated
    409401    public static List<List<Node>> buildSplitChunks(Way wayToSplit, List<Node> splitPoints) {
    410         CheckParameterUtil.ensureParameterNotNull(wayToSplit, "wayToSplit");
    411         CheckParameterUtil.ensureParameterNotNull(splitPoints, "splitPoints");
    412 
    413         Set<Node> nodeSet = new HashSet<>(splitPoints);
    414         List<List<Node>> wayChunks = new LinkedList<>();
    415         List<Node> currentWayChunk = new ArrayList<>();
    416         wayChunks.add(currentWayChunk);
    417 
    418         Iterator<Node> it = wayToSplit.getNodes().iterator();
    419         while (it.hasNext()) {
    420             Node currentNode = it.next();
    421             boolean atEndOfWay = currentWayChunk.isEmpty() || !it.hasNext();
    422             currentWayChunk.add(currentNode);
    423             if (nodeSet.contains(currentNode) && !atEndOfWay) {
    424                 currentWayChunk = new ArrayList<>();
    425                 currentWayChunk.add(currentNode);
    426                 wayChunks.add(currentWayChunk);
    427             }
    428         }
    429 
    430         // Handle circular ways specially.
    431         // If you split at a circular way at two nodes, you just want to split
    432         // it at these points, not also at the former endpoint.
    433         // So if the last node is the same first node, join the last and the
    434         // first way chunk.
    435         List<Node> lastWayChunk = wayChunks.get(wayChunks.size() - 1);
    436         if (wayChunks.size() >= 2
    437                 && wayChunks.get(0).get(0) == lastWayChunk.get(lastWayChunk.size() - 1)
    438                 && !nodeSet.contains(wayChunks.get(0).get(0))) {
    439             if (wayChunks.size() == 2) {
    440                 new Notification(
    441                         tr("You must select two or more nodes to split a circular way."))
    442                         .setIcon(JOptionPane.WARNING_MESSAGE)
    443                         .show();
    444                 return null;
    445             }
    446             lastWayChunk.remove(lastWayChunk.size() - 1);
    447             lastWayChunk.addAll(wayChunks.get(0));
    448             wayChunks.remove(wayChunks.size() - 1);
    449             wayChunks.set(0, lastWayChunk);
    450         }
    451 
    452         if (wayChunks.size() < 2) {
    453             if (wayChunks.get(0).get(0) == wayChunks.get(0).get(wayChunks.get(0).size() - 1)) {
    454                 new Notification(
    455                         tr("You must select two or more nodes to split a circular way."))
    456                         .setIcon(JOptionPane.WARNING_MESSAGE)
    457                         .show();
    458             } else {
    459                 new Notification(
    460                         tr("The way cannot be split at the selected nodes. (Hint: Select nodes in the middle of the way.)"))
    461                         .setIcon(JOptionPane.WARNING_MESSAGE)
    462                         .show();
    463             }
    464             return null;
    465         }
    466         return wayChunks;
     402        return SplitWayCommand.buildSplitChunks(wayToSplit, splitPoints);
    467403    }
    468404
     
    472408     * @param wayChunks the way chunks
    473409     * @return the new way objects
    474      */
     410     * @deprecated To be removed end of 2017. Use {@link SplitWayCommand#createNewWaysFromChunks} instead
     411     */
     412    @Deprecated
    475413    protected static List<Way> createNewWaysFromChunks(Way way, Iterable<List<Node>> wayChunks) {
    476         final List<Way> newWays = new ArrayList<>();
    477         for (List<Node> wayChunk : wayChunks) {
    478             Way wayToAdd = new Way();
    479             wayToAdd.setKeys(way.getKeys());
    480             wayToAdd.setNodes(wayChunk);
    481             newWays.add(wayToAdd);
    482         }
    483         return newWays;
     414        return SplitWayCommand.createNewWaysFromChunks(way, wayChunks);
    484415    }
    485416
     
    518449     * @return the result from the split operation
    519450     * @since 12718
    520      */
     451     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection)} instead
     452     */
     453    @Deprecated
    521454    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
    522455            Collection<? extends OsmPrimitive> selection) {
     
    565498     * @return the result from the split operation
    566499     * @since 12718
    567      */
     500     * @deprecated to be removed end of 2017. Use {@link SplitWayCommand#splitWay} instead
     501     */
     502    @Deprecated
    568503    public static SplitWayResult splitWay(Way way, List<List<Node>> wayChunks,
    569504            Collection<? extends OsmPrimitive> selection, Strategy splitStrategy) {
    570         // build a list of commands, and also a new selection list
    571         final List<OsmPrimitive> newSelection = new ArrayList<>(selection.size() + wayChunks.size());
    572         newSelection.addAll(selection);
    573 
    574         // Create all potential new ways
    575         final List<Way> newWays = createNewWaysFromChunks(way, wayChunks);
    576 
    577         // Determine which part reuses the existing way
    578         final Way wayToKeep = splitStrategy.determineWayToKeep(newWays);
    579 
    580         return wayToKeep != null ? doSplitWay(way, wayToKeep, newWays, newSelection) : null;
    581     }
    582 
    583     static SplitWayResult doSplitWay(Way way, Way wayToKeep, List<Way> newWays, List<OsmPrimitive> newSelection) {
    584 
    585         Collection<Command> commandList = new ArrayList<>(newWays.size());
    586         Collection<String> nowarnroles = Main.pref.getCollection("way.split.roles.nowarn",
    587                 Arrays.asList("outer", "inner", "forward", "backward", "north", "south", "east", "west"));
    588 
     505        SplitWayCommand cmd = SplitWayCommand.splitWay(way, wayChunks, selection, x -> splitStrategy.determineWayToKeep(x));
     506        return cmd != null ? new SplitWayResult(cmd) : null;
     507    }
     508
     509    static void doSplitWay(Way way, Way wayToKeep, List<Way> newWays, List<OsmPrimitive> newSelection) {
    589510        final MapFrame map = MainApplication.getMap();
    590511        final boolean isMapModeDraw = map != null && map.mapMode == map.mapModeDraw;
    591 
    592         // Change the original way
    593         final Way changedWay = new Way(way);
    594         changedWay.setNodes(wayToKeep.getNodes());
    595         commandList.add(new ChangeCommand(way, changedWay));
    596         if (!isMapModeDraw && !newSelection.contains(way)) {
    597             newSelection.add(way);
    598         }
    599         final int indexOfWayToKeep = newWays.indexOf(wayToKeep);
    600         newWays.remove(wayToKeep);
    601 
    602         if (!isMapModeDraw) {
    603             newSelection.addAll(newWays);
    604         }
    605         for (Way wayToAdd : newWays) {
    606             commandList.add(new AddCommand(way.getDataSet(), wayToAdd));
    607         }
    608 
    609         boolean warnmerole = false;
    610         boolean warnme = false;
    611         // now copy all relations to new way also
    612 
    613         for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) {
    614             if (!r.isUsable()) {
    615                 continue;
    616             }
    617             Relation c = null;
    618             String type = Optional.ofNullable(r.get("type")).orElse("");
    619 
    620             int ic = 0;
    621             int ir = 0;
    622             List<RelationMember> relationMembers = r.getMembers();
    623             for (RelationMember rm: relationMembers) {
    624                 if (rm.isWay() && rm.getMember() == way) {
    625                     boolean insert = true;
    626                     if ("restriction".equals(type) || "destination_sign".equals(type)) {
    627                         /* this code assumes the restriction is correct. No real error checking done */
    628                         String role = rm.getRole();
    629                         if ("from".equals(role) || "to".equals(role)) {
    630                             OsmPrimitive via = findVia(r, type);
    631                             List<Node> nodes = new ArrayList<>();
    632                             if (via != null) {
    633                                 if (via instanceof Node) {
    634                                     nodes.add((Node) via);
    635                                 } else if (via instanceof Way) {
    636                                     nodes.add(((Way) via).lastNode());
    637                                     nodes.add(((Way) via).firstNode());
    638                                 }
    639                             }
    640                             Way res = null;
    641                             for (Node n : nodes) {
    642                                 if (changedWay.isFirstLastNode(n)) {
    643                                     res = way;
    644                                 }
    645                             }
    646                             if (res == null) {
    647                                 for (Way wayToAdd : newWays) {
    648                                     for (Node n : nodes) {
    649                                         if (wayToAdd.isFirstLastNode(n)) {
    650                                             res = wayToAdd;
    651                                         }
    652                                     }
    653                                 }
    654                                 if (res != null) {
    655                                     if (c == null) {
    656                                         c = new Relation(r);
    657                                     }
    658                                     c.addMember(new RelationMember(role, res));
    659                                     c.removeMembersFor(way);
    660                                     insert = false;
    661                                 }
    662                             } else {
    663                                 insert = false;
    664                             }
    665                         } else if (!"via".equals(role)) {
    666                             warnme = true;
    667                         }
    668                     } else if (!("route".equals(type)) && !("multipolygon".equals(type))) {
    669                         warnme = true;
    670                     }
    671                     if (c == null) {
    672                         c = new Relation(r);
    673                     }
    674 
    675                     if (insert) {
    676                         if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
    677                             warnmerole = true;
    678                         }
    679 
    680                         Boolean backwards = null;
    681                         int k = 1;
    682                         while (ir - k >= 0 || ir + k < relationMembers.size()) {
    683                             if ((ir - k >= 0) && relationMembers.get(ir - k).isWay()) {
    684                                 Way w = relationMembers.get(ir - k).getWay();
    685                                 if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
    686                                     backwards = Boolean.FALSE;
    687                                 } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
    688                                     backwards = Boolean.TRUE;
    689                                 }
    690                                 break;
    691                             }
    692                             if ((ir + k < relationMembers.size()) && relationMembers.get(ir + k).isWay()) {
    693                                 Way w = relationMembers.get(ir + k).getWay();
    694                                 if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
    695                                     backwards = Boolean.TRUE;
    696                                 } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
    697                                     backwards = Boolean.FALSE;
    698                                 }
    699                                 break;
    700                             }
    701                             k++;
    702                         }
    703 
    704                         int j = ic;
    705                         final List<Way> waysToAddBefore = newWays.subList(0, indexOfWayToKeep);
    706                         for (Way wayToAdd : waysToAddBefore) {
    707                             RelationMember em = new RelationMember(rm.getRole(), wayToAdd);
    708                             j++;
    709                             if (Boolean.TRUE.equals(backwards)) {
    710                                 c.addMember(ic + 1, em);
    711                             } else {
    712                                 c.addMember(j - 1, em);
    713                             }
    714                         }
    715                         final List<Way> waysToAddAfter = newWays.subList(indexOfWayToKeep, newWays.size());
    716                         for (Way wayToAdd : waysToAddAfter) {
    717                             RelationMember em = new RelationMember(rm.getRole(), wayToAdd);
    718                             j++;
    719                             if (Boolean.TRUE.equals(backwards)) {
    720                                 c.addMember(ic, em);
    721                             } else {
    722                                 c.addMember(j, em);
    723                             }
    724                         }
    725                         ic = j;
    726                     }
    727                 }
    728                 ic++;
    729                 ir++;
    730             }
    731 
    732             if (c != null) {
    733                 commandList.add(new ChangeCommand(r.getDataSet(), r, c));
    734             }
    735         }
    736         if (warnmerole) {
    737             new Notification(
    738                     tr("A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
    739                     .setIcon(JOptionPane.WARNING_MESSAGE)
    740                     .show();
    741         } else if (warnme) {
    742             new Notification(
    743                     tr("A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
    744                     .setIcon(JOptionPane.WARNING_MESSAGE)
    745                     .show();
    746         }
    747 
    748         return new SplitWayResult(
    749                 new SequenceCommand(
    750                         /* for correct i18n of plural forms - see #9110 */
    751                         trn("Split way {0} into {1} part", "Split way {0} into {1} parts", newWays.size() + 1,
    752                                 way.getDisplayName(DefaultNameFormatter.getInstance()), newWays.size() + 1),
    753                         commandList
    754                         ),
    755                         newSelection,
    756                         way,
    757                         newWays
    758                 );
    759     }
    760 
    761     static OsmPrimitive findVia(Relation r, String type) {
    762         for (RelationMember rmv : r.getMembers()) {
    763             if (("restriction".equals(type) && "via".equals(rmv.getRole()))
    764              || ("destination_sign".equals(type) && rmv.hasRole("sign", "intersection"))) {
    765                 return rmv.getMember();
    766             }
    767         }
    768         return null;
     512        final SplitWayCommand result = SplitWayCommand.doSplitWay(way, wayToKeep, newWays, !isMapModeDraw ? newSelection : null);
     513        MainApplication.undoRedo.add(result);
     514        List<? extends PrimitiveId> newSel = result.getNewSelection();
     515        if (newSel != null && !newSel.isEmpty()) {
     516            MainApplication.getLayerManager().getEditDataSet().setSelected(newSel);
     517        }
    769518    }
    770519
     
    806555     * @return the result from the split operation
    807556     * @since 12718
    808      */
     557     * @deprecated to be removed end of 2017. Use {@link #splitWay(Way, List, Collection)} instead
     558     */
     559    @Deprecated
    809560    public static SplitWayResult split(Way way, List<Node> atNodes, Collection<? extends OsmPrimitive> selection) {
    810561        List<List<Node>> chunks = buildSplitChunks(way, atNodes);
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r12763 r12828  
    2222import javax.swing.Icon;
    2323
    24 import org.openstreetmap.josm.actions.SplitWayAction;
    25 import org.openstreetmap.josm.actions.SplitWayAction.SplitWayResult;
    2624import org.openstreetmap.josm.data.osm.DataSet;
    2725import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     
    659657            return new ChangeCommand(ws.way, wnew);
    660658        } else {
    661             SplitWayResult split = SplitWayAction.splitWay(ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
    662             return split != null ? split.getCommand() : null;
     659            return SplitWayCommand.splitWay(ws.way, Arrays.asList(n1, n2), Collections.<OsmPrimitive>emptyList());
    663660        }
    664661    }
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r12825 r12828  
    7878import org.openstreetmap.josm.actions.search.SearchAction;
    7979import org.openstreetmap.josm.command.DeleteCommand;
     80import org.openstreetmap.josm.command.SplitWayCommand;
    8081import org.openstreetmap.josm.data.Bounds;
    8182import org.openstreetmap.josm.data.UndoRedoHandler;
     
    10981099        MessageNotifier.setNotifierCallback(MainApplication::notifyNewMessages);
    10991100        DeleteCommand.setDeletionCallback(DeleteAction.defaultDeletionCallback);
     1101        SplitWayCommand.setWarningNotifier(msg -> new Notification(msg).setIcon(JOptionPane.WARNING_MESSAGE).show());
    11001102        FileWatcher.registerLoader(SourceType.MAP_PAINT_STYLE, MapPaintStyleLoader::reloadStyle);
    11011103        FileWatcher.registerLoader(SourceType.TAGCHECKER_RULE, MapCSSTagChecker::reloadRule);
Note: See TracChangeset for help on using the changeset viewer.