Ticket #19859: 19859.patch

File 19859.patch, 9.1 KB (added by GerdP, 4 years ago)

show more than one conflict dialog if needed, don't mess up associatedStreet relation

  • src/org/openstreetmap/josm/plugins/terracer/TerracerAction.java

     
    6363 */
    6464public final class TerracerAction extends JosmAction {
    6565
    66     private Collection<Command> commands;
    67     private Collection<OsmPrimitive> primitives;
    68     private TagCollection tagsInConflict;
    69 
     66    private transient Collection<Command> commands;
     67    private final transient List<Pair<TagCollection, List<OsmPrimitive>>> conflicts = new ArrayList<>();
     68   
    7069    public TerracerAction() {
    7170        super(tr("Terrace a building"), "terrace",
    7271                tr("Creates individual buildings from a long building."),
     
    7574                        Shortcut.SHIFT), true);
    7675    }
    7776
    78     protected static Set<Relation> findAssociatedStreets(Collection<OsmPrimitive> objects) {
     77    private static Set<Relation> findAssociatedStreets(Collection<OsmPrimitive> objects) {
    7978        Set<Relation> result = new HashSet<>();
    8079        if (objects != null) {
    8180            for (OsmPrimitive c : objects) {
     
    180179
    181180        } catch (InvalidUserInputException ex) {
    182181            Logging.warn("Terracer: "+ex.getMessage());
    183             new ExtendedDialog(MainApplication.getMainFrame(), tr("Invalid selection"), new String[] {"OK"})
    184                 .setButtonIcons(new String[] {"ok"}).setIcon(JOptionPane.INFORMATION_MESSAGE)
     182            new ExtendedDialog(MainApplication.getMainFrame(), tr("Invalid selection"), "OK")
     183                .setButtonIcons("ok").setIcon(JOptionPane.INFORMATION_MESSAGE)
    185184                .setContent(tr("Select a single, closed way of at least four nodes. " +
    186185                    "(Optionally you can also select a street for the addr:street tag " +
    187186                    "and a node to mark the start of numbering.)"))
     
    232231
    233232    private void cleanup() {
    234233        commands = null;
    235         primitives = null;
    236         tagsInConflict = null;
     234        conflicts.clear();
    237235    }
    238236
    239237    public Integer getNumber(String number) {
     
    246244
    247245    /**
    248246     * Sorts the house number nodes according their numbers only
    249      *
    250      * @param house
    251      *            number nodes
    252247     */
    253248    static class HousenumberNodeComparator implements Comparator<Node> {
    254249        private final Pattern pat = Pattern.compile("^(\\d+)\\s*(.*)");
     
    314309                boolean keepOutline, String buildingValue) throws UserCancelException {
    315310        final int nb;
    316311        Integer to = null, from = null;
    317         if (housenumbers == null || housenumbers.isEmpty()) {
     312        if (housenumbers.isEmpty()) {
    318313            to = getNumber(end);
    319314            from = getNumber(start);
    320315            if (to != null && from != null) {
     
    337332
    338333        final boolean swap = init != null && (interp.a.lastNode().equals(init) || interp.b.lastNode().equals(init));
    339334
    340         final double frontLength = wayLength(interp.a);
    341         final double backLength = wayLength(interp.b);
     335        final double frontLength = interp.a.getLength();
     336        final double backLength = interp.b.getLength();
    342337
    343338        // new nodes array to hold all intermediate nodes
    344339        // This set will contain at least 4 existing nodes from the original outline
     
    430425            }
    431426        }
    432427
    433         UndoRedoHandler.getInstance().add(createTerracingCommand(outline));
     428        UndoRedoHandler.getInstance().add(createTerracingCommand());
    434429        if (nb <= 1 && street != null) {
    435430            // Select the way (for quick selection of a new house (with the same way))
    436431            MainApplication.getLayerManager().getEditDataSet().setSelected(street);
     
    470465        this.commands.add(new AddCommand(getLayerManager().getEditDataSet(), associatedStreet));
    471466    }
    472467
    473     private Command createTerracingCommand(final Way outline) {
     468    private Command createTerracingCommand() {
    474469        return new SequenceCommand(tr("Terrace"), commands) {
    475470            @Override
    476471            public boolean executeCommand() {
    477472                boolean result = super.executeCommand();
    478                 if (result && tagsInConflict != null) {
     473                if (result && !conflicts.isEmpty()) {
    479474                    try {
    480                         // Build conflicts commands only after all primitives have been added to dataset to fix #8942
    481                         List<Command> conflictCommands = CombinePrimitiveResolverDialog.launchIfNecessary(
    482                                 tagsInConflict, primitives, Collections.singleton(outline));
    483                         if (!conflictCommands.isEmpty()) {
    484                             List<Command> newCommands = new ArrayList<>(commands);
    485                             newCommands.addAll(conflictCommands);
    486                             setSequence(newCommands.toArray(new Command[0]));
    487                             // Run conflicts commands
    488                             for (int i = 0; i < conflictCommands.size(); i++) {
    489                                 result = conflictCommands.get(i).executeCommand();
    490                                 if (!result && !continueOnError) {
    491                                     setSequenceComplete(false);
    492                                     undoCommands(commands.size()+i-1);
    493                                     return false;
     475                        for (Pair<TagCollection, List<OsmPrimitive>> conflict : conflicts) {
     476                            // Build conflicts commands only after all primitives have been added to dataset to fix #8942
     477                            OsmPrimitive target = getLayerManager().getEditDataSet().getPrimitiveById(conflict.b.get(1));
     478                            if (target == null)
     479                                continue;
     480                            List<Command> conflictCommands = CombinePrimitiveResolverDialog.launchIfNecessary(
     481                                    conflict.a, Collections.singleton(conflict.b.get(0)),
     482                                    Collections.singleton(target));
     483                            if (!conflictCommands.isEmpty()) {
     484                                List<Command> newCommands = new ArrayList<>(commands);
     485                                newCommands.addAll(conflictCommands);
     486                                setSequence(newCommands.toArray(new Command[0]));
     487                                // Run conflicts commands
     488                                for (int i = 0; i < conflictCommands.size(); i++) {
     489                                    result = conflictCommands.get(i).executeCommand();
     490                                    if (!result && !continueOnError) {
     491                                        setSequenceComplete(false);
     492                                        undoCommands(commands.size()+i-1);
     493                                        return false;
     494                                    }
    494495                                }
    495496                            }
    496497                        }
     
    511512     * @param streetName the name of a street (may be null). Used if not null and street is null.
    512513     * @param associatedStreet The associated street. Used to determine if addr:street should be set or not.
    513514     * @param buildingValue The value for {@code building} key to add
    514      * @return {@code outline}
    515515     * @throws UserCancelException if user cancels the operation
    516516     */
    517517    private void addressBuilding(Way outline, Way street, String streetName, Relation associatedStreet,
     
    521521        boolean numberAdded = false;
    522522        Map<String, String> tags = new HashMap<>();
    523523        if (houseNum != null) {
    524             primitives = Arrays.asList(new OsmPrimitive[]{houseNum, outline});
     524            List<OsmPrimitive> primitives = Arrays.asList(houseNum, outline);
    525525
    526526            TagCollection tagsToCopy = TagCollection.unionOfAllPrimitives(primitives).getTagsFor(houseNum.keySet());
    527             tagsInConflict = tagsToCopy.getTagsFor(tagsToCopy.getKeysWithMultipleValues());
     527            TagCollection tagsInConflict = tagsToCopy.getTagsFor(tagsToCopy.getKeysWithMultipleValues());
     528            if (!tagsInConflict.isEmpty()) {
     529                conflicts.add(Pair.create(tagsInConflict, primitives));
     530            }
    528531            tagsToCopy = tagsToCopy.minus(tagsInConflict).minus(TagCollection.from(outline));
    529532
    530533            for (Tag tag : tagsToCopy) {
     
    582585    }
    583586
    584587    /**
    585      * Calculates the great circle length of a way by summing the great circle
    586      * distance of each pair of nodes.
    587      *
    588      * @param w The way to calculate length of.
    589      * @return The length of the way.
    590      */
    591     private double wayLength(Way w) {
    592         double length = 0.0;
    593         for (Pair<Node, Node> p : w.getNodePairs(false)) {
    594             length += p.a.getCoor().greatCircleDistance(p.b.getCoor());
    595         }
    596         return length;
    597     }
    598 
    599     /**
    600588     * Given a way, try and find a definite front and back by looking at the
    601589     * segments to find the "sides". Sides are assumed to be single segments
    602590     * which cannot be contiguous.