Ignore:
Timestamp:
2011-06-26T02:46:22+02:00 (13 years ago)
Author:
benshu
Message:
Location:
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/JunctionPane.java

    r26154 r26182  
    3333       
    3434        public void mousePressed(MouseEvent e) {
    35             setFocusable(true);
     35            JunctionPane.this.requestFocus();
     36           
    3637            button = e.getButton();
    3738           
     
    158159        setJunction(container);
    159160       
     161        setFocusable(true);
     162       
    160163        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), "refresh");
    161164        getActionMap().put("refresh", new AbstractAction() {
     
    229232                rotation += Math.PI / 180;
    230233                setState(new State.Dirty(state));
     234            }
     235        });
     236       
     237        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
     238        getActionMap().put("delete", new AbstractAction() {
     239            private static final long serialVersionUID = 1L;
     240           
     241            @Override
     242            public void actionPerformed(ActionEvent e) {
     243                setState(state.delete());
    231244            }
    232245        });
     
    276289   
    277290    private void setState(State state) {
     291       
    278292        if (state instanceof State.AllTurns) {
    279293            dirty = true;
     
    282296            container = container.recalculate();
    283297            dirty = true;
    284             this.state = new State.Default();
     298            setState(((State.Invalid) state).unwrap());
    285299        } else if (state instanceof State.Dirty) {
    286300            dirty = true;
    287             this.state = ((State.Dirty) state).unwrap();
     301            setState(((State.Dirty) state).unwrap());
    288302        } else {
    289             this.state = state;
     303            this.state = state.carryOver(container);
    290304        }
    291305       
     
    431445        dot(g2d, p, r, Color.RED);
    432446    }
     447   
     448    void refresh() {
     449        if (state != null) {
     450            setState(new State.Invalid(state));
     451        }
     452    }
    433453}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/LaneGui.java

    r26154 r26182  
    3939                g2d.fill(circle);
    4040               
    41                 final String len = METER_FORMAT.format(getModel().getLength());
     41                final String len = METER_FORMAT.format(getLength() * getRoad().getContainer().getMpp());
    4242                final Rectangle2D bounds = circle.getBounds2D();
    4343                g2d.setFont(g2d.getFont().deriveFont(Font.BOLD, (float) bounds.getHeight()));
     
    7272        @Override
    7373        State drag(double x, double y, InteractiveElement target, State old) {
    74             move(x + dragDelta.getX(), y + dragDelta.getY());
     74            move(x + dragDelta.getX(), y + dragDelta.getY(), false);
    7575            return new State.Dirty(old);
    7676        }
    7777       
    78         void move(double x, double y) {
     78        @Override
     79        State drop(double x, double y, InteractiveElement target, State old) {
     80            move(x + dragDelta.getX(), y + dragDelta.getY(), true);
     81            return old;
     82        }
     83       
     84        void move(double x, double y, boolean updateModel) {
    7985            final double r = getRoad().connectorRadius;
    8086           
    8187            final double offset = getRoad().getOffset(x, y);
    82             final double newLength = getModel().getOutgoingRoadEnd().isFromEnd() ? offset : getRoad().getLength() - offset;
    83             if (newLength > 0) {
     88            final double newLength = getModel().getOutgoingRoadEnd().isFromEnd() ? offset : getRoad().getLength()
     89                    - offset;
     90           
     91            length = newLength;
     92            if (updateModel && newLength > 0) {
    8493                getModel().setLength(newLength * getRoad().getContainer().getMpp());
    8594            }
     
    169178       
    170179        private boolean isActive(State state) {
    171             return state instanceof State.OutgoingActive && LaneGui.this.equals(((State.OutgoingActive) state).getLane());
     180            return state instanceof State.OutgoingActive
     181                    && LaneGui.this.equals(((State.OutgoingActive) state).getLane());
    172182        }
    173183       
     
    234244                final RoadGui.ViaConnector a = s.getViaConnectors().get(i);
    235245                final RoadGui.ViaConnector b = s.getViaConnectors().get(i + 1);
    236                 assert a.getRoadEnd().getOppositeEnd().equals(b);
     246                assert a.getRoadEnd().getOppositeEnd().equals(b.getRoadEnd());
    237247                via.add(a.getRoadEnd().getRoad());
    238248            }
     
    271281   
    272282    private Shape clip;
     283    private double length;
    273284   
    274285    public LaneGui(RoadGui road, Lane lane) {
     
    276287        this.lane = lane;
    277288        this.lengthSlider = lane.isExtra() ? new LengthSlider() : null;
     289        this.length = lane.isExtra() ? lane.getLength() / road.getContainer().getMpp() : Double.NaN;
    278290    }
    279291   
    280292    public double getLength() {
    281         return getModel().isExtra() ? lane.getLength() / getRoad().getContainer().getMpp() : getRoad().getLength();
     293        return lane.isExtra() ? length : road.getLength();
    282294    }
    283295   
     
    305317        final Lane leftModel = left == null ? null : left.getModel();
    306318        final double leftLength = leftModel == null
    307             || !leftModel.getOutgoingRoadEnd().equals(getModel().getOutgoingRoadEnd()) ? Double.NEGATIVE_INFINITY
    308             : leftModel.getKind() == Lane.Kind.EXTRA_LEFT ? left.getLength() : L;
     319                || !leftModel.getOutgoingRoadEnd().equals(getModel().getOutgoingRoadEnd()) ? Double.NEGATIVE_INFINITY
     320                : leftModel.getKind() == Lane.Kind.EXTRA_LEFT ? left.getLength() : L;
    309321       
    310322        final Path outer;
     
    320332            if (L > leftLength) {
    321333                innerLine.append(inner.subpath(max(0, leftLength + WW), L).getIterator(), leftLength >= 0
    322                     || getModel().getOutgoingRoadEnd().isFromEnd());
     334                        || getModel().getOutgoingRoadEnd().isFromEnd());
    323335                final Point2D op = outer.getPoint(L + WW);
    324336                innerLine.lineTo(op.getX(), op.getY());
     
    335347            if (leftLength < L) {
    336348                innerLine.append(inner.subpath(max(0, leftLength + WW), L).getIterator(), leftLength >= 0
    337                     || getModel().getOutgoingRoadEnd().isFromEnd());
     349                        || getModel().getOutgoingRoadEnd().isFromEnd());
    338350            }
    339351        }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/State.java

    r26154 r26182  
    1111import org.openstreetmap.josm.plugins.turnlanes.model.Road;
    1212
    13 interface State {
    14     public class AllTurns implements State {
     13abstract class State {
     14    static class AllTurns extends State {
    1515        private final State wrapped;
    1616       
     
    2222            return wrapped;
    2323        }
    24     }
    25    
    26     public class Connecting implements State {
     24       
     25        @Override
     26        State carryOver(GuiContainer newContainer) {
     27            return new AllTurns(wrapped.carryOver(newContainer));
     28        }
     29    }
     30   
     31    static class Connecting extends State {
    2732        private final Lane lane;
    2833        private final List<RoadGui.ViaConnector> vias;
     
    9196    }
    9297   
    93     public class Invalid implements State {
     98    static class Invalid extends State {
    9499        private final State wrapped;
    95100       
     
    103108    }
    104109   
    105     public class Dirty implements State {
     110    static class Dirty extends State {
    106111        private final State wrapped;
    107112       
     
    113118            return wrapped;
    114119        }
    115     }
    116    
    117     class Default implements State {
     120       
     121        @Override
     122        State carryOver(GuiContainer newContainer) {
     123            return new Dirty(wrapped.carryOver(newContainer));
     124        }
     125    }
     126   
     127    static class Default extends State {
    118128        public Default() {}
    119129    }
    120130   
    121     class IncomingActive implements State {
     131    static class IncomingActive extends State {
    122132        private final Road.End roadEnd;
    123133       
     
    129139            return roadEnd;
    130140        }
    131     }
    132    
    133     class OutgoingActive implements State {
     141       
     142        @Override
     143        State carryOver(GuiContainer newContainer) {
     144            if (newContainer.getModel().equals(roadEnd.getRoad().getContainer())) {
     145                return this;
     146            }
     147           
     148            final Junction newJunction = newContainer.getModel().getJunction(roadEnd.getJunction().getNode());
     149           
     150            for (Road.End e : newJunction.getRoadEnds()) {
     151                if (e.isToEnd() && e.getWay().equals(roadEnd.getWay())) {
     152                    return new IncomingActive(e);
     153                }
     154            }
     155           
     156            return new Default();
     157        }
     158    }
     159   
     160    static class OutgoingActive extends State {
    134161        private final LaneGui lane;
    135162       
     
    141168            return lane;
    142169        }
     170       
     171        @Override
     172        State delete() {
     173            if (!lane.getModel().isExtra()) {
     174                return this;
     175            }
     176           
     177            lane.getModel().remove();
     178           
     179            return new Invalid(this);
     180        }
     181       
     182        @Override
     183        State carryOver(GuiContainer newContainer) {
     184            if (newContainer.equals(lane.getContainer())) {
     185                return this;
     186            }
     187           
     188            final Lane model = lane.getModel();
     189            final Junction newJunction = newContainer.getModel().getJunction(model.getOutgoingJunction().getNode());
     190           
     191            for (Road.End e : newJunction.getRoadEnds()) {
     192                if (e.isToEnd() && e.getWay().equals(model.getOutgoingRoadEnd().getWay())) {
     193                    for (Lane l : e.getLanes()) { // e.getLane(...) can fail on lane removal
     194                        if (l.getKind() == model.getKind() && l.getIndex() == model.getIndex()) {
     195                            return new OutgoingActive(newContainer.getGui(l));
     196                        }
     197                    }
     198                   
     199                    break;
     200                }
     201            }
     202           
     203            return new Default();
     204        }
     205    }
     206   
     207    State delete() {
     208        return this;
     209    }
     210   
     211    State carryOver(GuiContainer newContainer) {
     212        return this;
    143213    }
    144214}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/TurnLanesDialog.java

    r26154 r26182  
    99import java.util.Collection;
    1010import java.util.Collections;
     11import java.util.HashSet;
    1112import java.util.List;
     13import java.util.Set;
    1214
    1315import javax.swing.Action;
     
    1719import javax.swing.JToggleButton;
    1820
     21import org.openstreetmap.josm.Main;
    1922import org.openstreetmap.josm.actions.JosmAction;
    20 import org.openstreetmap.josm.Main;
    2123import org.openstreetmap.josm.data.SelectionChangedListener;
    2224import org.openstreetmap.josm.data.osm.DataSet;
     
    2426import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2527import org.openstreetmap.josm.data.osm.Way;
     28import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
     29import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
     30import org.openstreetmap.josm.data.osm.event.DataSetListener;
     31import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
     32import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
     33import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
     34import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
     35import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
     36import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
     37import org.openstreetmap.josm.gui.MapView;
     38import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
    2639import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
     40import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2741import org.openstreetmap.josm.plugins.turnlanes.model.ModelContainer;
     42import org.openstreetmap.josm.plugins.turnlanes.model.UnexpectedDataException;
    2843
    2944public class TurnLanesDialog extends ToggleDialog {
    3045    private class EditAction extends JosmAction {
    3146        private static final long serialVersionUID = 4114119073563457706L;
     47       
    3248        public EditAction() {
    33             super(tr("Edit"), "dialogs/edit",
    34             tr("Edit turn relations and lane lengths for selected node."), null, false);
     49            super(tr("Edit"), "dialogs/edit", tr("Edit turn relations and lane lengths for selected node."), null,
     50                    false);
    3551            putValue("toolbar", "turnlanes/edit");
    3652            Main.toolbar.register(this);
    3753        }
    38 
     54       
    3955        @Override
    4056        public void actionPerformed(ActionEvent e) {
     
    4258            cl.show(body, CARD_EDIT);
    4359            editing = true;
    44         }
    45     }
    46 
     60            editButton.setSelected(true);
     61        }
     62    }
     63   
    4764    private class ValidateAction extends JosmAction {
    4865        private static final long serialVersionUID = 7510740945725851427L;
     66       
    4967        public ValidateAction() {
    50             super(tr("Validate"), "dialogs/validator",
    51             tr("Validate turn- and lane-length-relations for consistency."), null, false);
     68            super(tr("Validate"), "dialogs/validator", tr("Validate turn- and lane-length-relations for consistency."),
     69                    null, false);
    5270            putValue("toolbar", "turnlanes/validate");
    5371            Main.toolbar.register(this);
    5472        }
    55 
     73       
    5674        @Override
    5775        public void actionPerformed(ActionEvent e) {
     
    5977            cl.show(body, CARD_VALIDATE);
    6078            editing = false;
    61         }
    62     }
    63 
     79            validateButton.setSelected(true);
     80        }
     81    }
     82   
     83    private final DataSetListener dataSetListener = new DataSetListener() {
     84        @Override
     85        public void wayNodesChanged(WayNodesChangedEvent event) {
     86            refresh();
     87        }
     88       
     89        @Override
     90        public void tagsChanged(TagsChangedEvent event) {
     91            refresh();
     92           
     93        }
     94       
     95        @Override
     96        public void relationMembersChanged(RelationMembersChangedEvent event) {
     97            refresh();
     98        }
     99       
     100        @Override
     101        public void primtivesRemoved(PrimitivesRemovedEvent event) {
     102            refresh();
     103        }
     104       
     105        @Override
     106        public void primtivesAdded(PrimitivesAddedEvent event) {
     107            refresh();
     108        }
     109       
     110        @Override
     111        public void otherDatasetChange(AbstractDatasetChangedEvent event) {
     112            refresh();
     113        }
     114       
     115        @Override
     116        public void nodeMoved(NodeMovedEvent event) {
     117            refresh();
     118        }
     119       
     120        @Override
     121        public void dataChanged(DataChangedEvent event) {
     122            refresh();
     123        }
     124       
     125        private void refresh() {
     126            if (editing) {
     127                junctionPane.refresh();
     128            }
     129        }
     130    };
     131   
    64132    private final Action editAction = new EditAction();
    65133    private final Action validateAction = new ValidateAction();
    66 
     134   
    67135    private static final long serialVersionUID = -1998375221636611358L;
    68 
     136   
    69137    private static final String CARD_EDIT = "EDIT";
    70138    private static final String CARD_VALIDATE = "VALIDATE";
    71139    private static final String CARD_ERROR = "ERROR";
    72 
     140   
    73141    private final JPanel body = new JPanel();
    74142    private final JunctionPane junctionPane = new JunctionPane(null);
    75143    private final JLabel error = new JLabel();
    76 
     144   
     145    private final JToggleButton editButton = new JToggleButton(editAction);
     146    private final JToggleButton validateButton = new JToggleButton(validateAction);
     147   
     148    private final Set<OsmPrimitive> selected = new HashSet<OsmPrimitive>();
     149   
    77150    private boolean editing = true;
    78 
     151   
    79152    public TurnLanesDialog() {
    80153        super(tr("Turn Lanes"), "turnlanes.png", tr("Edit turn lanes"), null, 200);
    81 
     154       
     155        MapView.addEditLayerChangeListener(new EditLayerChangeListener() {
     156            @Override
     157            public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     158                if (oldLayer != null) {
     159                    oldLayer.data.removeDataSetListener(dataSetListener);
     160                }
     161               
     162                if (newLayer != null) {
     163                    newLayer.data.addDataSetListener(dataSetListener);
     164                }
     165            }
     166        });
     167       
    82168        DataSet.addSelectionListener(new SelectionChangedListener() {
    83169            @Override
    84170            public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     171                if (selected.equals(new HashSet<OsmPrimitive>(newSelection))) {
     172                    return;
     173                }
     174                selected.clear();
     175                selected.addAll(newSelection);
     176               
    85177                final Collection<OsmPrimitive> s = Collections.unmodifiableCollection(newSelection);
    86178                final List<Node> nodes = OsmPrimitive.getFilteredList(s, Node.class);
    87179                final List<Way> ways = OsmPrimitive.getFilteredList(s, Way.class);
    88 
     180               
    89181                if (nodes.isEmpty()) {
    90182                    setJunction(null);
    91183                    return;
    92184                }
    93 
     185               
    94186                try {
    95187                    setJunction(ModelContainer.create(nodes, ways));
     188                } catch (UnexpectedDataException e) {
     189                    displayError(e);
     190                    return;
    96191                } catch (RuntimeException e) {
    97192                    displayError(e);
     
    100195            }
    101196        });
    102 
     197       
    103198        final JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 4, 4));
    104199        final ButtonGroup group = new ButtonGroup();
    105         final JToggleButton editButton = new JToggleButton(editAction);
    106         final JToggleButton validateButton = new JToggleButton(validateAction);
    107200        group.add(editButton);
    108201        group.add(validateButton);
    109202        buttonPanel.add(editButton);
    110203        buttonPanel.add(validateButton);
    111 
     204       
    112205        body.setLayout(new CardLayout(4, 4));
    113 
     206       
    114207        add(buttonPanel, BorderLayout.SOUTH);
    115208        add(body, BorderLayout.CENTER);
    116 
     209       
    117210        body.add(junctionPane, CARD_EDIT);
    118211        body.add(new ValidationPanel(), CARD_VALIDATE);
    119212        body.add(error, CARD_ERROR);
    120 
     213       
    121214        editButton.doClick();
    122215    }
    123 
     216   
     217    void displayError(UnexpectedDataException e) {
     218        if (editing) {
     219            if (e.getKind() == UnexpectedDataException.Kind.MISSING_TAG
     220                    && UnexpectedDataException.Kind.MISSING_TAG.format("lanes").equals(e.getMessage())) {
     221               
     222                error.setText("<html>The number of lanes is not specified for one or more roads;"
     223                        + " please add missing lanes tags.</html>");
     224            } else {
     225                displayError((RuntimeException) e);
     226            }
     227           
     228            final CardLayout cl = (CardLayout) body.getLayout();
     229            cl.show(body, CARD_ERROR);
     230        }
     231    }
     232   
    124233    void displayError(RuntimeException e) {
    125234        if (editing) {
    126235            e.printStackTrace();
    127 
     236           
    128237            error.setText("<html>An error occured while constructing the model."
    129                 + " Please run the validator to make sure the data is consistent.<br><br>Error: " + e.getMessage()
    130                 + "</html>");
    131 
     238                    + " Please run the validator to make sure the data is consistent.<br><br>Error: " + e.getMessage()
     239                    + "</html>");
     240           
    132241            final CardLayout cl = (CardLayout) body.getLayout();
    133242            cl.show(body, CARD_ERROR);
    134243        }
    135244    }
    136 
     245   
    137246    void setJunction(ModelContainer mc) {
    138247        if (mc != null && editing) {
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Lane.java

    r26154 r26182  
    11package org.openstreetmap.josm.plugins.turnlanes.model;
    22
     3import static org.openstreetmap.josm.tools.I18n.tr;
     4
    35import java.util.ArrayList;
     6import java.util.Collections;
     7import java.util.Iterator;
    48import java.util.List;
    59import java.util.Set;
    610
     11import org.openstreetmap.josm.Main;
    712import org.openstreetmap.josm.data.osm.Node;
    813import org.openstreetmap.josm.data.osm.Relation;
    914import org.openstreetmap.josm.data.osm.RelationMember;
    1015import org.openstreetmap.josm.data.osm.Way;
    11 import org.openstreetmap.josm.plugins.turnlanes.CollectionUtils;
    1216
    1317public class Lane {
     
    2731       
    2832        i = 0;
    29         for (double l : CollectionUtils.reverse(roadEnd.getLengths(Kind.EXTRA_LEFT))) {
     33        for (double l : roadEnd.getLengths(Kind.EXTRA_LEFT)) {
    3034            result.add(new Lane(roadEnd, --i, Kind.EXTRA_LEFT, l));
    3135        }
     36        Collections.reverse(result);
    3237       
    3338        final int regulars = getRegularCount(roadEnd.getWay(), roadEnd.getJunction().getNode());
     
    5358                final Double length = Double.parseDouble(s.trim());
    5459               
    55                 if (length > lengthBound) {
     60                if (length >= lengthBound) {
    5661                    result.add(length);
    5762                }
     
    139144        }
    140145       
     146        this.length = length;
     147       
    141148        // TODO if needed, increase length of other lanes
    142149        getOutgoingRoadEnd().updateLengths();
    143        
    144         this.length = length;
    145150    }
    146151   
     
    174179   
    175180    public void addTurn(List<Road> via, Road.End to) {
    176         assert equals(to.getJunction());
     181        final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Add turn"));
    177182       
    178183        Relation existing = null;
     
    203208            r.addMember(new RelationMember(Constants.TURN_ROLE_TO, to.getWay()));
    204209           
    205             getOutgoingJunction().getNode().getDataSet().addPrimitive(r);
     210            cmd.add(r);
    206211        } else {
    207212            r = existing;
     
    211216        final List<Integer> lanes = Turn.indices(r, key);
    212217        lanes.add(getIndex());
    213         r.put(key, Turn.join(lanes));
     218        cmd.backup(r).put(key, Turn.join(lanes));
     219       
     220        Main.main.undoRedo.add(cmd);
    214221    }
    215222   
    216223    public Set<Turn> getTurns() {
    217         return Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getOutgoingRoadEnd().getWay());
     224        final Set<Turn> turns = Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getOutgoingRoadEnd().getWay());
     225       
     226        final Iterator<Turn> it = turns.iterator();
     227        while (it.hasNext()) {
     228            final Turn t = it.next();
     229           
     230            if (!t.getFrom().equals(this)) {
     231                it.remove();
     232            }
     233        }
     234       
     235        return turns;
     236    }
     237   
     238    public void remove() {
     239        if (!isExtra()) {
     240            throw new UnsupportedOperationException();
     241        }
     242       
     243        final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Delete lane."));
     244       
     245        for (Turn t : getTurns()) {
     246            t.remove(cmd);
     247        }
     248       
     249        getOutgoingRoadEnd().removeLane(cmd, this);
     250       
     251        Main.main.undoRedo.add(cmd);
    218252    }
    219253}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/ModelContainer.java

    r26154 r26182  
    3333            closed = true;
    3434           
    35             for (Node n : closedNodes) {
     35            for (Node n : new ArrayList<Node>(closedNodes)) {
    3636                for (Way w : Utils.filterRoads(n.getReferrers())) {
    3737                    if (w.isFirstLastNode(n)) {
     
    4141                }
    4242               
    43                 for (Way w : closedWays) {
     43                for (Way w : new ArrayList<Way>(closedWays) ) {
    4444                    closed &= close(closedNodes, closedWays, w, Constants.TURN_ROLE_VIA);
    4545                }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Road.java

    r26154 r26182  
    99import java.util.Set;
    1010
     11import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.data.osm.AbstractPrimitive;
    1113import org.openstreetmap.josm.data.osm.Node;
    1214import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    109111            assert kind == Lane.Kind.EXTRA_LEFT || kind == Lane.Kind.EXTRA_RIGHT;
    110112           
     113            final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Add lane");
     114           
    111115            final boolean left = kind == Lane.Kind.EXTRA_LEFT;
    112116            final Relation rel = left ? lengthsLeft : lengthsRight;
     
    129133            final String old = target.get(key);
    130134            if (old == null) {
    131                 target.put(key, lengthStr);
     135                cmd.backup(target).put(key, lengthStr);
    132136            } else {
    133                 target.put(key, old + Constants.SEPARATOR + lengthStr);
    134             }
     137                cmd.backup(target).put(key, old + Constants.SEPARATOR + lengthStr);
     138            }
     139           
     140            Main.main.undoRedo.add(cmd);
    135141        }
    136142       
     
    152158       
    153159        void updateLengths() {
     160            final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Change lane length");
     161           
    154162            for (final boolean left : Arrays.asList(true, false)) {
    155163                final Lane.Kind kind = left ? Lane.Kind.EXTRA_LEFT : Lane.Kind.EXTRA_RIGHT;
     
    169177               
    170178                lengths.setLength(lengths.length() - Constants.SEPARATOR.length());
    171                 r.put(left ? Constants.LENGTHS_KEY_LENGTHS_LEFT : Constants.LENGTHS_KEY_LENGTHS_RIGHT, lengths.toString());
    172             }
     179                cmd.backup(r).put(left ? Constants.LENGTHS_KEY_LENGTHS_LEFT : Constants.LENGTHS_KEY_LENGTHS_RIGHT,
     180                        lengths.toString());
     181            }
     182           
     183            Main.main.undoRedo.add(cmd);
    173184        }
    174185       
     
    220231            }
    221232        }
     233       
     234        void removeLane(GenericCommand cmd, Lane lane) {
     235            assert lane.getKind() == Lane.Kind.EXTRA_LEFT || lane.getKind() == Lane.Kind.EXTRA_RIGHT;
     236           
     237            final boolean left = lane.getKind() == Lane.Kind.EXTRA_LEFT;
     238            final Relation rel = left ? lengthsLeft : lengthsRight;
     239           
     240            for (Turn t : Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getWay())) {
     241                t.fixReferences(cmd, left, lane.getIndex());
     242            }
     243           
     244            final double extraLength = left ? extraLengthLeft : extraLengthRight;
     245            final List<Double> newLengths = new ArrayList<Double>();
     246            int i = Math.abs(lane.getIndex());
     247            final String key = left ? Constants.LENGTHS_KEY_LENGTHS_LEFT : Constants.LENGTHS_KEY_LENGTHS_RIGHT;
     248            for (double l : Lane.loadLengths(rel, key, 0)) {
     249                if (l < extraLength) {
     250                    newLengths.add(l);
     251                } else if (--i != 0) {
     252                    newLengths.add(l);
     253                }
     254            }
     255           
     256            final AbstractPrimitive bRel = cmd.backup(rel);
     257            bRel.put(key, join(newLengths));
     258           
     259            if (bRel.get(Constants.LENGTHS_KEY_LENGTHS_LEFT) == null
     260                    && bRel.get(Constants.LENGTHS_KEY_LENGTHS_RIGHT) == null) {
     261                bRel.setDeleted(true);
     262            }
     263        }
    222264    }
    223265   
     
    247289        if (left.size() > 1) {
    248290            throw new IllegalArgumentException("Way is in " + left.size()
    249                 + " lengths relations for given direction, both specifying left lane lengths.");
     291                    + " lengths relations for given direction, both specifying left lane lengths.");
    250292        }
    251293       
    252294        if (right.size() > 1) {
    253295            throw new IllegalArgumentException("Way is in " + right.size()
    254                 + " lengths relations for given direction, both specifying right lane lengths.");
     296                    + " lengths relations for given direction, both specifying right lane lengths.");
    255297        }
    256298       
    257299        return new Pair<Relation, Relation>( //
    258             left.isEmpty() ? null : left.get(0), //
    259             right.isEmpty() ? null : right.get(0) //
     300                left.isEmpty() ? null : left.get(0), //
     301                right.isEmpty() ? null : right.get(0) //
    260302        );
    261303    }
     
    263305    /**
    264306     * @param r
    265      *          lengths relation
     307     *            lengths relation
    266308     * @param w
    267      *          the way to check for
     309     *            the way to check for
    268310     * @param n
    269      *          first or last node of w, determines the direction
     311     *            first or last node of w, determines the direction
    270312     * @return whether the turn lane goes into the direction of n
    271313     */
     
    293335       
    294336        this.container = container;
    295         this.route = lengthsRelations.a == null && lengthsRelations.b == null ? Route.create(Arrays.asList(w), n) : Route
    296             .load(lengthsRelations.a, lengthsRelations.b, w);
     337        this.route = lengthsRelations.a == null && lengthsRelations.b == null ? Route.create(Arrays.asList(w), n)
     338                : Route.load(lengthsRelations.a, lengthsRelations.b, w);
    297339        this.fromEnd = new End(true, container.getOrCreateJunction(route.getFirstSegment().getStart()));
    298340        this.toEnd = new End(false, j, lengthsRelations.a, lengthsRelations.b);
     
    322364    }
    323365   
    324     private String toLengthString(double length) {
     366    private static String join(List<Double> list) {
     367        if (list.isEmpty()) {
     368            return null;
     369        }
     370       
     371        final StringBuilder builder = new StringBuilder(list.size() * (4 + Constants.SEPARATOR.length()));
     372       
     373        for (double e : list) {
     374            builder.append(toLengthString(e)).append(Constants.SEPARATOR);
     375        }
     376       
     377        builder.setLength(builder.length() - Constants.SEPARATOR.length());
     378        return builder.toString();
     379    }
     380   
     381    private static String toLengthString(double length) {
    325382        final DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
    326383        dfs.setDecimalSeparator('.');
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Turn.java

    r26154 r26182  
    11package org.openstreetmap.josm.plugins.turnlanes.model;
     2
     3import static org.openstreetmap.josm.tools.I18n.tr;
    24
    35import java.util.ArrayList;
     
    911import java.util.Set;
    1012
     13import org.openstreetmap.josm.Main;
    1114import org.openstreetmap.josm.data.osm.Node;
    1215import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    2124       
    2225        for (Relation r : OsmPrimitive.getFilteredList(primitive.getReferrers(), Relation.class)) {
    23             if (!r.get("type").equals(Constants.TYPE_TURNS)) {
     26            if (!r.isUsable() || !r.get("type").equals(Constants.TYPE_TURNS)) {
    2427                continue;
    2528            }
     
    7174           
    7275            final Iterator<Route.Segment> it2 = (v.getRoute().getFirstSegment().getWay().equals(w) ? v.getRoute()
    73                 .getSegments() : CollectionUtils.reverse(v.getRoute().getSegments())).iterator();
     76                    .getSegments() : CollectionUtils.reverse(v.getRoute().getSegments())).iterator();
    7477            it2.next(); // first is done
    7578           
     
    123126        final Set<Turn> result = new HashSet<Turn>();
    124127        for (int i : indices(r, Constants.TURN_KEY_LANES)) {
    125             result.add(new Turn(r, fromRoadEnd.getLane(Lane.Kind.REGULAR, i), Collections.<Road> emptyList(), toRoadEnd));
     128            result
     129                    .add(new Turn(r, fromRoadEnd.getLane(Lane.Kind.REGULAR, i), Collections.<Road> emptyList(),
     130                            toRoadEnd));
    126131        }
    127132        for (int i : indices(r, Constants.TURN_KEY_EXTRA_LANES)) {
     
    176181   
    177182    public void remove() {
     183        final GenericCommand cmd = new GenericCommand(relation.getDataSet(), tr("Delete turn."));
     184       
     185        remove(cmd);
     186       
     187        Main.main.undoRedo.add(cmd);
     188    }
     189   
     190    void remove(GenericCommand cmd) {
    178191        final List<Integer> lanes = indices(relation, Constants.TURN_KEY_LANES);
    179192        final List<Integer> extraLanes = indices(relation, Constants.TURN_KEY_EXTRA_LANES);
    180193       
     194        // TODO understand & document
    181195        if (lanes.size() + extraLanes.size() == 1 && (from.isExtra() ^ !lanes.isEmpty())) {
    182             relation.getDataSet().removePrimitive(relation.getPrimitiveId());
     196            cmd.backup(relation).setDeleted(true);
     197            // relation.getDataSet().removePrimitive(relation.getPrimitiveId());
    183198        } else if (from.isExtra()) {
    184199            extraLanes.remove(Integer.valueOf(from.getIndex()));
     
    187202        }
    188203       
    189         relation.put(Constants.TURN_KEY_LANES, lanes.isEmpty() ? null : join(lanes));
    190         relation.put(Constants.TURN_KEY_EXTRA_LANES, extraLanes.isEmpty() ? null : join(extraLanes));
     204        cmd.backup(relation).put(Constants.TURN_KEY_LANES, lanes.isEmpty() ? null : join(lanes));
     205        cmd.backup(relation).put(Constants.TURN_KEY_EXTRA_LANES, extraLanes.isEmpty() ? null : join(extraLanes));
     206    }
     207   
     208    void fixReferences(GenericCommand cmd, boolean left, int index) {
     209        final List<Integer> fixed = new ArrayList<Integer>();
     210        for (int i : indices(relation, Constants.TURN_KEY_EXTRA_LANES)) {
     211            if (left ? i < index : i > index) {
     212                fixed.add(left ? i + 1 : i - 1);
     213            } else {
     214                fixed.add(i);
     215            }
     216        }
     217       
     218        cmd.backup(relation).put(Constants.TURN_KEY_EXTRA_LANES, join(fixed));
    191219    }
    192220}
Note: See TracChangeset for help on using the changeset viewer.