Ticket #12711: alignways-datasetlistener.patch
| File alignways-datasetlistener.patch, 23.0 KB (added by , 9 years ago) |
|---|
-
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysAlgnSegment.java
5 5 import java.awt.Graphics2D; 6 6 import java.awt.Point; 7 7 import java.awt.Shape; 8 import java.awt.RenderingHints; 8 9 import java.awt.geom.Ellipse2D; 9 10 import java.awt.geom.Line2D; 10 11 import java.util.ArrayList; … … 37 38 38 39 private enum PivotLocations { 39 40 NONE, NODE1, NODE2, CENTRE 40 } ;41 } 41 42 42 43 private PivotLocations currPivot; 43 44 Map<PivotLocations, EastNorth> pivotList = new EnumMap<>( … … 118 119 EastNorth n2; 119 120 switch (pp) { 120 121 case NODE1: 121 return segment. way.getNode(segment.lowerIndex).getEastNorth();122 return segment.getFirstNode().getEastNorth(); 122 123 case NODE2: 123 return segment. way.getNode(segment.lowerIndex + 1).getEastNorth();124 return segment.getSecondNode().getEastNorth(); 124 125 case CENTRE: 125 126 n1 = getPivotCoord(PivotLocations.NODE1); 126 127 n2 = getPivotCoord(PivotLocations.NODE2); … … 226 227 227 228 @Override 228 229 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 229 // Note: segment should never be null here230 230 super.paint(g, mv, bbox); 231 231 232 // Note: segment should never be null here, and its nodes should never be missing. 233 // If they are, it's a bug, possibly related to tracking of DataSet deletions. 234 if (segment.way.getNodesCount() <= segment.lowerIndex + 1) { 235 Main.warn("Not drawing AlignWays pivot points: underlying nodes disappeared"); 236 return; 237 } 238 232 239 // Ensure consistency 233 240 updatePivotsEndpoints(); 234 241 … … 246 253 private void highlightPivot(Graphics2D g, MapView mv, EastNorth pivot) { 247 254 g.setColor(pivotColor); 248 255 g.setStroke(new BasicStroke()); 256 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 249 257 250 258 Shape pvCentrePoint = new Ellipse2D.Double( 251 259 mv.getPoint(pivot).getX() - 5.0f, … … 271 279 272 280 g.setColor(crossColor); 273 281 g.setStroke(new BasicStroke()); 282 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 283 274 284 g.draw(crossV); 275 285 g.draw(crossH); 276 286 -
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysCmdKeepLength.java
9 9 import java.util.HashMap; 10 10 import java.util.HashSet; 11 11 import java.util.Map; 12 import java.util.Collections; 12 13 13 14 import javax.swing.Icon; 14 15 import javax.swing.JOptionPane; … … 91 92 this.pivot = algnSeg.getCurrPivotCoord(); 92 93 this.displaceableNodes = algnSeg.getSegmentEndPoints(); 93 94 94 EastNorth enRefNode1 = refWS.way.getNode(refWS.lowerIndex) 95 .getEastNorth(); 96 EastNorth enRefNode2 = refWS.way.getNode(refWS.lowerIndex + 1) 97 .getEastNorth(); 95 EastNorth enRefNode1 = refWS.getFirstNode().getEastNorth(); 96 EastNorth enRefNode2 = refWS.getSecondNode().getEastNorth(); 98 97 99 EastNorth enAlgnNode1 = algnWS.way.getNode(algnWS.lowerIndex) 100 .getEastNorth(); 101 EastNorth enAlgnNode2 = algnWS.way.getNode(algnWS.lowerIndex + 1) 102 .getEastNorth(); 98 EastNorth enAlgnNode1 = algnWS.getFirstNode().getEastNorth(); 99 EastNorth enAlgnNode2 = algnWS.getSecondNode().getEastNorth(); 103 100 104 101 // Calculate the rotation angle 105 102 double refAngle = Math.atan2(enRefNode1.north() - enRefNode2.north(), … … 205 202 } 206 203 207 204 @Override 205 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() { 206 Collection<OsmPrimitive> prims = new HashSet<>(displaceableNodes); 207 prims.add(algnSeg.getSegment().way); 208 return Collections.unmodifiableCollection(prims); 209 } 210 211 @Override 208 212 public boolean executeCommand() { 209 213 rotateNodes(true); 210 214 return true; -
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysDialog.java
10 10 import java.awt.GridLayout; 11 11 import java.awt.event.ActionEvent; 12 12 import java.awt.event.ActionListener; 13 import java.util.Objects; 13 14 14 15 import javax.swing.BorderFactory; 15 16 import javax.swing.Box; … … 116 117 117 118 @Override 118 119 public void actionPerformed(ActionEvent e) { 119 if ( e.getActionCommand() == "awOptKeepLen") {120 if (Objects.equals(e.getActionCommand(), "awOptKeepLen")) { 120 121 awOpt = AligningModeOption.ALGN_OPT_KEEP_LENGTH; 121 122 infoText.setText(tr("<html>Aligns the way segment to the reference so that its length is preserved.</html>")); 122 } else if ( e.getActionCommand() == "awOptKeepAng") {123 } else if (Objects.equals(e.getActionCommand(), "awOptKeepAng")) { 123 124 awOpt = AligningModeOption.ALGN_OPT_KEEP_ANGLE; 124 125 infoText.setText(tr("<html>Aligns the way segment to the reference so that the angles of its adjacent segments are preserved.<br/>" + 125 126 "The length of the aligned segment is likely to change as result.</html>")); … … 135 136 136 137 137 138 /** 138 * @param acti onIf set to true, the dialog will show the mode options, otherwise it will show some instructions139 * @param activeMode If set to true, the dialog will show the mode options, otherwise it will show some instructions 139 140 */ 140 141 public void activate(boolean activeMode) { 141 142 -
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysMode.java
20 20 import org.openstreetmap.josm.Main; 21 21 import org.openstreetmap.josm.actions.mapmode.MapMode; 22 22 import org.openstreetmap.josm.data.osm.DataSet; 23 import org.openstreetmap.josm.data.osm.event.*; 23 24 import org.openstreetmap.josm.gui.IconToggleButton; 24 25 import org.openstreetmap.josm.gui.MapFrame; 25 26 import org.openstreetmap.josm.gui.layer.Layer; 27 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 26 28 import org.openstreetmap.josm.tools.Shortcut; 27 29 28 30 /** … … 30 32 * Handles the state machine and user interaction (mouse clicks). 31 33 * 32 34 */ 33 public class AlignWaysMode extends MapMode /* implements MapViewPaintable */{35 public class AlignWaysMode extends MapMode implements DataSetListener { 34 36 35 37 private static final long serialVersionUID = -1090955708412011141L; 36 38 private final AlignWaysState noneSelected; … … 77 79 78 80 awSegs = AlignWaysSegmentMgr.getInstance(Main.map.mapView); 79 81 Main.map.mapView.addMouseListener(this); 82 DataSet ds = Main.getLayerManager().getEditDataSet(); 83 if (ds != null) 84 ds.addDataSetListener(this); 80 85 setCurrentState(noneSelected); 81 86 } 82 87 … … 94 99 95 100 setCurrentState(noneSelected); 96 101 Main.map.mapView.removeMouseListener(this); 102 DataSet ds = Main.getLayerManager().getEditDataSet(); 103 if (ds != null) 104 ds.removeDataSetListener(this); 97 105 AlignWaysPlugin.getAwAction().setEnabled(false); 98 106 } 99 107 … … 127 135 } 128 136 } 129 137 130 // Activate the Align Ways button if we have enough selections131 if (currentState == bothSelected) {132 AlignWaysPlugin.getAwAction().setEnabled(true);133 } else {134 AlignWaysPlugin.getAwAction().setEnabled(false);135 }136 138 Main.map.mapView.repaint(); 137 139 } 138 140 139 141 /** 140 * @param currentState141 * One of the AlignWays states142 * Sets the current state based on the selected segments. 143 * @param mgr AlignWays segment manager singleton 142 144 */ 145 public void setCurrentState(AlignWaysSegmentMgr mgr) { 146 147 boolean algnSelected = mgr.getAlgnSeg() != null; 148 boolean refSelected = mgr.getRefSeg() != null; 149 150 if (algnSelected && refSelected) 151 setCurrentState(getBothSelected()); 152 else if (algnSelected) 153 setCurrentState(getAligneeSelected()); 154 else if (refSelected) 155 setCurrentState(getReferenceSelected()); 156 else 157 setCurrentState(getNoneSelected()); 158 } 159 160 /** 161 * Sets the current state. 162 * @param currentState One of the AlignWays states 163 */ 143 164 public void setCurrentState(AlignWaysState currentState) { 144 165 this.currentState = currentState; 145 166 currentState.setHelpText(); 146 167 168 // Activate the Align Ways button if we have enough selections 169 AlignWaysPlugin.getAwAction().setEnabled(currentState == bothSelected); 170 147 171 if (currentState == noneSelected) { 148 172 awSegs.cleanupWays(); 149 // TODO getCurrentDataSet may return null when the editable layer had 173 174 // getEditDataSet() may return null when the editable layer had 150 175 // already been removed by JOSM. This happens e.g. when the user closes 151 176 // JOSM while AlignWays mode is still active. 152 177 DataSet ds = getLayerManager().getEditDataSet(); … … 184 209 return bothSelected; 185 210 } 186 211 187 /**188 * @return the current state189 */190 public AlignWaysState getCurrentState() {191 return currentState;192 }193 194 212 private void showTips() { 195 213 196 214 AlignWaysTipsPanel atp = new AlignWaysTipsPanel(); … … 228 246 229 247 @Override 230 248 public boolean layerIsSupported(Layer l) { 231 if (l == null) 232 return false; 233 else 234 return true; 249 return l instanceof OsmDataLayer; 235 250 } 251 252 @Override 253 protected void updateEnabledState() { 254 setEnabled(getLayerManager().getEditLayer() != null); 255 } 256 257 /* --------------- * 258 * DataSetListener * 259 * --------------- */ 260 261 @Override 262 public void primitivesAdded(PrimitivesAddedEvent event) { 263 } 264 265 @Override 266 public void primitivesRemoved(PrimitivesRemovedEvent event) { 267 awSegs = AlignWaysSegmentMgr.getInstance(Main.map.mapView); 268 269 // Check whether any of the removed primitives were part of a highlighted alignee or reference segment. 270 // If so: remove the affected segment and update the state accordingly. 271 if (awSegs.primitivesRemoved(event.getPrimitives())) 272 setCurrentState(awSegs); 273 } 274 275 @Override 276 public void tagsChanged(TagsChangedEvent event) { 277 } 278 279 @Override 280 public void nodeMoved(NodeMovedEvent event) { 281 } 282 283 @Override 284 public void wayNodesChanged(WayNodesChangedEvent event) { 285 } 286 287 @Override 288 public void relationMembersChanged(RelationMembersChangedEvent event) { 289 } 290 291 @Override 292 public void otherDatasetChange(AbstractDatasetChangedEvent event) { 293 } 294 295 @Override 296 public void dataChanged(DataChangedEvent event) { 297 } 298 236 299 } -
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysSegment.java
9 9 import java.awt.Color; 10 10 import java.awt.Graphics2D; 11 11 import java.awt.Point; 12 import java.awt.RenderingHints; 12 13 import java.awt.geom.Line2D; 13 14 import java.util.Collection; 14 15 import java.util.HashSet; … … 18 19 import org.openstreetmap.josm.data.Bounds; 19 20 import org.openstreetmap.josm.data.osm.Node; 20 21 import org.openstreetmap.josm.data.osm.OsmPrimitive; 22 import org.openstreetmap.josm.data.osm.Way; 21 23 import org.openstreetmap.josm.data.osm.WaySegment; 22 24 import org.openstreetmap.josm.gui.MapView; 23 25 import org.openstreetmap.josm.gui.layer.MapViewPaintable; … … 56 58 void setSegmentEndpoints(WaySegment segment) { 57 59 if (segment != null) { 58 60 try { 59 Node node1 = segment.way.getNode(segment.lowerIndex);60 Node node2 = segment.way.getNode(segment.lowerIndex + 1);61 62 61 segmentEndPoints = new HashSet<>(); 63 segmentEndPoints.add( node1);64 segmentEndPoints.add( node2);62 segmentEndPoints.add(segment.getFirstNode()); 63 segmentEndPoints.add(segment.getSecondNode()); 65 64 } catch (IndexOutOfBoundsException e) { 66 65 Main.error(e); 67 66 } … … 88 87 89 88 @Override 90 89 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 90 // Note: segment should never be null here, and its nodes should never be missing. 91 // If they are, it's a bug, possibly related to tracking of DataSet deletions. 92 if (segment.way.getNodesCount() <= segment.lowerIndex + 1) { 93 Main.warn("Not drawing AlignWays highlighting segment: underlying nodes disappeared"); 94 return; 95 } 96 91 97 highlightSegment(segmentColor, g, mv); 92 98 } 93 99 94 100 protected void highlightSegment(Color c, Graphics2D g, MapView mv) { 95 if (segment.way.getNodesCount() == 0) {96 return;97 }98 99 101 g.setColor(c); 100 102 g.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 103 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 101 104 drawSegment(g, mv); 102 105 } 103 106 104 107 protected void drawSegment(Graphics2D g, MapView mv) { 105 108 try { 106 Node n1 = segment. way.getNode(segment.lowerIndex);107 Node n2 = segment. way.getNode(segment.lowerIndex + 1);109 Node n1 = segment.getFirstNode(); 110 Node n2 = segment.getSecondNode(); 108 111 109 112 g.draw(new Line2D.Double(mv.getPoint(n1), mv.getPoint(n2))); 110 113 } catch (IndexOutOfBoundsException e) { … … 112 115 } 113 116 } 114 117 118 protected boolean containsPrimitive(OsmPrimitive primitive) { 119 if (segment == null) 120 return false; 121 122 return (primitive instanceof Way && segment.way.equals(primitive)) || 123 (primitive instanceof Node && segmentEndPoints.contains(primitive)); 124 125 } 126 115 127 @Override 116 128 public int hashCode() { 117 129 if (segment == null) { -
plugins/alignways/src/com/tilusnet/josm/plugins/alignways/AlignWaysSegmentMgr.java
4 4 5 5 import java.awt.Point; 6 6 import java.util.Collection; 7 import java.util.List; 7 8 8 9 import javax.swing.JOptionPane; 9 10 10 11 import org.openstreetmap.josm.Main; 11 12 import org.openstreetmap.josm.data.osm.Node; 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 14 import org.openstreetmap.josm.gui.MapView; 13 15 14 16 /** … … 30 32 mv = mapView; 31 33 } 32 34 35 /** 36 * Get or creates the segment manager instance belonging to a given MapView. 37 */ 33 38 public static AlignWaysSegmentMgr getInstance(MapView mapView) { 34 if (singleton == null) { 35 synchronized (AlignWaysSegmentMgr.class) { 36 if (singleton == null) { 37 singleton = new AlignWaysSegmentMgr(mapView); 38 } 39 synchronized (AlignWaysSegmentMgr.class) { 40 if (singleton == null || !singleton.getMapView().equals(mapView)) { 41 singleton = new AlignWaysSegmentMgr(mapView); 39 42 } 40 43 } 41 44 return singleton; … … 42 45 } 43 46 44 47 /** 48 * @return The MapView this segment manager belongs to. 49 */ 50 private MapView getMapView() { 51 return mv; 52 } 53 54 /** 45 55 * @param clickedPoint 46 56 * Point nearby where user probably clicked 47 57 * @return true, if alignee changed, false otherwise … … 48 58 */ 49 59 public boolean algnUpdate(Point clickedPoint) { 50 60 51 if (algnSeg != null) { 52 // Check first if there is a pivot point nearby that needs selection 53 if (algnSeg.updatePivot(clickedPoint)) 54 // Updated pivot, alignee reference unchanged 55 return false; 61 // Check first if there is a pivot point nearby that needs selection 62 if (algnSeg != null && algnSeg.updatePivot(clickedPoint)) { 63 // Updated pivot, alignee reference unchanged 64 return false; 56 65 } 57 66 58 67 // Previous attempt of pivot update unsuccessful, check alignee update 59 AlignWaysAlgnSegment tmpAlgnSeg = new AlignWaysAlgnSegment(mv, 60 clickedPoint); 68 AlignWaysAlgnSegment tmpAlgnSeg = new AlignWaysAlgnSegment(mv, clickedPoint); 61 69 if (tmpAlgnSeg.getSegment() == null) 62 70 return false; 63 else {64 // Found a segment65 // It may happen that the new segment is identical with the already66 // selected reference:67 if ((refSeg != null) && (tmpAlgnSeg.equals(refSeg))) {68 // This action is then ignored (we won't clear the reference69 // segment)70 JOptionPane.showMessageDialog(Main.parent,71 tr("Segment to be aligned cannot be the same with the reference segment.\n" +72 "Please choose a different segment to be aligned."),73 tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE);74 return false;75 }76 // This will be a new alignee, old alignee (if any) will be lost:77 if (algnSeg != null) {78 algnSeg.destroy();79 }80 71 81 // Update alignee 82 algnSeg = tmpAlgnSeg; 72 // Found a segment - it may happen that the new segment is identical with the already 73 // selected asignee or reference segment. This action is then ignored. 74 if (algnSeg != null && tmpAlgnSeg.equals(algnSeg)) { 75 return false; 76 } 77 else if (refSeg != null && tmpAlgnSeg.equals(refSeg)) { 78 JOptionPane.showMessageDialog(Main.parent, 79 tr("Segment to be aligned cannot be the same with the reference segment.\n" + 80 "Please choose a different segment to be aligned."), 81 tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE); 82 return false; 83 } 83 84 84 return true; 85 // This will be a new alignee, old alignee (if any) will be lost: 86 if (algnSeg != null) { 87 algnSeg.destroy(); 85 88 } 86 89 90 // Update alignee 91 algnSeg = tmpAlgnSeg; 92 return true; 87 93 } 88 94 89 95 /** … … 93 99 */ 94 100 public boolean refUpdate(Point clickedPoint) { 95 101 96 AlignWaysRefSegment tmpRefSeg = new AlignWaysRefSegment(mv, 97 clickedPoint); 98 // TODO Have to check what happens when refSeg wasn't null previously 102 AlignWaysRefSegment tmpRefSeg = new AlignWaysRefSegment(mv, clickedPoint); 99 103 if (tmpRefSeg.getSegment() == null) 100 104 return false; 101 else {102 // Found a segment103 // It may happen that the new segment is identical with the already104 // selected alignee:105 if ((algnSeg != null) && (tmpRefSeg.equals(algnSeg))) {106 // This action is then ignored (we won't clear the alignee107 // segment)108 JOptionPane.showMessageDialog(Main.parent,109 tr("Reference segment cannot be the same with the segment to be aligned.\n" +110 "Please choose a different reference segment."),111 tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE);112 return false;113 }114 // This will be a new reference, old reference (if any) will be lost:115 if (refSeg != null) {116 refSeg.destroy();117 }118 105 119 // Update reference 120 refSeg = tmpRefSeg; 121 return true; 106 // Found a segment - it may happen that the new segment is identical with the already 107 // selected asignee or reference segment. This action is then ignored. 108 if (refSeg != null && refSeg.equals(tmpRefSeg)) { 109 return false; 110 } 111 else if (algnSeg != null && tmpRefSeg.equals(algnSeg)) { 112 JOptionPane.showMessageDialog(Main.parent, 113 tr("Reference segment cannot be the same with the segment to be aligned.\n" + 114 "Please choose a different reference segment."), 115 tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE); 116 return false; 117 } 122 118 119 // This will be a new reference, old reference (if any) will be lost: 120 if (refSeg != null) { 121 refSeg.destroy(); 123 122 } 124 123 124 // Update reference 125 refSeg = tmpRefSeg; 126 return true; 125 127 } 126 128 127 129 /** … … 158 160 return refSeg; 159 161 } 160 162 163 164 /** 165 * Handles the event that OSM primitives were removed and checks whether 166 * this invalidates the currently selected alignee or reference segment. 167 * @return Whether any of the selected segments were invalidated. 168 * @param primitives List of primitives that were removed. 169 */ 170 public boolean primitivesRemoved(List<? extends OsmPrimitive> primitives) { 171 boolean changed = false; 172 for (OsmPrimitive p : primitives) { 173 if (algnSeg != null && algnSeg.containsPrimitive(p)) { 174 algnSeg.destroy(); 175 algnSeg = null; 176 changed = true; 177 } 178 if (refSeg != null && refSeg.containsPrimitive(p)) { 179 refSeg.destroy(); 180 refSeg = null; 181 changed = true; 182 } 183 } 184 return changed; 185 } 161 186 }
