Changeset 26182 in osm for applications/editors/josm/plugins/turnlanes
- Timestamp:
- 2011-06-26T02:46:22+02:00 (14 years ago)
- 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 33 33 34 34 public void mousePressed(MouseEvent e) { 35 setFocusable(true); 35 JunctionPane.this.requestFocus(); 36 36 37 button = e.getButton(); 37 38 … … 158 159 setJunction(container); 159 160 161 setFocusable(true); 162 160 163 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), "refresh"); 161 164 getActionMap().put("refresh", new AbstractAction() { … … 229 232 rotation += Math.PI / 180; 230 233 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()); 231 244 } 232 245 }); … … 276 289 277 290 private void setState(State state) { 291 278 292 if (state instanceof State.AllTurns) { 279 293 dirty = true; … … 282 296 container = container.recalculate(); 283 297 dirty = true; 284 this.state = new State.Default();298 setState(((State.Invalid) state).unwrap()); 285 299 } else if (state instanceof State.Dirty) { 286 300 dirty = true; 287 this.state = ((State.Dirty) state).unwrap();301 setState(((State.Dirty) state).unwrap()); 288 302 } else { 289 this.state = state ;303 this.state = state.carryOver(container); 290 304 } 291 305 … … 431 445 dot(g2d, p, r, Color.RED); 432 446 } 447 448 void refresh() { 449 if (state != null) { 450 setState(new State.Invalid(state)); 451 } 452 } 433 453 } -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/LaneGui.java
r26154 r26182 39 39 g2d.fill(circle); 40 40 41 final String len = METER_FORMAT.format(get Model().getLength());41 final String len = METER_FORMAT.format(getLength() * getRoad().getContainer().getMpp()); 42 42 final Rectangle2D bounds = circle.getBounds2D(); 43 43 g2d.setFont(g2d.getFont().deriveFont(Font.BOLD, (float) bounds.getHeight())); … … 72 72 @Override 73 73 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); 75 75 return new State.Dirty(old); 76 76 } 77 77 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) { 79 85 final double r = getRoad().connectorRadius; 80 86 81 87 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) { 84 93 getModel().setLength(newLength * getRoad().getContainer().getMpp()); 85 94 } … … 169 178 170 179 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()); 172 182 } 173 183 … … 234 244 final RoadGui.ViaConnector a = s.getViaConnectors().get(i); 235 245 final RoadGui.ViaConnector b = s.getViaConnectors().get(i + 1); 236 assert a.getRoadEnd().getOppositeEnd().equals(b );246 assert a.getRoadEnd().getOppositeEnd().equals(b.getRoadEnd()); 237 247 via.add(a.getRoadEnd().getRoad()); 238 248 } … … 271 281 272 282 private Shape clip; 283 private double length; 273 284 274 285 public LaneGui(RoadGui road, Lane lane) { … … 276 287 this.lane = lane; 277 288 this.lengthSlider = lane.isExtra() ? new LengthSlider() : null; 289 this.length = lane.isExtra() ? lane.getLength() / road.getContainer().getMpp() : Double.NaN; 278 290 } 279 291 280 292 public double getLength() { 281 return getModel().isExtra() ? lane.getLength() / getRoad().getContainer().getMpp() : getRoad().getLength();293 return lane.isExtra() ? length : road.getLength(); 282 294 } 283 295 … … 305 317 final Lane leftModel = left == null ? null : left.getModel(); 306 318 final double leftLength = leftModel == null 307 || !leftModel.getOutgoingRoadEnd().equals(getModel().getOutgoingRoadEnd()) ? Double.NEGATIVE_INFINITY308 : 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; 309 321 310 322 final Path outer; … … 320 332 if (L > leftLength) { 321 333 innerLine.append(inner.subpath(max(0, leftLength + WW), L).getIterator(), leftLength >= 0 322 || getModel().getOutgoingRoadEnd().isFromEnd());334 || getModel().getOutgoingRoadEnd().isFromEnd()); 323 335 final Point2D op = outer.getPoint(L + WW); 324 336 innerLine.lineTo(op.getX(), op.getY()); … … 335 347 if (leftLength < L) { 336 348 innerLine.append(inner.subpath(max(0, leftLength + WW), L).getIterator(), leftLength >= 0 337 || getModel().getOutgoingRoadEnd().isFromEnd());349 || getModel().getOutgoingRoadEnd().isFromEnd()); 338 350 } 339 351 } -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/State.java
r26154 r26182 11 11 import org.openstreetmap.josm.plugins.turnlanes.model.Road; 12 12 13 interfaceState {14 public class AllTurns implements State {13 abstract class State { 14 static class AllTurns extends State { 15 15 private final State wrapped; 16 16 … … 22 22 return wrapped; 23 23 } 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 { 27 32 private final Lane lane; 28 33 private final List<RoadGui.ViaConnector> vias; … … 91 96 } 92 97 93 public class Invalid implements State {98 static class Invalid extends State { 94 99 private final State wrapped; 95 100 … … 103 108 } 104 109 105 public class Dirty implements State {110 static class Dirty extends State { 106 111 private final State wrapped; 107 112 … … 113 118 return wrapped; 114 119 } 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 { 118 128 public Default() {} 119 129 } 120 130 121 class IncomingActive implements State {131 static class IncomingActive extends State { 122 132 private final Road.End roadEnd; 123 133 … … 129 139 return roadEnd; 130 140 } 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 { 134 161 private final LaneGui lane; 135 162 … … 141 168 return lane; 142 169 } 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; 143 213 } 144 214 } -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/TurnLanesDialog.java
r26154 r26182 9 9 import java.util.Collection; 10 10 import java.util.Collections; 11 import java.util.HashSet; 11 12 import java.util.List; 13 import java.util.Set; 12 14 13 15 import javax.swing.Action; … … 17 19 import javax.swing.JToggleButton; 18 20 21 import org.openstreetmap.josm.Main; 19 22 import org.openstreetmap.josm.actions.JosmAction; 20 import org.openstreetmap.josm.Main;21 23 import org.openstreetmap.josm.data.SelectionChangedListener; 22 24 import org.openstreetmap.josm.data.osm.DataSet; … … 24 26 import org.openstreetmap.josm.data.osm.OsmPrimitive; 25 27 import org.openstreetmap.josm.data.osm.Way; 28 import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent; 29 import org.openstreetmap.josm.data.osm.event.DataChangedEvent; 30 import org.openstreetmap.josm.data.osm.event.DataSetListener; 31 import org.openstreetmap.josm.data.osm.event.NodeMovedEvent; 32 import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent; 33 import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent; 34 import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent; 35 import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; 36 import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; 37 import org.openstreetmap.josm.gui.MapView; 38 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener; 26 39 import org.openstreetmap.josm.gui.dialogs.ToggleDialog; 40 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 27 41 import org.openstreetmap.josm.plugins.turnlanes.model.ModelContainer; 42 import org.openstreetmap.josm.plugins.turnlanes.model.UnexpectedDataException; 28 43 29 44 public class TurnLanesDialog extends ToggleDialog { 30 45 private class EditAction extends JosmAction { 31 46 private static final long serialVersionUID = 4114119073563457706L; 47 32 48 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); 35 51 putValue("toolbar", "turnlanes/edit"); 36 52 Main.toolbar.register(this); 37 53 } 38 54 39 55 @Override 40 56 public void actionPerformed(ActionEvent e) { … … 42 58 cl.show(body, CARD_EDIT); 43 59 editing = true; 44 } 45 } 46 60 editButton.setSelected(true); 61 } 62 } 63 47 64 private class ValidateAction extends JosmAction { 48 65 private static final long serialVersionUID = 7510740945725851427L; 66 49 67 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); 52 70 putValue("toolbar", "turnlanes/validate"); 53 71 Main.toolbar.register(this); 54 72 } 55 73 56 74 @Override 57 75 public void actionPerformed(ActionEvent e) { … … 59 77 cl.show(body, CARD_VALIDATE); 60 78 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 64 132 private final Action editAction = new EditAction(); 65 133 private final Action validateAction = new ValidateAction(); 66 134 67 135 private static final long serialVersionUID = -1998375221636611358L; 68 136 69 137 private static final String CARD_EDIT = "EDIT"; 70 138 private static final String CARD_VALIDATE = "VALIDATE"; 71 139 private static final String CARD_ERROR = "ERROR"; 72 140 73 141 private final JPanel body = new JPanel(); 74 142 private final JunctionPane junctionPane = new JunctionPane(null); 75 143 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 77 150 private boolean editing = true; 78 151 79 152 public TurnLanesDialog() { 80 153 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 82 168 DataSet.addSelectionListener(new SelectionChangedListener() { 83 169 @Override 84 170 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 85 177 final Collection<OsmPrimitive> s = Collections.unmodifiableCollection(newSelection); 86 178 final List<Node> nodes = OsmPrimitive.getFilteredList(s, Node.class); 87 179 final List<Way> ways = OsmPrimitive.getFilteredList(s, Way.class); 88 180 89 181 if (nodes.isEmpty()) { 90 182 setJunction(null); 91 183 return; 92 184 } 93 185 94 186 try { 95 187 setJunction(ModelContainer.create(nodes, ways)); 188 } catch (UnexpectedDataException e) { 189 displayError(e); 190 return; 96 191 } catch (RuntimeException e) { 97 192 displayError(e); … … 100 195 } 101 196 }); 102 197 103 198 final JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 4, 4)); 104 199 final ButtonGroup group = new ButtonGroup(); 105 final JToggleButton editButton = new JToggleButton(editAction);106 final JToggleButton validateButton = new JToggleButton(validateAction);107 200 group.add(editButton); 108 201 group.add(validateButton); 109 202 buttonPanel.add(editButton); 110 203 buttonPanel.add(validateButton); 111 204 112 205 body.setLayout(new CardLayout(4, 4)); 113 206 114 207 add(buttonPanel, BorderLayout.SOUTH); 115 208 add(body, BorderLayout.CENTER); 116 209 117 210 body.add(junctionPane, CARD_EDIT); 118 211 body.add(new ValidationPanel(), CARD_VALIDATE); 119 212 body.add(error, CARD_ERROR); 120 213 121 214 editButton.doClick(); 122 215 } 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 124 233 void displayError(RuntimeException e) { 125 234 if (editing) { 126 235 e.printStackTrace(); 127 236 128 237 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 132 241 final CardLayout cl = (CardLayout) body.getLayout(); 133 242 cl.show(body, CARD_ERROR); 134 243 } 135 244 } 136 245 137 246 void setJunction(ModelContainer mc) { 138 247 if (mc != null && editing) { -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Lane.java
r26154 r26182 1 1 package org.openstreetmap.josm.plugins.turnlanes.model; 2 2 3 import static org.openstreetmap.josm.tools.I18n.tr; 4 3 5 import java.util.ArrayList; 6 import java.util.Collections; 7 import java.util.Iterator; 4 8 import java.util.List; 5 9 import java.util.Set; 6 10 11 import org.openstreetmap.josm.Main; 7 12 import org.openstreetmap.josm.data.osm.Node; 8 13 import org.openstreetmap.josm.data.osm.Relation; 9 14 import org.openstreetmap.josm.data.osm.RelationMember; 10 15 import org.openstreetmap.josm.data.osm.Way; 11 import org.openstreetmap.josm.plugins.turnlanes.CollectionUtils;12 16 13 17 public class Lane { … … 27 31 28 32 i = 0; 29 for (double l : CollectionUtils.reverse(roadEnd.getLengths(Kind.EXTRA_LEFT))) {33 for (double l : roadEnd.getLengths(Kind.EXTRA_LEFT)) { 30 34 result.add(new Lane(roadEnd, --i, Kind.EXTRA_LEFT, l)); 31 35 } 36 Collections.reverse(result); 32 37 33 38 final int regulars = getRegularCount(roadEnd.getWay(), roadEnd.getJunction().getNode()); … … 53 58 final Double length = Double.parseDouble(s.trim()); 54 59 55 if (length > lengthBound) {60 if (length >= lengthBound) { 56 61 result.add(length); 57 62 } … … 139 144 } 140 145 146 this.length = length; 147 141 148 // TODO if needed, increase length of other lanes 142 149 getOutgoingRoadEnd().updateLengths(); 143 144 this.length = length;145 150 } 146 151 … … 174 179 175 180 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")); 177 182 178 183 Relation existing = null; … … 203 208 r.addMember(new RelationMember(Constants.TURN_ROLE_TO, to.getWay())); 204 209 205 getOutgoingJunction().getNode().getDataSet().addPrimitive(r);210 cmd.add(r); 206 211 } else { 207 212 r = existing; … … 211 216 final List<Integer> lanes = Turn.indices(r, key); 212 217 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); 214 221 } 215 222 216 223 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); 218 252 } 219 253 } -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/ModelContainer.java
r26154 r26182 33 33 closed = true; 34 34 35 for (Node n : closedNodes) {35 for (Node n : new ArrayList<Node>(closedNodes)) { 36 36 for (Way w : Utils.filterRoads(n.getReferrers())) { 37 37 if (w.isFirstLastNode(n)) { … … 41 41 } 42 42 43 for (Way w : closedWays) {43 for (Way w : new ArrayList<Way>(closedWays) ) { 44 44 closed &= close(closedNodes, closedWays, w, Constants.TURN_ROLE_VIA); 45 45 } -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Road.java
r26154 r26182 9 9 import java.util.Set; 10 10 11 import org.openstreetmap.josm.Main; 12 import org.openstreetmap.josm.data.osm.AbstractPrimitive; 11 13 import org.openstreetmap.josm.data.osm.Node; 12 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 109 111 assert kind == Lane.Kind.EXTRA_LEFT || kind == Lane.Kind.EXTRA_RIGHT; 110 112 113 final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Add lane"); 114 111 115 final boolean left = kind == Lane.Kind.EXTRA_LEFT; 112 116 final Relation rel = left ? lengthsLeft : lengthsRight; … … 129 133 final String old = target.get(key); 130 134 if (old == null) { 131 target.put(key, lengthStr);135 cmd.backup(target).put(key, lengthStr); 132 136 } 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); 135 141 } 136 142 … … 152 158 153 159 void updateLengths() { 160 final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Change lane length"); 161 154 162 for (final boolean left : Arrays.asList(true, false)) { 155 163 final Lane.Kind kind = left ? Lane.Kind.EXTRA_LEFT : Lane.Kind.EXTRA_RIGHT; … … 169 177 170 178 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); 173 184 } 174 185 … … 220 231 } 221 232 } 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 } 222 264 } 223 265 … … 247 289 if (left.size() > 1) { 248 290 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."); 250 292 } 251 293 252 294 if (right.size() > 1) { 253 295 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."); 255 297 } 256 298 257 299 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) // 260 302 ); 261 303 } … … 263 305 /** 264 306 * @param r 265 * lengths relation307 * lengths relation 266 308 * @param w 267 * the way to check for309 * the way to check for 268 310 * @param n 269 * first or last node of w, determines the direction311 * first or last node of w, determines the direction 270 312 * @return whether the turn lane goes into the direction of n 271 313 */ … … 293 335 294 336 this.container = container; 295 this.route = lengthsRelations.a == null && lengthsRelations.b == null ? Route.create(Arrays.asList(w), n) : Route296 .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); 297 339 this.fromEnd = new End(true, container.getOrCreateJunction(route.getFirstSegment().getStart())); 298 340 this.toEnd = new End(false, j, lengthsRelations.a, lengthsRelations.b); … … 322 364 } 323 365 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) { 325 382 final DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(); 326 383 dfs.setDecimalSeparator('.'); -
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Turn.java
r26154 r26182 1 1 package org.openstreetmap.josm.plugins.turnlanes.model; 2 3 import static org.openstreetmap.josm.tools.I18n.tr; 2 4 3 5 import java.util.ArrayList; … … 9 11 import java.util.Set; 10 12 13 import org.openstreetmap.josm.Main; 11 14 import org.openstreetmap.josm.data.osm.Node; 12 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 21 24 22 25 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)) { 24 27 continue; 25 28 } … … 71 74 72 75 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(); 74 77 it2.next(); // first is done 75 78 … … 123 126 final Set<Turn> result = new HashSet<Turn>(); 124 127 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)); 126 131 } 127 132 for (int i : indices(r, Constants.TURN_KEY_EXTRA_LANES)) { … … 176 181 177 182 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) { 178 191 final List<Integer> lanes = indices(relation, Constants.TURN_KEY_LANES); 179 192 final List<Integer> extraLanes = indices(relation, Constants.TURN_KEY_EXTRA_LANES); 180 193 194 // TODO understand & document 181 195 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()); 183 198 } else if (from.isExtra()) { 184 199 extraLanes.remove(Integer.valueOf(from.getIndex())); … … 187 202 } 188 203 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)); 191 219 } 192 220 }
Note:
See TracChangeset
for help on using the changeset viewer.