Changeset 23189 in osm
- Timestamp:
- 2010-09-15T18:53:09+02:00 (14 years ago)
- Location:
- applications/editors/josm/plugins
- Files:
-
- 177 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysAction.java
r23082 r23189 24 24 public class AlignWaysAction extends JosmAction { 25 25 26 27 28 29 26 /** 27 * 28 */ 29 private static final long serialVersionUID = -1540319652562985458L; 30 30 31 32 33 34 35 36 37 38 39 31 public AlignWaysAction() { 32 super(tr("Align Way Segments"), "alignways", 33 tr("Makes a pair of selected way segments parallel by rotating one of them " + 34 "around a chosen pivot."), 35 Shortcut.registerShortcut("tools:alignways", tr("Tool: {0}", 36 tr("Align Ways")), KeyEvent.VK_A, Shortcut.GROUP_EDIT, 37 Shortcut.SHIFT_DEFAULT), true); 38 setEnabled(false); 39 } 40 40 41 42 43 44 45 41 public void actionPerformed(ActionEvent e) { 42 if (!isEnabled()) 43 return; 44 if (getCurrentDataSet() == null) 45 return; 46 46 47 47 Collection<Node> affectedNodes = AlignWaysSegmentMgr.getInstance(Main.map.mapView).getSelectedNodes(); 48 48 49 50 51 49 Command c = !Main.main.undoRedo.commands.isEmpty() ? Main.main.undoRedo.commands 50 .getLast() 51 : null; 52 52 53 54 55 56 57 58 59 53 if (!(c instanceof AlignWaysRotateCommand && 54 affectedNodes.equals(((AlignWaysRotateCommand) c).getRotatedNodes()))) { 55 c = new AlignWaysRotateCommand(); 56 if (actionValid((AlignWaysRotateCommand)c, affectedNodes)) { 57 Main.main.undoRedo.add(c); 58 } 59 } 60 60 61 61 Main.map.mapView.repaint(); 62 62 63 64 63 return; 64 } 65 65 66 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 67 /** 68 * Validates the circumstances of the alignment (rotation) command to be executed. 69 * @param c Command to be verified. 70 * @param affectedNodes Nodes to be affected by the action. 71 * @return true if the aligning action can be done, false otherwise. 72 */ 73 private boolean actionValid(AlignWaysRotateCommand c, Collection<Node> affectedNodes) { 74 // Deny action if reference and alignee segment cannot be aligned 75 if (!c.areSegsAlignable()) { 76 JOptionPane.showMessageDialog(Main.parent, 77 tr("Please select two segments that don''t share any nodes\n" 78 + " or put the pivot on their common node.\n"), 79 tr("AlignWayS: Alignment not possible"), JOptionPane.WARNING_MESSAGE); 80 return false; 81 } 82 82 83 84 85 86 87 88 89 90 91 92 83 // Deny action if the nodes would end up outside world 84 for (Node n : affectedNodes) { 85 if (n.getCoor().isOutSideWorld()) { 86 // Revert move 87 (c).undoCommand(); 88 JOptionPane.showMessageDialog(Main.parent, 89 tr("Aligning would result nodes outside the world.\n"), 90 tr("AlignWayS: Alignment not possible"), JOptionPane.WARNING_MESSAGE); 91 return false; 92 } 93 93 94 94 } 95 95 96 97 98 96 // Action valid 97 return true; 98 } 99 99 100 100 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysAlgnSegment.java
r21613 r23189 26 26 public class AlignWaysAlgnSegment extends AlignWaysSegment { 27 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 28 private enum PivotLocations { 29 NONE, NODE1, NODE2, CENTRE 30 }; 31 32 private PivotLocations currPivot; 33 Map<PivotLocations, EastNorth> pivotList = new EnumMap<PivotLocations, EastNorth>( 34 PivotLocations.class); 35 private final Color pivotColor = Color.YELLOW; 36 private final Color crossColor = pivotColor; 37 38 public AlignWaysAlgnSegment(MapView mapview, Point p) 39 throws IllegalArgumentException { 40 super(mapview, p); 41 setSegment(getNearestWaySegment(p)); 42 segmentColor = Color.ORANGE; 43 } 44 45 /** 46 * Sets segment and initialises its pivot list and activates the centre 47 * rotation pivot. 48 */ 49 @Override 50 public void setSegment(WaySegment segment) { 51 super.setSegment(segment); 52 setPivots(); 53 } 54 55 /** 56 * Useful when segments moves (or e.g. rotates) on the map. Updates the end 57 * segment points and the pivot coordinates without changing the current 58 * pivot. 59 */ 60 public void updatePivotsEndpoints() { 61 setPivots(currPivot); 62 setSegmentEndpoints(segment); 63 } 64 65 /** 66 * Updates the segment's pivot list and sets the rotation pivot to centre. 67 */ 68 private void setPivots(PivotLocations pivotRef) { 69 if (segment != null) { 70 for (PivotLocations pl : PivotLocations.values()) { 71 pivotList.put(pl, getPivotCoord(pl)); 72 } 73 setPivotReference(pivotRef); 74 } else { 75 setPivotReference(PivotLocations.NONE); 76 } 77 } 78 79 private void setPivots() { 80 setPivots(PivotLocations.CENTRE); 81 } 82 83 private void setPivotReference(PivotLocations pp) { 84 currPivot = pp; 85 } 86 87 /** 88 * Returns the EastNorth of the specified pivot point pp. It always returns 89 * up-to-date data from dataset. Assumes segment is not null. 90 * 91 * @param pp 92 * The pivot location 93 */ 94 private EastNorth getPivotCoord(PivotLocations pp) { 95 switch (pp) { 96 case NONE: 97 return null; 98 case NODE1: 99 return segment.way.getNode(segment.lowerIndex).getEastNorth(); 100 case NODE2: 101 return segment.way.getNode(segment.lowerIndex + 1).getEastNorth(); 102 case CENTRE: 103 return getPivotCoord(PivotLocations.NODE1).getCenter( 104 getPivotCoord(PivotLocations.NODE2)); 105 default: 106 // Should never happen 107 return null; 108 } 109 } 110 111 /** 112 * @return The EastNorth of the currently selected pivot. 113 */ 114 public EastNorth getCurrPivotCoord() { 115 if (segment != null) 116 return getPivotCoord(currPivot); 117 return null; 118 } 119 120 /** 121 * @param clickedPoint 122 * Pivot may be updated in the vicinity of this point 123 * @return true if a pivot is within reach on the segment, false otherwise 124 */ 125 public boolean updatePivot(Point clickedPoint) { 126 // tHQ Done. 127 PivotLocations tmpPivot = findNearbyPivot(clickedPoint); 128 if (tmpPivot != PivotLocations.NONE) { 129 setPivotReference(tmpPivot); 130 return true; 131 } else 132 return false; 133 } 134 135 private PivotLocations findNearbyPivot(Point clickedPoint) { 136 PivotLocations nearest = PivotLocations.NONE; 137 int snapDistance = NavigatableComponent.snapDistance; 138 139 // If no alignee selected yet, there's no point to carry on 140 if (segment == null) 141 return PivotLocations.NONE; 142 143 for (PivotLocations pl : PivotLocations.values()) { 144 if (pl.equals(PivotLocations.NONE)) { 145 continue; 146 } 147 if (mapview.getPoint(pivotList.get(pl)).distance(clickedPoint) <= snapDistance) { 148 nearest = pl; 149 break; 150 } 151 } 152 return nearest; 153 } 154 155 /* 156 * (non-Javadoc) 157 * 158 * @see 159 * org.openstreetmap.josm.plugins.alignways.AlignWaysRefSegment#paint(java 160 * .awt.Graphics2D, org.openstreetmap.josm.gui.MapView, 161 * org.openstreetmap.josm.data.Bounds) 162 */ 163 @Override 164 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 165 // Note: segment should never be null here 166 super.paint(g, mv, bbox); 167 168 // Highlight potential pivot points 169 for (PivotLocations pl : PivotLocations.values()) { 170 if (pl != PivotLocations.NONE) { 171 highlightCross(g, mv, pivotList.get(pl)); 172 } 173 } 174 175 // Highlight active pivot 176 highlightPivot(g, mv, getPivotCoord(currPivot)); 177 178 } 179 180 private void highlightPivot(Graphics2D g, MapView mv, EastNorth pivot) { 181 g.setColor(pivotColor); 182 g.setStroke(new BasicStroke()); 183 184 Shape pvCentrePoint = new Ellipse2D.Double( 185 mv.getPoint(pivot).getX() - 5.0f, 186 mv.getPoint(pivot).getY() - 5.0f, 10.0f, 10.0f); 187 g.fill(pvCentrePoint); 188 Shape pvPoint = new Ellipse2D.Double(mv.getPoint(pivot).getX() - 8.0f, 189 mv.getPoint(pivot).getY() - 8.0f, 16.0f, 16.0f); 190 191 g.draw(pvCentrePoint); 192 g.draw(pvPoint); 193 } 194 195 private void highlightCross(Graphics2D g, MapView mv, EastNorth en) { 196 197 double crossX = mv.getPoint(en).getX(); 198 double crossY = mv.getPoint(en).getY(); 199 double crossSize = 10.0; 200 201 Line2D crossV = new Line2D.Double(crossX, crossY - crossSize, crossX, 202 crossY + crossSize); 203 Line2D crossH = new Line2D.Double(crossX - crossSize, crossY, crossX 204 + crossSize, crossY); 205 206 g.setColor(crossColor); 207 g.setStroke(new BasicStroke()); 208 g.draw(crossV); 209 g.draw(crossH); 210 211 } 212 212 213 213 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysPlugin.java
r21613 r23189 20 20 public class AlignWaysPlugin extends Plugin { 21 21 22 23 24 25 22 static AlignWaysMode awMode; 23 private final IconToggleButton btn; 24 static JMenuItem alignWaysMenuItem; 25 static JosmAction awAction; 26 26 27 28 29 30 31 32 33 34 35 36 37 38 27 /** 28 * 29 */ 30 public AlignWaysPlugin(PluginInformation info) { 31 super(info); 32 awMode = new AlignWaysMode(Main.map, "alignways", tr("Align Ways mode")); 33 btn = new IconToggleButton(awMode); 34 btn.setVisible(true); 35 Main.main.menu.toolsMenu.addSeparator(); 36 awAction = new AlignWaysAction(); 37 alignWaysMenuItem = MainMenu.add(Main.main.menu.toolsMenu, awAction); 38 Main.main.menu.toolsMenu.addSeparator(); 39 39 40 40 } 41 41 42 43 44 45 46 47 42 @Override 43 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 44 if (Main.map != null) { 45 Main.map.addMapMode(btn); 46 } 47 } 48 48 49 50 51 52 53 54 49 /** 50 * @return the awAction 51 */ 52 public static JosmAction getAwAction() { 53 return awAction; 54 } 55 55 56 57 58 59 60 61 56 /** 57 * @return the awMode 58 */ 59 public static AlignWaysMode getAwMode() { 60 return awMode; 61 } 62 62 63 63 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysRefSegment.java
r21613 r23189 15 15 public class AlignWaysRefSegment extends AlignWaysSegment { 16 16 17 17 // Note: segment may be null. This is normal. 18 18 19 20 21 22 23 19 public AlignWaysRefSegment(MapView mapview, Point p) 20 throws IllegalArgumentException { 21 super(mapview, p); 22 setSegment(getNearestWaySegment(p)); 23 segmentColor = Color.GREEN; 24 24 25 25 } 26 26 27 27 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysRotateCommand.java
r22758 r23189 32 32 public class AlignWaysRotateCommand extends Command { 33 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 34 private final AlignWaysAlgnSegment algnSeg; 35 36 /** 37 * The objects to rotate. 38 */ 39 private Collection<Node> nodes = new HashSet<Node>(); 40 41 /** 42 * pivot point 43 */ 44 private final EastNorth pivot; 45 46 /** 47 * Small helper for holding the interesting part of the old data state of 48 * the objects. 49 */ 50 public static class OldState { 51 LatLon latlon; 52 EastNorth eastNorth; 53 WaySegment ws; 54 boolean modified; 55 } 56 57 /** 58 * computed rotation angle to rotate the segment 59 * 60 */ 61 private final double rotationAngle; 62 63 /** 64 * List of all old states of the objects. 65 */ 66 private final Map<Node, OldState> oldState = new HashMap<Node, OldState>(); 67 private final Stack<WaySegment> oldWS = new Stack<WaySegment>(); 68 69 /** 70 * Creates an AlignWaysRotateCommand. 71 */ 72 public AlignWaysRotateCommand() { 73 74 algnSeg = AlignWaysSegmentMgr.getInstance(Main.map.mapView) 75 .getAlgnSeg(); 76 WaySegment algnWS = algnSeg.getSegment(); 77 WaySegment refWS = AlignWaysSegmentMgr.getInstance(Main.map.mapView) 78 .getRefSeg().getSegment(); 79 80 this.pivot = algnSeg.getCurrPivotCoord(); 81 this.nodes = algnSeg.getSegmentEndPoints(); 82 83 EastNorth enRefNode1 = refWS.way.getNode(refWS.lowerIndex) 84 .getEastNorth(); 85 EastNorth enRefNode2 = refWS.way.getNode(refWS.lowerIndex + 1) 86 .getEastNorth(); 87 88 EastNorth enAlgnNode1 = algnWS.way.getNode(algnWS.lowerIndex) 89 .getEastNorth(); 90 EastNorth enAlgnNode2 = algnWS.way.getNode(algnWS.lowerIndex + 1) 91 .getEastNorth(); 92 93 // Calculate the rotation angle 94 double refAngle = Math.atan2(enRefNode1.north() - enRefNode2.north(), 95 enRefNode1.east() - enRefNode2.east()); 96 double algnAngle = Math.atan2( 97 enAlgnNode1.north() - enAlgnNode2.north(), enAlgnNode1.east() 98 - enAlgnNode2.east()); 99 100 rotationAngle = normalise_angle(refAngle - algnAngle); 101 102 /* For debug only 103 String s = "Ref Angle: " + refAngle + " (" + Math.toDegrees(refAngle) 104 + ")\n"; 105 s += "Algn Angle: " + algnAngle + " (" + Math.toDegrees(algnAngle) 106 + ")\n"; 107 s += "Rotation angle: " + rotationAngle + " (" 108 + Math.toDegrees(rotationAngle) + ")"; 109 */ 110 111 // rotateNodes(true); 112 113 } 114 115 /** 116 * Helper for actually rotating the nodes. 117 * 118 * @param setModified 119 * - true if rotated nodes should be flagged "modified" 120 */ 121 private void rotateNodes(boolean setModified) { 122 123 // "Backup" state 124 WaySegment algnWS = algnSeg.getSegment(); 125 for (Node n : this.nodes) { 126 OldState os = new OldState(); 127 os.latlon = new LatLon(n.getCoor()); 128 os.eastNorth = n.getEastNorth(); 129 os.ws = algnWS; 130 os.modified = n.isModified(); 131 oldState.put(n, os); 132 } 133 oldWS.push(algnWS); 134 135 // Rotate 136 for (Node n : nodes) { 137 double cosPhi = Math.cos(rotationAngle); 138 double sinPhi = Math.sin(rotationAngle); 139 EastNorth oldEastNorth = oldState.get(n).eastNorth; 140 double x = oldEastNorth.east() - pivot.east(); 141 double y = oldEastNorth.north() - pivot.north(); 142 double nx = cosPhi * x - sinPhi * y + pivot.east(); 143 double ny = sinPhi * x + cosPhi * y + pivot.north(); 144 n.setEastNorth(new EastNorth(nx, ny)); 145 if (setModified) { 146 n.setModified(true); 147 } 148 } 149 algnSeg.updatePivotsEndpoints(); 150 } 151 152 /** 153 * Make sure angle is in interval ( -Pi/2, Pi/2 ]. 154 */ 155 private static double normalise_angle(double a) { 156 while (a > Math.PI) { 157 a -= 2 * Math.PI; 158 } 159 while (a <= -Math.PI) { 160 a += 2 * Math.PI; 161 } 162 163 if (a > Math.PI / 2) { 164 a -= Math.PI; 165 } else if (a < -Math.PI / 2) { 166 a += Math.PI; 167 } 168 return a; 169 } 170 171 @Override 172 public JLabel getDescription() { 173 return new JLabel(tr("Align way segment"), ImageProvider.get( 174 "", "alignways"), SwingConstants.HORIZONTAL); 175 } 176 177 /* 178 * (non-Javadoc) 179 * 180 * @see 181 * org.openstreetmap.josm.command.Command#fillModifiedData(java.util.Collection 182 * , java.util.Collection, java.util.Collection) 183 */ 184 @Override 185 public void fillModifiedData(Collection<OsmPrimitive> modified, 186 Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { 187 for (OsmPrimitive osm : nodes) { 188 modified.add(osm); 189 } 190 } 191 192 /* 193 * (non-Javadoc) 194 * 195 * @see org.openstreetmap.josm.command.Command#executeCommand() 196 */ 197 @Override 198 public boolean executeCommand() { 199 rotateNodes(true); 200 return true; 201 } 202 203 /* 204 * (non-Javadoc) 205 * 206 * @see org.openstreetmap.josm.command.Command#undoCommand() 207 */ 208 @Override 209 public void undoCommand() { 210 for (Node n : nodes) { 211 OldState os = oldState.get(n); 212 n.setCoor(os.latlon); 213 n.setModified(os.modified); 214 } 215 algnSeg.updatePivotsEndpoints(); 216 } 217 218 public Collection<Node> getRotatedNodes() { 219 return nodes; 220 } 221 222 /** Returns true if the two selected segments are alignable. 223 * They are not if they are connected *and* the pivot is not the connection node. 224 */ 225 public boolean areSegsAlignable() { 226 Collection<Node> algnNodes = nodes; 227 Collection<Node> refNodes = AlignWaysSegmentMgr.getInstance(Main.map.mapView) 228 .getRefSeg().getSegmentEndPoints(); 229 230 // First check if the pivot node of the alignee exists in the reference: 231 // in this case the pivot is the shared node and alignment is possible 232 for (Node nR : refNodes) { 233 if (nR.getEastNorth().equals(pivot)) 234 return true; 235 } 236 237 // Otherwise if the segments are connected, alignment is not possible 238 for (Node nA : algnNodes) { 239 for (Node nR : refNodes) { 240 if (nA.equals(nR)) 241 return false; 242 } 243 } 244 245 // In all other cases alignment is possible 246 return true; 247 } 248 248 249 249 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSegment.java
r21613 r23189 27 27 public class AlignWaysSegment implements MapViewPaintable { 28 28 29 30 31 32 29 protected WaySegment segment; 30 protected MapView mapview; 31 protected Color segmentColor = Color.WHITE; 32 protected Collection<Node> segmentEndPoints; 33 33 34 35 36 37 38 39 40 41 34 public AlignWaysSegment(MapView mapview, Point p) 35 throws IllegalArgumentException { 36 if (mapview == null) 37 throw new IllegalArgumentException(tr( 38 "Parameter ''{0}'' must not be null", "mapview")); 39 if (p == null) 40 throw new IllegalArgumentException(tr( 41 "Parameter ''{0}'' must not be null", "p")); 42 42 43 44 43 this.mapview = mapview; 44 } 45 45 46 47 48 49 50 51 52 46 void setSegment(WaySegment segment) { 47 this.segment = segment; 48 if (segment != null) { 49 setSegmentEndpoints(segment); 50 mapview.addTemporaryLayer(this); 51 } 52 } 53 53 54 54 55 56 57 58 55 void setSegmentEndpoints(WaySegment segment) { 56 if (segment != null) { 57 Node node1 = segment.way.getNode(segment.lowerIndex); 58 Node node2 = segment.way.getNode(segment.lowerIndex + 1); 59 59 60 61 62 60 segmentEndPoints = new HashSet<Node>(); 61 segmentEndPoints.add(node1); 62 segmentEndPoints.add(node2); 63 63 64 65 64 } 65 } 66 66 67 67 protected WaySegment getNearestWaySegment(Point p) { 68 68 69 69 return mapview.getNearestWaySegment(p, OsmPrimitive.isUsablePredicate); 70 70 71 71 } 72 72 73 74 75 76 77 73 public void destroy() { 74 if (segment != null) { 75 mapview.removeTemporaryLayer(this); 76 } 77 } 78 78 79 80 81 79 public WaySegment getSegment() { 80 return segment; 81 } 82 82 83 84 85 83 public Collection<Node> getSegmentEndPoints() { 84 return segmentEndPoints; 85 } 86 86 87 88 89 87 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 88 highlightSegment(segmentColor, g, mv); 89 } 90 90 91 91 protected void highlightSegment(Color c, Graphics2D g, MapView mv) { 92 92 93 94 95 96 93 g.setColor(c); 94 g.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, 95 BasicStroke.JOIN_ROUND)); 96 drawSegment(g, mv); 97 97 98 98 } 99 99 100 101 102 100 protected void drawSegment(Graphics2D g, MapView mv) { 101 Node n1 = segment.way.getNode(segment.lowerIndex); 102 Node n2 = segment.way.getNode(segment.lowerIndex + 1); 103 103 104 105 106 104 Line2D newline = new Line2D.Double(mv.getPoint(n1), mv.getPoint(n2)); 105 g.draw(newline); 106 } 107 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 108 /* 109 * (non-Javadoc) 110 * 111 * @see java.lang.Object#hashCode() 112 */ 113 @Override 114 public int hashCode() { 115 final int prime = 31; 116 int result = 1; 117 result = prime * result + ((segment == null) ? 0 : segment.hashCode()); 118 result = prime * result 119 + ((segmentColor == null) ? 0 : segmentColor.hashCode()); 120 return result; 121 } 122 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 123 /* 124 * (non-Javadoc) 125 * 126 * @see java.lang.Object#equals(java.lang.Object) 127 */ 128 @Override 129 public boolean equals(Object obj) { 130 if (this == obj) 131 return true; 132 if (obj == null) 133 return false; 134 if (!(obj instanceof AlignWaysSegment)) 135 return false; 136 AlignWaysSegment other = (AlignWaysSegment) obj; 137 if (segment == null) { 138 if (other.segment != null) 139 return false; 140 } else if (!segment.equals(other.segment)) 141 return false; 142 /* Segment colour is ignored in comparison 143 if (segmentColor == null) { 144 if (other.segmentColor != null) 145 return false; 146 } else if (!segmentColor.equals(other.segmentColor)) 147 return false; 148 */ 149 return true; 150 } 151 151 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSegmentMgr.java
r21613 r23189 22 22 public class AlignWaysSegmentMgr { 23 23 24 25 26 27 24 private volatile static AlignWaysSegmentMgr singleton; 25 private AlignWaysRefSegment refSeg = null; 26 private AlignWaysAlgnSegment algnSeg = null; 27 private final MapView mv; 28 28 29 30 31 29 private AlignWaysSegmentMgr(MapView mapView) { 30 mv = mapView; 31 } 32 32 33 34 35 36 37 38 39 40 41 42 33 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 } 40 } 41 return singleton; 42 } 43 43 44 45 46 47 48 49 44 /** 45 * @param clickedPoint 46 * Point nearby where user probably clicked 47 * @return true, if alignee changed, false otherwise 48 */ 49 public boolean algnUpdate(Point clickedPoint) { 50 50 51 52 53 54 55 56 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; 56 } 57 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 58 // Previous attempt of pivot update unsuccessful, check alignee update 59 AlignWaysAlgnSegment tmpAlgnSeg = new AlignWaysAlgnSegment(mv, 60 clickedPoint); 61 if (tmpAlgnSeg.getSegment() == null) 62 return false; 63 else { 64 // Found a segment 65 // It may happen that the new segment is identical with the already 66 // selected reference: 67 if ((refSeg != null) && (tmpAlgnSeg.equals(refSeg))) { 68 // This action is then ignored (we won't clear the reference 69 // 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 80 81 82 81 // Update alignee 82 algnSeg = tmpAlgnSeg; 83 83 84 85 84 return true; 85 } 86 86 87 87 } 88 88 89 90 91 92 93 94 89 /** 90 * @param clickedPoint 91 * Point nearby where user probably clicked 92 * @return true, if reference changed, false otherwise 93 */ 94 public boolean refUpdate(Point clickedPoint) { 95 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 96 AlignWaysRefSegment tmpRefSeg = new AlignWaysRefSegment(mv, 97 clickedPoint); 98 // TODO Have to check what happens when refSeg wasn't null previously 99 if (tmpRefSeg.getSegment() == null) 100 return false; 101 else { 102 // Found a segment 103 // It may happen that the new segment is identical with the already 104 // selected alignee: 105 if ((algnSeg != null) && (tmpRefSeg.equals(algnSeg))) { 106 // This action is then ignored (we won't clear the alignee 107 // 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 118 119 120 121 119 // Update reference 120 refSeg = tmpRefSeg; 121 return true; 122 122 123 123 } 124 124 125 125 } 126 126 127 128 129 130 131 132 133 134 127 /** 128 * @return Collection of the nodes that belong to the selected alignee. 129 */ 130 public Collection<Node> getSelectedNodes() { 131 if (algnSeg != null) 132 return algnSeg.getSegmentEndPoints(); 133 return null; 134 } 135 135 136 137 138 139 140 141 142 143 144 145 146 147 148 136 /** 137 * Performs "clean-up" on the initialised segments 138 */ 139 public void cleanupWays() { 140 if (algnSeg != null) { 141 algnSeg.destroy(); 142 algnSeg = null; 143 } 144 if (refSeg != null) { 145 refSeg.destroy(); 146 refSeg = null; 147 } 148 } 149 149 150 151 152 150 public AlignWaysAlgnSegment getAlgnSeg() { 151 return algnSeg; 152 } 153 153 154 155 156 157 158 159 154 /** 155 * @return the refSeg 156 */ 157 public AlignWaysRefSegment getRefSeg() { 158 return refSeg; 159 } 160 160 161 161 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSelAlgnState.java
r21613 r23189 12 12 public class AlignWaysSelAlgnState extends AlignWaysState { 13 13 14 15 16 17 14 @Override 15 public void leftClick(AlignWaysMode alignWaysMode) { 16 // No state change, nothing to do 17 } 18 18 19 20 21 22 19 @Override 20 public void ctrlLClick(AlignWaysMode alignWaysMode) { 21 alignWaysMode.setCurrentState(alignWaysMode.getBothSelected()); 22 } 23 23 24 25 26 27 28 24 @Override 25 public void setHelpText() { 26 Main.map.statusLine 27 .setHelpText("Ctrl-Click: select reference way segment; Alt-click: Clear selection"); 28 } 29 29 30 30 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSelBothState.java
r22758 r23189 12 12 public class AlignWaysSelBothState extends AlignWaysState { 13 13 14 15 16 17 14 @Override 15 public void leftClick(AlignWaysMode alignWaysMode) { 16 // No state change, nothing to do 17 } 18 18 19 20 21 22 19 @Override 20 public void ctrlLClick(AlignWaysMode alignWaysMode) { 21 // No state change, nothing to do 22 } 23 23 24 25 26 27 28 29 24 @Override 25 public void setHelpText() { 26 Main.map.statusLine 27 .setHelpText(AlignWaysPlugin.getAwAction().getShortcut().getKeyText() + 28 ": Align segments; Alt-click: Clear selection"); 29 } 30 30 31 31 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSelNoneState.java
r21613 r23189 12 12 public class AlignWaysSelNoneState extends AlignWaysState { 13 13 14 15 16 17 14 @Override 15 public void leftClick(AlignWaysMode alignWaysMode) { 16 // Reference way segment selected successfully 17 alignWaysMode.setCurrentState(alignWaysMode.getAligneeSelected()); 18 18 19 19 } 20 20 21 22 23 24 25 21 @Override 22 public void ctrlLClick(AlignWaysMode alignWaysMode) { 23 // Reference way segment selected successfully 24 alignWaysMode.setCurrentState(alignWaysMode.getReferenceSelected()); 25 } 26 26 27 28 29 30 31 27 @Override 28 public void setHelpText() { 29 Main.map.statusLine 30 .setHelpText("Ctrl-click: select reference way segment; Click: select way segment to be aligned"); 31 } 32 32 33 33 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysSelRefState.java
r21613 r23189 12 12 public class AlignWaysSelRefState extends AlignWaysState { 13 13 14 15 16 17 14 @Override 15 public void leftClick(AlignWaysMode alignWaysMode) { 16 alignWaysMode.setCurrentState(alignWaysMode.getBothSelected()); 17 } 18 18 19 20 21 22 19 @Override 20 public void ctrlLClick(AlignWaysMode alignWaysMode) { 21 // No state change, nothing to do 22 } 23 23 24 25 26 27 28 24 @Override 25 public void setHelpText() { 26 Main.map.statusLine 27 .setHelpText("Click: select way segment to be aligned; Alt-click: Clear selection"); 28 } 29 29 30 30 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysState.java
r21613 r23189 12 12 public abstract class AlignWaysState { 13 13 14 14 public abstract void leftClick(AlignWaysMode alignWaysMode); 15 15 16 16 public abstract void ctrlLClick(AlignWaysMode alignWaysMode); 17 17 18 18 public abstract void setHelpText(); 19 19 20 21 22 23 24 20 public void altLClick(AlignWaysMode alignWaysMode) { 21 alignWaysMode.setCurrentState(alignWaysMode.getNoneSelected()); 22 Main.map.statusLine 23 .setHelpText("Ctrl-Click: select reference way segment; Click: select way segment to be aligned"); 24 } 25 25 26 26 } -
applications/editors/josm/plugins/alignways/src/org/openstreetmap/josm/plugins/alignways/AlignWaysTipsPanel.java
r22842 r23189 27 27 public class AlignWaysTipsPanel extends javax.swing.JPanel { 28 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 29 private static final long serialVersionUID = -8583989497599985140L; 30 31 public AlignWaysTipsPanel() { 32 initComponents(); 33 } 34 35 private void initComponents() { 36 37 Title = new JPanel(); 38 WelcomeTo = new JLabel(); 39 Icon = new JLabel(); 40 separator = new JSeparator(); 41 Intro = new JPanel(); 42 introText = new JLabel(); 43 scrollableSteps = new JScrollPane(); 44 steps = new JPanel(); 45 step01 = new JLabel(); 46 step02 = new JLabel(); 47 step03 = new JLabel(); 48 step04 = new JLabel(); 49 lastHint = new JLabel(); 50 dontShow = new JCheckBox(); 51 52 setAutoscrolls(true); 53 54 WelcomeTo.setText(tr("<html>\n<div style=\"font-family: 'sans-serif'; font-weight: bold; font-style: italic;\">\n<span style=\"font-size: large;\">Welcome to the</span><br>\n<span style=\"font-size: xx-large;\">AlignWay<span style=\"color: rgb(204, 85, 0);\">S</span> Plugin<br>\n</span><span style=\"font-size: medium;\"><br>\n...or it rather should be called <br>\n<span style=\"font-size: large;\">AlignWayS(egments)</span> Plugin...</span>\n</div>\n</html>")); 55 56 WelcomeTo.setVerticalAlignment(SwingConstants.TOP); 57 WelcomeTo.setPreferredSize(new Dimension(400, 128)); 58 59 Icon.setIcon(new ImageIcon(getClass().getResource("/images/tipsdialog/alignways128.png"))); // NOI18N 60 GroupLayout TitleLayout = new GroupLayout(Title); 61 Title.setLayout(TitleLayout); 62 TitleLayout.setHorizontalGroup( 63 TitleLayout.createParallelGroup(GroupLayout.LEADING) 64 .add(GroupLayout.TRAILING, TitleLayout.createSequentialGroup() 65 .add(WelcomeTo, GroupLayout.DEFAULT_SIZE, 396, Short.MAX_VALUE) 66 .addPreferredGap(LayoutStyle.RELATED) 67 .add(Icon, GroupLayout.PREFERRED_SIZE, 132, GroupLayout.PREFERRED_SIZE)) 68 ); 69 TitleLayout.setVerticalGroup( 70 TitleLayout.createParallelGroup(GroupLayout.LEADING) 71 .add(TitleLayout.createSequentialGroup() 72 .add(Icon) 73 .addContainerGap()) 74 .add(WelcomeTo, GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE) 75 ); 76 77 Intro.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 78 79 introText.setText(tr("<html>\n<p style=\"font-family: sans-serif; font-weight: bold;\">AlignWays will\nhelp you to align two way segments. This can be handy when for instance\nyou sketch the outlines of a building and want its side to be parallel\nwith a street or road.<br>\n<br>\nSome tips may help before you start:\n</p>\n</html>\n\n")); 80 introText.setVerticalAlignment(SwingConstants.TOP); 81 82 scrollableSteps.setBorder(null); 83 scrollableSteps.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 84 85 step01.setIcon(new ImageIcon(getClass().getResource("/images/tipsdialog/hlpRefSel.png"))); // NOI18N 86 step01.setText(tr("<html>\n<div style=\"font-family: sans-serif;\">\n<ul>\n<li><b>Select a reference segment.</b> You can do this by <b><i><span style=\"color:green\">Ctrl-click</span></i></b>ing\non a segment. The other, to be aligned segment will become parallel to\nthis one. </li>\n</ul>\n</div>\n</html>\n\n")); 87 step01.setVerticalAlignment(SwingConstants.TOP); 88 89 step02.setIcon(new ImageIcon(getClass().getResource("/images/tipsdialog/hlpAlgSel.png"))); // NOI18N 90 step02.setText(tr("<html>\n<div style=\"font-family:sans-serif\">\n<ul>\n <li><b>Select the to be aligned segment.</b> You can do this by simply <b><i><span style=\"color:green\">click</span></i></b>ing on a different segment. \nThe rotation pivot will be highlighted by default in the centre of the segment.\n </li>\n</ul>\n</div>\n</html>\n\n")); 91 step02.setVerticalAlignment(SwingConstants.TOP); 92 93 step03.setIcon(new ImageIcon(getClass().getResource("/images/tipsdialog/hlpPvtSel.png"))); // NOI18N 94 step03.setText(tr("<html>\n<div style=\"font-family:sans-serif\">\n<ul>\n <li>Optionally <b>change the rotation pivot point</b>. In order to get parallel with the reference segment, the to be aligned segment will rotate around this point. You can choose the two extremities or the centre of the segment by <b><i><span style=\"color:green\">click</span></i></b>ing nearby. \n </li>\n</ul>\n</div>\n</html>\n\n")); 95 step03.setVerticalAlignment(SwingConstants.TOP); 96 97 step04.setIcon(new ImageIcon(getClass().getResource("/images/tipsdialog/hlpAlgCmd.png"))); // NOI18N 98 step04.setText(tr("<html>\n<div style=\"font-family:sans-serif\">\n<ul>\n <li><b>Align the segments.</b> Press <b><i><span style=\"color:green\">" 99 + AlignWaysPlugin.awAction.getShortcut().getKeyText() 100 + "</span></i></b>. Alternatively you''ll find the command in the <b>Tools</b>\n menu or may want to place the action on the <b>toolbar</b>.\n </li>\n</ul>\n</div>\n</html>\n\n")); 101 step04.setVerticalAlignment(SwingConstants.TOP); 102 103 lastHint.setText(tr("<html>\n<div style=\"font-family:sans-serif\">\n<b>Last hint:</b> There is an easy way to start over your selections if you want: <b><i><span style=\"color:green\">Alt-Click</span></i></b> somewhere on the map.\n</div>\n</html>\n\n")); 104 lastHint.setVerticalAlignment(SwingConstants.TOP); 105 106 GroupLayout stepsLayout = new GroupLayout(steps); 107 steps.setLayout(stepsLayout); 108 stepsLayout.setHorizontalGroup( 109 stepsLayout.createParallelGroup(GroupLayout.LEADING) 110 .add(stepsLayout.createSequentialGroup() 111 .addContainerGap() 112 .add(stepsLayout.createParallelGroup(GroupLayout.TRAILING) 113 .add(GroupLayout.LEADING, lastHint, 0, 0, Short.MAX_VALUE) 114 .add(GroupLayout.LEADING, step04, 0, 0, Short.MAX_VALUE) 115 .add(GroupLayout.LEADING, step03, 0, 0, Short.MAX_VALUE) 116 .add(GroupLayout.LEADING, step02, 0, 0, Short.MAX_VALUE) 117 .add(GroupLayout.LEADING, step01, GroupLayout.DEFAULT_SIZE, 496, Short.MAX_VALUE)) 118 .add(18, 18, 18)) 119 ); 120 stepsLayout.setVerticalGroup( 121 stepsLayout.createParallelGroup(GroupLayout.LEADING) 122 .add(stepsLayout.createSequentialGroup() 123 .add(step01, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 124 .addPreferredGap(LayoutStyle.RELATED) 125 .add(step02, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 126 .addPreferredGap(LayoutStyle.RELATED) 127 .add(step03, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 128 .addPreferredGap(LayoutStyle.RELATED) 129 .add(step04, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 130 .addPreferredGap(LayoutStyle.RELATED) 131 .add(lastHint, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 132 .addContainerGap(22, Short.MAX_VALUE)) 133 ); 134 135 scrollableSteps.setViewportView(steps); 136 137 dontShow.setText(tr("Don''t show this again")); 138 139 GroupLayout IntroLayout = new GroupLayout(Intro); 140 Intro.setLayout(IntroLayout); 141 IntroLayout.setHorizontalGroup( 142 IntroLayout.createParallelGroup(GroupLayout.LEADING) 143 .add(IntroLayout.createSequentialGroup() 144 .addContainerGap() 145 .add(dontShow, GroupLayout.PREFERRED_SIZE, 245, GroupLayout.PREFERRED_SIZE) 146 .addContainerGap(283, Short.MAX_VALUE)) 147 .add(scrollableSteps, GroupLayout.DEFAULT_SIZE, 534, Short.MAX_VALUE) 148 .add(introText, GroupLayout.DEFAULT_SIZE, 534, Short.MAX_VALUE) 149 ); 150 IntroLayout.setVerticalGroup( 151 IntroLayout.createParallelGroup(GroupLayout.LEADING) 152 .add(GroupLayout.TRAILING, IntroLayout.createSequentialGroup() 153 .add(introText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 154 .addPreferredGap(LayoutStyle.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 155 .add(scrollableSteps, GroupLayout.PREFERRED_SIZE, 209, GroupLayout.PREFERRED_SIZE) 156 .addPreferredGap(LayoutStyle.UNRELATED) 157 .add(dontShow) 158 .addContainerGap()) 159 ); 160 161 GroupLayout layout = new GroupLayout(this); 162 this.setLayout(layout); 163 layout.setHorizontalGroup( 164 layout.createParallelGroup(GroupLayout.LEADING) 165 .add(GroupLayout.TRAILING, layout.createSequentialGroup() 166 .addContainerGap() 167 .add(layout.createParallelGroup(GroupLayout.TRAILING) 168 .add(GroupLayout.LEADING, separator, GroupLayout.DEFAULT_SIZE, 534, Short.MAX_VALUE) 169 .add(Title, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 170 .add(Intro, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 171 .addContainerGap()) 172 ); 173 layout.setVerticalGroup( 174 layout.createParallelGroup(GroupLayout.LEADING) 175 .add(layout.createSequentialGroup() 176 .addContainerGap() 177 .add(Title, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 178 .addPreferredGap(LayoutStyle.UNRELATED) 179 .add(separator, GroupLayout.PREFERRED_SIZE, 17, GroupLayout.PREFERRED_SIZE) 180 .addPreferredGap(LayoutStyle.RELATED) 181 .add(Intro, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 182 .addContainerGap(45, Short.MAX_VALUE)) 183 ); 184 } 185 186 187 private JLabel Icon; 188 private JPanel Intro; 189 private JPanel Title; 190 private JLabel WelcomeTo; 191 private JCheckBox dontShow; 192 private JLabel introText; 193 private JLabel lastHint; 194 private JScrollPane scrollableSteps; 195 private JSeparator separator; 196 private JLabel step01; 197 private JLabel step02; 198 private JLabel step03; 199 private JLabel step04; 200 private JPanel steps; 201 202 public boolean isChkBoxSelected() { 203 return dontShow.isSelected(); 204 } 205 205 206 206 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxLayer.java
r22548 r23189 35 35 public class EditGpxLayer extends Layer { 36 36 37 38 39 37 private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(EditGpxPlugin.class.getResource("/images/editgpx_layer.png"))); 38 public final EditGpxData data; 39 private GPXLayerImportAction layerImport; 40 40 41 42 43 44 45 41 public EditGpxLayer(String str, EditGpxData gpxData) { 42 super(str); 43 data = gpxData; 44 layerImport = new GPXLayerImportAction(data); 45 } 46 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 47 /** 48 * check if dataSet is empty 49 * if so show import dialog to user 50 */ 51 public void initializeImport() { 52 try { 53 if(data.isEmpty()) { 54 layerImport.activateImport(); 55 } 56 } catch (Exception e) { 57 System.out.println(e.getMessage()); 58 e.printStackTrace(); 59 } 60 } 61 61 62 63 64 65 62 @Override 63 public Icon getIcon() { 64 return icon; 65 } 66 66 67 68 69 70 67 @Override 68 public Object getInfoComponent() { 69 return getToolTipText(); 70 } 71 71 72 73 74 75 76 77 78 79 80 81 82 83 72 @Override 73 public Action[] getMenuEntries() { 74 return new Action[] { 75 LayerListDialog.getInstance().createShowHideLayerAction(), 76 LayerListDialog.getInstance().createDeleteLayerAction(), 77 SeparatorLayerAction.INSTANCE, 78 layerImport, 79 new ConvertToGpxLayerAction(), 80 new ConvertToAnonTimeGpxLayerAction(), 81 SeparatorLayerAction.INSTANCE, 82 new LayerListPopup.InfoAction(this)}; 83 } 84 84 85 86 87 88 85 @Override 86 public String getToolTipText() { 87 return tr("Layer for editing GPX tracks"); 88 } 89 89 90 91 92 93 94 90 @Override 91 public boolean isMergable(Layer other) { 92 // TODO 93 return false; 94 } 95 95 96 97 98 99 96 @Override 97 public void mergeFrom(Layer from) { 98 // TODO 99 } 100 100 101 102 103 101 @Override 102 public void paint(Graphics2D g, MapView mv, Bounds bounds) { 103 g.setColor(Color.yellow); 104 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 105 //don't iterate through dataSet whiling making changes 106 synchronized(layerImport.importing) { 107 for (EditGpxTrack track: data.getTracks()) { 108 for (EditGpxTrackSegment segment: track.getSegments()) { 109 for (EditGpxWayPoint wayPoint: segment.getWayPoints()) { 110 if (!wayPoint.isDeleted()) { 111 Point pnt = Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth()); 112 g.drawOval(pnt.x - 2, pnt.y - 2, 4, 4); 113 } 114 } 115 } 116 } 117 } 118 } 119 119 120 120 121 122 123 121 public void reset(){ 122 //TODO implement a reset 123 } 124 124 125 125 126 127 128 129 126 @Override 127 public void visitBoundingBox(BoundingXYVisitor v) { 128 // TODO Auto-generated method stub 129 } 130 130 131 131 132 133 134 135 136 137 138 139 140 132 /** 133 * convert a DataSet to GPX 134 * 135 * @param boolean anonTime If true set all time and date in GPX to 01/01/1970 00:00 ? 136 * @return GPXData 137 */ 138 private GpxData toGpxData(boolean anonTime) { 139 return data.createGpxData(); 140 } 141 141 142 143 144 145 146 147 148 149 150 151 152 153 142 //context item "Convert to GPX layer" 143 public class ConvertToGpxLayerAction extends AbstractAction { 144 public ConvertToGpxLayerAction() { 145 super(tr("Convert to GPX layer"), ImageProvider.get("converttogpx")); 146 } 147 public void actionPerformed(ActionEvent e) { 148 Main.main.addLayer(new GpxLayer(toGpxData(false), tr("Converted from: {0}", getName()))); 149 Main.main.removeLayer(EditGpxLayer.this); 150 if(Main.map.mapMode instanceof EditGpxMode) 151 Main.map.selectSelectTool(false); 152 } 153 } 154 154 155 156 157 158 159 160 161 162 163 164 165 166 155 //context item "Convert to GPX layer with anonymised time" 156 public class ConvertToAnonTimeGpxLayerAction extends AbstractAction { 157 public ConvertToAnonTimeGpxLayerAction() { 158 super(tr("Convert to GPX layer with anonymised time"), ImageProvider.get("converttogpx")); 159 } 160 public void actionPerformed(ActionEvent e) { 161 Main.main.addLayer(new GpxLayer(toGpxData(true), tr("Converted from: {0}", getName()))); 162 Main.main.removeLayer(EditGpxLayer.this); 163 if(Main.map.mapMode instanceof EditGpxMode) 164 Main.map.selectSelectTool(false); 165 } 166 } 167 167 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxMode.java
r21582 r23189 29 29 public class EditGpxMode extends MapMode implements LayerChangeListener { 30 30 31 32 33 34 35 36 31 private static final long serialVersionUID = 7940589057093872411L; 32 Point pointPressed; 33 MapFrame mapFrame; 34 Rectangle oldRect; 35 MapFrame frame; 36 EditGpxLayer currentEditLayer; 37 37 38 39 40 38 public EditGpxMode(MapFrame mapFrame, String name, String desc) { 39 super(name, "editgpx_mode.png", desc, mapFrame, Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); 40 } 41 41 42 43 44 45 46 47 48 42 @Override public void enterMode() { 43 super.enterMode(); 44 Main.map.mapView.addMouseListener(this); 45 Main.map.mapView.addMouseMotionListener(this); 46 MapView.addLayerChangeListener(this); 47 updateLayer(); 48 } 49 49 50 51 52 53 54 50 @Override public void exitMode() { 51 super.exitMode(); 52 Main.map.mapView.removeMouseListener(this); 53 Main.map.mapView.removeMouseMotionListener(this); 54 } 55 55 56 56 57 58 59 57 @Override public void mousePressed(MouseEvent e) { 58 pointPressed = new Point(e.getPoint()); 59 } 60 60 61 61 62 63 64 65 66 67 62 @Override public void mouseDragged(MouseEvent e) { 63 if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK) { 64 //if button1 is hold, draw the rectangle. 65 paintRect(pointPressed, e.getPoint()); 66 } 67 } 68 68 69 70 71 72 69 @Override public void mouseReleased(MouseEvent e) { 70 if (e.getButton() != MouseEvent.BUTTON1) { 71 return; 72 } 73 73 74 74 Point pointReleased = e.getPoint(); 75 75 76 76 Rectangle r = createRect(pointReleased, pointPressed); 77 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 78 //go through nodes and mark the ones in the selection rect as deleted 79 if (currentEditLayer != null) { 80 for (EditGpxTrack track: currentEditLayer.data.getTracks()) { 81 for (EditGpxTrackSegment segment: track.getSegments()) { 82 for (EditGpxWayPoint wayPoint: segment.getWayPoints()) { 83 Point p = Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth()); 84 if (r.contains(p)) { 85 wayPoint.setDeleted(true); 86 } 87 } 88 } 89 } 90 } 91 oldRect = null; 92 Main.map.mapView.repaint(); 93 93 94 94 } 95 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 96 /** 97 * create rectangle out of two given corners 98 */ 99 public Rectangle createRect(Point p1, Point p2) { 100 int x,y,w,h; 101 if (p1.x == p2.x && p1.y == p2.y) { 102 //if p1 and p2 same points draw a small rectangle around them 103 x = p1.x -1; 104 y = p1.y -1; 105 w = 3; 106 h = 3; 107 } else { 108 if (p1.x < p2.x){ 109 x = p1.x; 110 w = p2.x-p1.x; 111 } else { 112 x = p2.x; 113 w = p1.x-p2.x; 114 } 115 if (p1.y < p2.y) { 116 y = p1.y; 117 h = p2.y-p1.y; 118 } else { 119 y = p2.y; 120 h = p1.y-p2.y; 121 } 122 } 123 return new Rectangle(x,y,w,h); 124 } 125 125 126 127 128 129 130 126 /** 127 * Draw a selection rectangle on screen. 128 */ 129 private void paintRect(Point p1, Point p2) { 130 Graphics g = frame.getGraphics();//Main.map.mapView.getGraphics(); 131 131 132 133 134 135 136 137 138 132 Rectangle r = oldRect; 133 if (r != null) { 134 //overwrite old rct 135 g.setXORMode(Color.BLACK); 136 g.setColor(Color.WHITE); 137 g.drawRect(r.x,r.y,r.width,r.height); 138 } 139 139 140 141 142 143 144 145 140 g.setXORMode(Color.BLACK); 141 g.setColor(Color.WHITE); 142 r = createRect(p1,p2); 143 g.drawRect(r.x,r.y,r.width,r.height); 144 oldRect = r; 145 } 146 146 147 147 148 149 150 148 public void setFrame(MapFrame mapFrame) { 149 frame = mapFrame; 150 } 151 151 152 153 154 155 152 /** 153 * create new layer, add listeners and try importing gpx data. 154 */ 155 private void updateLayer() { 156 156 157 158 157 List<EditGpxLayer> layers = Main.map.mapView.getLayersOfType(EditGpxLayer.class); 158 currentEditLayer = layers.isEmpty()?null:layers.get(0); 159 159 160 161 162 163 164 165 166 160 if(currentEditLayer == null) { 161 currentEditLayer = new EditGpxLayer(tr("EditGpx"), new EditGpxData()); 162 Main.main.addLayer(currentEditLayer); 163 currentEditLayer.initializeImport(); 164 } 165 Main.map.mapView.repaint(); 166 } 167 167 168 168 public void activeLayerChange(Layer oldLayer, Layer newLayer) { } 169 169 170 170 public void layerAdded(Layer newLayer) { } 171 171 172 173 174 175 176 177 178 172 public void layerRemoved(Layer oldLayer) { 173 if (oldLayer instanceof EditGpxLayer) { 174 currentEditLayer = null; 175 if(Main.map.mapMode instanceof EditGpxMode) 176 Main.map.selectSelectTool(false); 177 } 178 } 179 179 180 180 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/EditGpxPlugin.java
r22548 r23189 31 31 public class EditGpxPlugin extends Plugin { 32 32 33 34 33 private IconToggleButton btn; 34 private EditGpxMode mode; 35 35 36 37 38 36 public EditGpxPlugin(PluginInformation info) { 37 super(info); 38 mode = new EditGpxMode(Main.map, "editgpx", tr("edit gpx tracks")); 39 39 40 41 42 40 btn = new IconToggleButton(mode); 41 btn.setVisible(true); 42 } 43 43 44 45 46 47 48 49 50 44 /** 45 * initialize button. if button is pressed create new layer. 46 */ 47 @Override 48 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 49 if(oldFrame == null && newFrame != null) { 50 mode.setFrame(newFrame); 51 51 52 53 54 55 52 if(Main.map != null) 53 Main.map.addMapMode(btn); 54 } 55 } 56 56 57 58 59 60 57 public static ImageIcon loadIcon(String name) { 58 URL url = EditGpxPlugin.class.getResource("/images/editgpx.png"); 59 return new ImageIcon(url); 60 } 61 61 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/GPXLayerImportAction.java
r21582 r23189 38 38 39 39 40 41 42 40 private static final long serialVersionUID = 5794897888911798168L; 41 private EditGpxData data; 42 public Object importing = new Object(); //used for synchronization 43 43 44 45 46 47 48 44 public GPXLayerImportAction(EditGpxData data) { 45 //TODO what is icon at the end? 46 super(tr("Import path from GPX layer"), ImageProvider.get("dialogs", "edit")); 47 this.data = data; 48 } 49 49 50 51 52 53 54 55 56 50 /** 51 * shows a list of GPX layers. if user selects one the data from this layer is 52 * imported. 53 */ 54 public void activateImport() { 55 Box panel = Box.createVerticalBox(); 56 DefaultListModel dModel= new DefaultListModel(); 57 57 58 59 60 61 58 final JList layerList = new JList(dModel); 59 Collection<Layer> data = Main.map.mapView.getAllLayers(); 60 Layer lastLayer = null; 61 int layerCnt = 0; 62 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 63 for (Layer l : data){ 64 if(l instanceof GpxLayer){ 65 dModel.addElement(l); 66 lastLayer = l; 67 layerCnt++; 68 } 69 } 70 if(layerCnt == 1){ 71 layerList.setSelectedValue(lastLayer, true); 72 } 73 if(layerCnt > 0){ 74 layerList.setCellRenderer(new DefaultListCellRenderer(){ 75 @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 76 Layer layer = (Layer)value; 77 JLabel label = (JLabel)super.getListCellRendererComponent(list, 78 layer.getName(), index, isSelected, cellHasFocus); 79 Icon icon = layer.getIcon(); 80 label.setIcon(icon); 81 label.setToolTipText(layer.getToolTipText()); 82 return label; 83 } 84 }); 85 85 86 86 JCheckBox dropFirst = new JCheckBox(tr("Drop existing path")); 87 87 88 89 88 panel.add(layerList); 89 panel.add(dropFirst); 90 90 91 92 93 94 95 96 97 91 final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION){ 92 @Override public void selectInitialValue() { 93 layerList.requestFocusInWindow(); 94 } 95 }; 96 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Import path from GPX layer")); 97 dlg.setVisible(true); 98 98 99 100 101 102 103 99 Object answer = optionPane.getValue(); 100 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE || 101 (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) { 102 return; 103 } 104 104 105 105 GpxLayer gpx = (GpxLayer)layerList.getSelectedValue(); 106 106 107 108 109 110 107 synchronized(importing) { 108 this.data.load(gpx.data, dropFirst.isSelected()); 109 } 110 Main.map.mapView.repaint(); 111 111 112 113 114 115 116 112 } else { 113 // no gps layer 114 JOptionPane.showMessageDialog(Main.parent,tr("No GPX data layer found.")); 115 } 116 } 117 117 118 119 120 121 122 123 124 118 /** 119 * called when pressing "Import.." from context menu of EditGpx layer 120 * 121 */ 122 public void actionPerformed(ActionEvent arg0) { 123 activateImport(); 124 } 125 125 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxData.java
r21582 r23189 11 11 public class EditGpxData { 12 12 13 14 15 16 13 private final List<EditGpxTrack> tracks = new ArrayList<EditGpxTrack>(); 14 // Only copy of routes and waypoints to preserve all info when converting back to gpx track 15 private final List<GpxRoute> routes = new ArrayList<GpxRoute>(); 16 private final List<WayPoint> waypoints = new ArrayList<WayPoint>(); 17 17 18 19 20 21 22 23 24 25 26 27 28 18 public void load(GpxData data, boolean drop) { 19 if(drop) 20 tracks.clear(); 21 for (GpxTrack track: data.tracks) { 22 tracks.add(new EditGpxTrack(track)); 23 } 24 routes.clear(); 25 routes.addAll(data.routes); 26 waypoints.clear(); 27 waypoints.addAll(data.waypoints); 28 } 29 29 30 31 32 33 34 35 36 37 38 39 30 public boolean isEmpty() { 31 for (EditGpxTrack track: tracks) { 32 for (EditGpxTrackSegment segment: track.getSegments()) { 33 if (!segment.getWayPoints().isEmpty()) { 34 return false; 35 } 36 } 37 } 38 return true; 39 } 40 40 41 42 43 41 public List<EditGpxTrack> getTracks() { 42 return tracks; 43 } 44 44 45 46 45 public GpxData createGpxData() { 46 GpxData result = new GpxData(); 47 47 48 49 50 51 52 53 54 55 48 for (EditGpxTrack track: tracks) { 49 if (!track.isDeleted()) { 50 GpxTrack newTrack = track.createGpxTrack(); 51 if (!newTrack.getSegments().isEmpty()) { 52 result.tracks.add(newTrack); 53 } 54 } 55 } 56 56 57 58 59 60 57 result.routes.addAll(routes); 58 result.waypoints.addAll(waypoints); 59 return result; 60 } 61 61 62 62 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrack.java
r21472 r23189 14 14 public class EditGpxTrack { 15 15 16 17 18 16 private final List<EditGpxTrackSegment> segments = new ArrayList<EditGpxTrackSegment>(); 17 private final Map<String, Object> attributes = new HashMap<String, Object>(); 18 private boolean isDeleted; 19 19 20 21 22 23 24 25 20 public EditGpxTrack(GpxTrack track) { 21 attributes.putAll(track.getAttributes()); 22 for (GpxTrackSegment segment: track.getSegments()) { 23 segments.add(new EditGpxTrackSegment(segment)); 24 } 25 } 26 26 27 28 29 30 31 32 27 public List<EditGpxTrackSegment> getSegments() { 28 return segments; 29 } 30 public Map<String, Object> getAttributes() { 31 return attributes; 32 } 33 33 34 34 public GpxTrack createGpxTrack() { 35 35 36 36 Collection<Collection<WayPoint>> wayPoints = new ArrayList<Collection<WayPoint>>(); 37 37 38 39 40 41 42 43 44 45 38 for (EditGpxTrackSegment segment: segments) { 39 if (!segment.isDeleted()) { 40 List<WayPoint> points = segment.getNonDeletedWaypoints(); 41 if (!points.isEmpty()) { 42 wayPoints.add(points); 43 } 44 } 45 } 46 46 47 48 47 return new ImmutableGpxTrack(wayPoints, attributes); 48 } 49 49 50 51 52 50 public void setDeleted(boolean isDeleted) { 51 this.isDeleted = isDeleted; 52 } 53 53 54 55 56 54 public boolean isDeleted() { 55 return isDeleted; 56 } 57 57 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxTrackSegment.java
r21472 r23189 9 9 public class EditGpxTrackSegment { 10 10 11 12 11 private final List<EditGpxWayPoint> wayPoints = new ArrayList<EditGpxWayPoint>(); 12 private boolean deleted; 13 13 14 15 16 17 18 14 public EditGpxTrackSegment(GpxTrackSegment segment) { 15 for (WayPoint wayPoint: segment.getWayPoints()) { 16 wayPoints.add(new EditGpxWayPoint(wayPoint)); 17 } 18 } 19 19 20 21 22 20 public List<EditGpxWayPoint> getWayPoints() { 21 return wayPoints; 22 } 23 23 24 25 24 public List<WayPoint> getNonDeletedWaypoints() { 25 List<WayPoint> result = new ArrayList<WayPoint>(); 26 26 27 28 29 30 31 27 for (EditGpxWayPoint wp: wayPoints) { 28 if (!wp.isDeleted()) { 29 result.add(wp.createWayPoint()); 30 } 31 } 32 32 33 34 33 return result; 34 } 35 35 36 37 38 36 public void setDeleted(boolean deleted) { 37 this.deleted = deleted; 38 } 39 39 40 41 42 40 public boolean isDeleted() { 41 return deleted; 42 } 43 43 44 44 } -
applications/editors/josm/plugins/editgpx/src/org/openstreetmap/josm/plugins/editgpx/data/EditGpxWayPoint.java
r21472 r23189 8 8 9 9 public class EditGpxWayPoint { 10 11 12 13 10 private final double time; 11 private final CachedLatLon coor; 12 private boolean deleted; 13 private Map<String, Object> attributes; 14 14 15 16 17 18 19 15 public EditGpxWayPoint(WayPoint wayPoint) { 16 this.time = wayPoint.time; 17 this.coor = new CachedLatLon(wayPoint.getCoor()); 18 this.attributes = new HashMap<String, Object>(wayPoint.attr); 19 } 20 20 21 22 23 24 25 26 21 public WayPoint createWayPoint() { 22 WayPoint result = new WayPoint(getCoor()); 23 result.time = time; 24 result.attr = attributes; 25 return result; 26 } 27 27 28 29 30 28 public void setDeleted(boolean deleted) { 29 this.deleted = deleted; 30 } 31 31 32 33 34 32 public boolean isDeleted() { 33 return deleted; 34 } 35 35 36 37 38 36 public CachedLatLon getCoor() { 37 return coor; 38 } 39 39 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/AccessEvaluator.java
r16520 r23189 19 19 public interface AccessEvaluator<N, W> { 20 20 21 22 23 24 25 26 27 28 29 30 21 /** 22 * checks whether a way may be accessed in the given direction 23 * 24 * @param way object to be checked; != null 25 * @param segmentProperties map from road property types to their values for this way's 26 * segments; each value must be a valid value for its property type; 27 * != null 28 */ 29 public boolean wayUsable(W way, boolean forward, 30 Map<RoadPropertyType<?>, Object> roadPropertyValues); 31 31 32 33 34 35 36 37 38 39 40 32 /** 33 * checks whether a node may be accessed/passed 34 * 35 * @param node object to be checked; != null 36 * @param segmentProperties map from road property types to their values for SegmentNodes 37 * based on this node, each value must be a valid value for its 38 * property type; != null 39 */ 40 public boolean nodeUsable(N node, Map<RoadPropertyType<?>, Object> roadPropertyValues); 41 41 42 42 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/AccessParameters.java
r16520 r23189 11 11 public interface AccessParameters { 12 12 13 13 public String getAccessClass(); 14 14 15 16 17 18 19 15 /** 16 * returns true iff a road with a given access type can be used 17 * @param accessType access type to check usablitly for; != null 18 */ 19 public boolean getAccessTypeUsable(AccessType accessType); 20 20 21 22 23 24 25 26 21 /** 22 * returns all {@link VehiclePropertyType}s a value is avaliable for. 23 * The value can be accessed using {@link #getVehiclePropertyValue(VehiclePropertyType)} 24 * @return collection of property types; != null 25 */ 26 public Collection<VehiclePropertyType<?>> getAvailableVehicleProperties(); 27 27 28 29 30 31 32 33 34 35 36 37 28 /** 29 * returns the value for a vehicle property. 30 * 31 * @param <V> type of property value 32 * @param vehicleProperty property to get value for; != null 33 * @return value for vehicleProperty, null if no value is available. 34 * Guaranteed to be valid according to vehicleProperty's 35 * {@link VehiclePropertyType#isValidValue(Object)} method. 36 */ 37 public <V> V getVehiclePropertyValue(VehiclePropertyType<V> vehicleProperty); 38 38 39 39 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/AccessRuleset.java
r16520 r23189 12 12 public interface AccessRuleset { 13 13 14 15 16 17 18 19 20 21 22 23 14 /** 15 * for a mode of transport, returns all transport categories it is a subset of. 16 * For example, the returned collection for "motorcycle" might include "motor_vehicle" and "vehicle". 17 * 18 * @param transportMode mode of transport to get "supertypes" for; != null 19 * @return parameters superset categories, including the parameter itself, 20 * in the order of decreasing specificness 21 * empty if the parameter was no known mode of transport; != null 22 */ 23 public List<String> getAccessHierarchyAncestors(String transportMode); 24 24 25 26 27 28 29 30 25 /** 26 * returns all base tags. 27 * Base tags are tags that make an object "eligible" for access evaluation 28 * (commonly things like highway=* or barrier=*) 29 */ 30 public Collection<Tag> getBaseTags(); 31 31 32 33 34 35 36 32 /** 33 * returns ruleset-specific implications 34 * @return list of implications in the order they are expected to be applied; != null 35 */ 36 public List<Implication> getImplications(); 37 37 38 38 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/AccessRulesetReader.java
r16836 r23189 20 20 public class AccessRulesetReader { 21 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 22 public static class AccessRulesetSyntaxException extends IOException { 23 private static final long serialVersionUID = 1L; 24 public AccessRulesetSyntaxException(String message) { 25 super(message); 26 }; 27 public AccessRulesetSyntaxException(Throwable t) { 28 super(t.toString()); 29 } 30 } 31 32 /** private constructor to prevent instantiation */ 33 private AccessRulesetReader() { } 34 35 public static AccessRuleset readAccessRuleset(InputStream inputStream) 36 throws AccessRulesetSyntaxException, IOException { 37 38 RulesetHandler rulesetHandler = new RulesetHandler(); 39 40 try { 41 XMLReader reader = XMLReaderFactory.createXMLReader(); 42 InputSource input = new InputSource(inputStream); 43 reader.setContentHandler(rulesetHandler); 44 reader.setErrorHandler(null); 45 reader.parse(input); 46 } catch (SAXException e) { 47 throw new AccessRulesetSyntaxException(e); 48 } 49 50 return rulesetHandler.getAccessRuleset(); 51 } 52 53 private static class RulesetHandler extends DefaultHandler { 54 55 private static class AccessClass { 56 final String name; 57 final AccessClass parent; 58 public AccessClass(String name, AccessClass parent) { 59 this.name = name; 60 this.parent = parent; 61 } 62 List<String> getAncestorHierarchy() { 63 List<String> names; 64 if (parent == null) { 65 names = new LinkedList<String>(); 66 } else { 67 names = parent.getAncestorHierarchy(); 68 } 69 names.add(0, name); 70 return names; 71 } 72 } 73 74 private final Collection<AccessClass> accessClasses = new LinkedList<AccessClass>(); 75 private final Collection<Tag> baseTags = new LinkedList<Tag>(); 76 77 private static enum Section {NONE, CLASSES, BASETAGS, IMPLICATIONS}; 78 private Section currentSection = Section.NONE; 79 80 private AccessClass currentAccessClass = null; 81 82 private ImplicationXMLReader implicationReader = null; 83 private final List<Implication> implications = new LinkedList<Implication>(); 84 85 /** returns the AccessRuleset that was read */ 86 AccessRuleset getAccessRuleset() { 87 88 return new AccessRuleset() { 89 90 public List<String> getAccessHierarchyAncestors(String transportMode) { 91 for (AccessClass accessClass : accessClasses) { 92 if (accessClass.name.equals(transportMode)) { 93 return accessClass.getAncestorHierarchy(); 94 } 95 } 96 return new LinkedList<String>(); 97 } 98 99 public Collection<Tag> getBaseTags() { 100 return baseTags; 101 } 102 103 public List<Implication> getImplications() { 104 return implications; 105 } 106 107 }; 108 } 109 110 @Override 111 public void startElement(String uri, String localName, String name, 112 Attributes attributes) throws SAXException { 113 114 if (implicationReader != null) { 115 implicationReader.startElement(uri, localName, name, attributes); 116 return; 117 } 118 119 if ("classes".equals(name)) { 120 121 if (currentSection != Section.NONE) { 122 throw new SAXException("classes element below root child level"); 123 } 124 125 currentSection = Section.CLASSES; 126 127 } else if ("class".equals(name)) { 128 129 String className = attributes.getValue("name"); 130 131 if (currentSection != Section.CLASSES) { 132 throw new SAXException("class element (" + className + ") outside classes element"); 133 } else if (className == null) { 134 throw new SAXException("class element without name"); 135 } 136 137 AccessClass newAccessClass = new AccessClass(className, currentAccessClass); 138 139 accessClasses.add(newAccessClass); 140 141 currentAccessClass = newAccessClass; 142 143 } else if ("basetags".equals(name)) { 144 145 if (currentSection != Section.NONE) { 146 throw new SAXException("classes element below root child level"); 147 } 148 149 currentSection = Section.BASETAGS; 150 151 } else if ("tag".equals(name)) { 152 153 if (currentSection == Section.BASETAGS) { 154 baseTags.add(readTag(attributes)); 155 } else { 156 throw new SAXException("tag element outside basetag and implication elements"); 157 } 158 159 } else if ("implications".equals(name)) { 160 161 if (currentSection != Section.NONE) { 162 throw new SAXException("implications element below root child level"); 163 } 164 165 implicationReader = new ImplicationXMLReader(); 166 currentSection = Section.IMPLICATIONS; 167 168 } 169 170 } 171 172 private static Tag readTag(Attributes attributes) throws SAXException { 173 174 String key = attributes.getValue("k"); 175 String value = attributes.getValue("v"); 176 177 if (key == null) { 178 throw new SAXException("tag without key"); 179 } else if (value == null) { 180 throw new SAXException("tag without value (key is " + key + ")"); 181 } 182 183 return new Tag(key, value); 184 } 185 186 @Override 187 public void endElement(String uri, String localName, String name) 188 throws SAXException { 189 190 if (implicationReader != null && !"implications".equals(name)) { 191 implicationReader.endElement(uri, localName, name); 192 } 193 194 if ("classes".equals(name)) { 195 196 if (currentSection != Section.CLASSES) { 197 throw new SAXException("closed classes while it wasn't open"); 198 } else if (currentAccessClass != null) { 199 throw new SAXException("closed classes element before all class elements were closed"); 200 } 201 202 currentSection = Section.NONE; 203 204 } else if ("class".equals(name)) { 205 206 if (currentAccessClass == null) { 207 throw new SAXException("closed class element while none was open"); 208 } 209 210 currentAccessClass = currentAccessClass.parent; 211 212 } else if ("basetags".equals(name)) { 213 214 if (currentSection != Section.BASETAGS) { 215 throw new SAXException("closed basetags while it wasn't open"); 216 } 217 218 currentSection = Section.NONE; 219 220 } else if ("implications".equals(name)) { 221 222 if (currentSection != Section.IMPLICATIONS) { 223 throw new SAXException("closed implications while it wasn't open"); 224 } 225 226 implications.addAll(implicationReader.getImplications()); 227 implicationReader = null; 228 currentSection = Section.NONE; 229 230 } 231 232 } 233 234 }; 235 235 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/AccessType.java
r16520 r23189 3 3 public enum AccessType { 4 4 5 6 7 8 9 10 11 12 13 14 5 YES("yes"), 6 PERMISSIVE("permissive"), 7 DESIGNATED("designated"), 8 DESTINATION("destination"), 9 AGRICULTURAL("agricultural"), 10 FORESTRY("forestry"), 11 DELIVERY("delivery"), 12 PRIVATE("private"), 13 NO("no"), 14 UNDEFINED(); 15 15 16 17 18 19 16 private String[] valueStrings; 17 private AccessType(String... valueStrings) { 18 this.valueStrings = valueStrings; 19 } 20 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 21 /** 22 * returns the AccessType that fits for a tag's value 23 * 24 * @param valueString a tag's value; != null 25 * @return AccessType for the value; != null, will be UNDEFINED for unknown values 26 */ 27 public static AccessType getAccessType(String valueString) { 28 for (AccessType accessType : AccessType.values()) { 29 for (String typeValueString : accessType.valueStrings) { 30 if (typeValueString.equals(valueString)) { 31 return accessType; 32 } 33 } 34 } 35 return UNDEFINED; 36 } 37 37 38 38 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/Implication.java
r16520 r23189 15 15 public final class Implication { 16 16 17 18 17 private final TagCondition condition; 18 private final Collection<Tag> impliedTags; 19 19 20 21 22 23 20 public Implication(TagCondition condition, Collection<Tag> impliedTags) { 21 this.condition = condition; 22 this.impliedTags = impliedTags; 23 } 24 24 25 26 27 28 29 30 31 32 25 /** 26 * applies this implication to a tag group. 27 * The resulting tag group will contain all tags from the original group 28 * and all implied tags with a key that didn't occur in the original group. 29 * 30 * @param tags tag group to apply implications to; != null 31 */ 32 public TagGroup apply(TagGroup tags) { 33 33 34 34 if (condition.matches(tags)) { 35 35 36 36 Map<String, String> newTagMap = new HashMap<String, String>(); 37 37 38 39 40 38 for (Tag tag : tags) { 39 newTagMap.put(tag.key, tag.value); 40 } 41 41 42 43 44 45 46 42 for (Tag impliedTag : impliedTags) { 43 if (!newTagMap.containsKey(impliedTag.key)) { 44 newTagMap.put(impliedTag.key, impliedTag.value); 45 } 46 } 47 47 48 48 return new MapBasedTagGroup(newTagMap); 49 49 50 51 52 50 } else { 51 return tags; 52 } 53 53 54 54 } 55 55 56 57 58 59 56 @Override 57 public String toString() { 58 return condition.toString() + " => " + impliedTags.toString(); 59 } 60 60 61 61 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/ImplicationXMLReader.java
r16520 r23189 17 17 public class ImplicationXMLReader { 18 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 19 private final List<Implication> implications = new LinkedList<Implication>(); 20 21 private static enum State {BEFORE_IMPLICATION, BEFORE_CONDITION, CONDITION, BEFORE_IMPLIES, IMPLIES, AFTER_IMPLIES}; 22 private State state = State.BEFORE_IMPLICATION; 23 24 private ConditionReader currentConditionReader; 25 private TagCondition currentCondition; 26 private Collection<Tag> currentImpliedTags; 27 28 boolean tagOpen = false; 29 30 public void startElement(String uri, String localName, String name, Attributes attributes) 31 throws SAXException { 32 33 switch (state) { 34 35 case BEFORE_IMPLICATION: 36 37 if ("implication".equals(name)) { 38 state = State.BEFORE_CONDITION; 39 return; 40 } 41 break; 42 43 case BEFORE_CONDITION: 44 45 if ("condition".equals(name)) { 46 currentConditionReader = new ConditionReader(); 47 state = State.CONDITION; 48 return; 49 } 50 break; 51 52 case CONDITION: 53 currentConditionReader.startElement(uri, localName, name, attributes); 54 return; 55 56 case BEFORE_IMPLIES: 57 58 if ("implies".equals(name)) { 59 currentImpliedTags = new LinkedList<Tag>(); 60 state = State.IMPLIES; 61 return; 62 } 63 break; 64 65 case IMPLIES: 66 67 if ("tag".equals(name)) { 68 if (tagOpen) { 69 throw new SAXException("tag element inside other tag element"); 70 } 71 currentImpliedTags.add(readTag(attributes)); 72 tagOpen = true; 73 return; 74 } 75 break; 76 77 } 78 79 //all vaild paths end with return; reaching this indicates an invalid tag 80 throw new SAXException("invalid opening xml tag <" + name + "> in state " + state); 81 82 } 83 84 public void endElement(String uri, String localName, String name) 85 throws SAXException { 86 87 switch (state) { 88 89 case CONDITION: 90 91 if (name.equals("condition")) { 92 if (!currentConditionReader.isFinished()) { 93 throw new SAXException("condition isn't finished at </condition> tag"); 94 } else { 95 currentCondition = currentConditionReader.getCondition(); 96 currentConditionReader = null; 97 state = State.BEFORE_IMPLIES; 98 return; 99 } 100 } else { 101 currentConditionReader.endElement(uri, localName, name); 102 return; 103 } 104 105 case IMPLIES: 106 107 if (name.equals("implies")) { 108 state = State.AFTER_IMPLIES; 109 return; 110 } else if (name.equals("tag")) { 111 if (!tagOpen) { 112 throw new SAXException("closing tag element that was not open"); 113 } 114 tagOpen = false; 115 return; 116 } 117 break; 118 119 case AFTER_IMPLIES: 120 121 if (name.equals("implication")) { 122 implications.add(new Implication(currentCondition, currentImpliedTags)); 123 currentCondition = null; 124 currentImpliedTags = null; 125 state = State.BEFORE_IMPLICATION; 126 return; 127 } 128 break; 129 130 } 131 132 //all vaild paths end with return; reaching this indicates an invalid tag 133 throw new SAXException("invalid closing xml tag </" + name + "> in state " + state); 134 135 } 136 137 public List<Implication> getImplications() throws SAXException { 138 139 if (state != State.BEFORE_IMPLICATION) { 140 throw new SAXException("some tags not been closed; now in state " + state); 141 } else { 142 return new ArrayList<Implication>(implications); 143 } 144 } 145 146 private static Tag readTag(Attributes attributes) throws SAXException { 147 148 String key = attributes.getValue("k"); 149 String value = attributes.getValue("v"); 150 151 if (key == null) { 152 throw new SAXException("tag without key"); 153 } else if (value == null) { 154 throw new SAXException("tag without value (key is " + key + ")"); 155 } 156 157 return new Tag(key, value); 158 } 159 160 private static String readKey(Attributes attributes) throws SAXException { 161 162 String key = attributes.getValue("k"); 163 164 if (key == null) { 165 throw new SAXException("key element without attribute k"); 166 } 167 168 return key; 169 } 170 171 /** 172 * class to be used for reading tag condition sections of xml files 173 */ 174 private static class ConditionReader { 175 176 String openingName; 177 TagCondition condition; 178 boolean finished; 179 180 private final List<ConditionReader> childReaders = new LinkedList<ConditionReader>(); 181 private ConditionReader currentChildReader = null; 182 183 public void startElement(String uri, String localName, String name, Attributes attributes) 184 throws SAXException { 185 186 if (finished) { 187 throw new SAXException("condition is already finished at <" + name + ">"); 188 } 189 190 if (currentChildReader != null) { 191 currentChildReader.startElement(uri, localName, name, attributes); 192 return; 193 } 194 195 //first tag is start tag of this condition 196 if (openingName == null) { 197 198 openingName = name; 199 200 if ("tag".equals(name)) { 201 condition = TagConditionLogic.tag(readTag(attributes)); 202 } else if ("key".equals(name)) { 203 condition = TagConditionLogic.key(readKey(attributes)); 204 } else if (!("or".equals(name)) && !("and".equals(name)) && !("not".equals(name))) { 205 throw new SAXException("unknown tag for condition: " + name); 206 } 207 208 //all tags after the first are start tags of child conditions 209 } else { 210 211 if ("tag".equals(openingName) || "key".equals(openingName)) { 212 throw new SAXException("element must not have childs: " + openingName); 213 } 214 215 currentChildReader = new ConditionReader(); 216 currentChildReader.startElement(uri, localName, name, attributes); 217 218 } 219 220 } 221 222 public void endElement(String uri, String localName, String name) 223 throws SAXException { 224 225 if (finished) { 226 throw new SAXException("condition is already finished at </" + name + ">"); 227 } 228 229 /* if active child reader exists, pass parameter to it. */ 230 if (currentChildReader != null) { 231 232 currentChildReader.endElement(uri, localName, name); 233 234 if (currentChildReader.isFinished()) { 235 childReaders.add(currentChildReader); 236 currentChildReader = null; 237 } 238 239 } else { 240 241 if (openingName.equals(name)) { 242 243 List<TagCondition> childConditions = new ArrayList<TagCondition>(); 244 for (ConditionReader childReader : childReaders) { 245 childConditions.add(childReader.getCondition()); 246 } 247 248 if ("and".equals(openingName)) { 249 if (childConditions.size() > 0) { 250 condition = TagConditionLogic.and(childConditions); 251 } else { 252 throw new SAXException("<and> needs at least one child"); 253 } 254 } else if ("or".equals(openingName)) { 255 if (childConditions.size() > 0) { 256 condition = TagConditionLogic.or(childConditions); 257 } else { 258 throw new SAXException("<or> needs at least one child"); 259 } 260 } else if ("not".equals(openingName)) { 261 if (childConditions.size() == 1) { 262 condition = TagConditionLogic.not(childConditions.get(0)); 263 } else { 264 throw new SAXException("<not> needs at least one child"); 265 } 266 } 267 268 finished = true; 269 270 } else { 271 throw new SAXException("wrong closing tag " + name + 272 " (</" + openingName + "> expected"); 273 } 274 275 } 276 277 } 278 279 public boolean isFinished() { 280 return finished; 281 } 282 283 public TagCondition getCondition() { 284 if (!finished) { 285 throw new IllegalStateException("condition " + openingName + " not yet finished"); 286 } else { 287 assert condition != null; 288 return condition; 289 } 290 } 291 292 } 293 293 294 294 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/access/RulesetAccessEvaluator.java
r19216 r23189 18 18 public class RulesetAccessEvaluator<N, W, R, M> implements AccessEvaluator<N, W> { 19 19 20 21 22 20 private final DataSource<N, W, R, M> dataSource; 21 private final AccessRuleset ruleset; 22 private final AccessParameters parameters; 23 23 24 25 26 27 28 29 30 31 24 /** 25 * @param dataSource object that allows access to data objects and tags/members; != null 26 * @param ruleset ruleset that is used for evaluation; != null 27 * @param parameters parameters object that describes the vehicle 28 * and situation to evaluate access for; != null 29 */ 30 public RulesetAccessEvaluator(DataSource<N, W, R, M> dataSource, AccessRuleset ruleset, AccessParameters parameters) { 31 assert dataSource != null && ruleset != null && parameters != null; 32 32 33 34 35 33 this.dataSource = dataSource; 34 this.ruleset = ruleset; 35 this.parameters = parameters; 36 36 37 37 } 38 38 39 40 39 public boolean wayUsable(W way, boolean forward, 40 Map<RoadPropertyType<?>, Object> segmentPropertyValues) { 41 41 42 42 TagGroup wayTags = dataSource.getTagsW(way); 43 43 44 45 46 47 44 TagGroup wayTagsWithImplications = new MapBasedTagGroup(wayTags); 45 for (Implication implication : ruleset.getImplications()) { 46 wayTagsWithImplications = implication.apply(wayTagsWithImplications); 47 } 48 48 49 49 /* check base tagging */ 50 50 51 52 53 54 55 56 57 51 boolean usableWay = false; 52 for (Tag tag : ruleset.getBaseTags()) { 53 if (wayTags.contains(tag)) { 54 usableWay = true; 55 break; 56 } 57 } 58 58 59 60 61 59 if (!usableWay) { 60 return false; 61 } 62 62 63 63 /* evaluate one-way tagging */ 64 64 65 65 String onewayValue = wayTagsWithImplications.getValue("oneway"); 66 66 67 68 69 70 67 if (forward && "-1".equals(onewayValue) 68 && !"foot".equals(parameters.getAccessClass())) { 69 return false; 70 } 71 71 72 73 74 75 76 72 if (!forward 73 && ("1".equals(onewayValue) || "yes".equals(onewayValue) || "true".equals(onewayValue)) 74 && !"foot".equals(parameters.getAccessClass())) { 75 return false; 76 } 77 77 78 78 /* evaluate properties and access tagging */ 79 79 80 81 80 return objectUsable(segmentPropertyValues, wayTags); 81 } 82 82 83 83 public boolean nodeUsable(N node, Map<RoadPropertyType<?>,Object> roadPropertyValues) { 84 84 85 85 TagGroup nodeTags = dataSource.getTagsN(node); 86 86 87 88 87 return objectUsable(roadPropertyValues, nodeTags); 88 }; 89 89 90 91 90 private boolean objectUsable(Map<RoadPropertyType<?>, Object> roadPropertyValues, 91 TagGroup tags) { 92 92 93 93 /* evaluate road properties */ 94 94 95 96 97 98 99 95 for (RoadPropertyType<?> property : roadPropertyValues.keySet()) { 96 if (!property.isUsable(roadPropertyValues.get(property), parameters)) { 97 return false; 98 } 99 } 100 100 101 101 /* evaluate access type */ 102 102 103 103 AccessType accessType = UNDEFINED; 104 104 105 105 if (tags.size() > 0) { 106 106 107 108 107 Map<String, AccessType> accessTypePerClass = 108 createAccessTypePerClassMap(tags, ruleset.getAccessHierarchyAncestors(parameters.getAccessClass())); 109 109 110 111 112 113 110 for (String accessClass : ruleset.getAccessHierarchyAncestors(parameters.getAccessClass())) { 111 accessType = accessTypePerClass.get(accessClass); 112 if (accessType != UNDEFINED) { break; } 113 } 114 114 115 115 } 116 116 117 118 117 return parameters.getAccessTypeUsable(accessType); 118 } 119 119 120 121 120 private Map<String, AccessType> createAccessTypePerClassMap( 121 TagGroup wayTags, Collection<String> accessClasses) { 122 122 123 124 125 126 123 /* 124 * create map and fill with UNDEFINED values 125 * (this also allows to use keySet instead of accessClasses later) 126 */ 127 127 128 128 Map<String, AccessType> accessTypePerClass = new HashMap<String, AccessType>(); 129 129 130 131 132 130 for (String accessClass : accessClasses) { 131 accessTypePerClass.put(accessClass, AccessType.UNDEFINED); 132 } 133 133 134 134 /* evaluate implied tagging of base tag */ 135 135 136 137 138 139 140 141 142 136 Tag baseTag = null; 137 for (Tag tag : wayTags) { 138 if (ruleset.getBaseTags().contains(tag)) { 139 baseTag = tag; 140 break; 141 } 142 } 143 143 144 144 if (baseTag != null) { 145 145 146 147 148 149 146 TagGroup tagsWithBaseImplications = new MapBasedTagGroup(baseTag); 147 for (Implication implication : ruleset.getImplications()) { 148 tagsWithBaseImplications = implication.apply(tagsWithBaseImplications); 149 } 150 150 151 151 setAccessTypesFromTags(accessTypePerClass, tagsWithBaseImplications); 152 152 153 153 } 154 154 155 155 /* evaluate implied tagging of other tags */ 156 156 157 158 159 160 161 162 157 Map<String, String> tagMap = new HashMap<String, String>(); 158 for (Tag tag : wayTags) { 159 if (!tag.equals(baseTag)) { 160 tagMap.put(tag.key, tag.value); 161 } 162 } 163 163 164 165 166 167 164 TagGroup tagsWithOtherImplications = new MapBasedTagGroup(tagMap); 165 for (Implication implication : ruleset.getImplications()) { 166 tagsWithOtherImplications = implication.apply(tagsWithOtherImplications); 167 } 168 168 169 169 setAccessTypesFromTags(accessTypePerClass, tagsWithOtherImplications); 170 170 171 171 /* evaluate explicit access tagging */ 172 172 173 174 175 176 177 178 179 173 for (String key : ruleset.getAccessHierarchyAncestors(parameters.getAccessClass())) { 174 String value = wayTags.getValue(key); 175 if (value != null) { 176 AccessType accessType = AccessType.getAccessType(value); 177 accessTypePerClass.put(key, accessType); 178 } 179 } 180 180 181 182 181 return accessTypePerClass; 182 } 183 183 184 185 186 187 188 189 190 191 192 193 194 195 196 184 /** 185 * adds all access information from a collection of tags to a [access class -> access type] map. 186 * Existing entries will be replaced. 187 */ 188 private void setAccessTypesFromTags(Map<String, AccessType> accessTypePerClass, TagGroup tags) { 189 for (String accessClass : accessTypePerClass.keySet()) { 190 String value = tags.getValue(accessClass); 191 if (value != null) { 192 AccessType accessType = AccessType.getAccessType(value); 193 accessTypePerClass.put(accessClass, accessType); 194 } 195 } 196 } 197 197 198 198 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/data/DataSource.java
r19216 r23189 9 9 */ 10 10 public interface DataSource<N, W, R, M> { 11 12 /** returns all nodes */13 public Iterable<N> getNodes();14 11 15 ways */16 W> getWays();12 /** returns all nodes */ 13 public Iterable<N> getNodes(); 17 14 18 relations */19 R> getRelations();15 /** returns all ways */ 16 public Iterable<W> getWays(); 20 17 21 node's latitude*/22 double getLat(N node);18 /** returns all relations */ 19 public Iterable<R> getRelations(); 23 20 24 ongitude */25 on(N node);21 /** returns a node's latitude */ 22 public double getLat(N node); 26 23 27 way's nodes*/28 Iterable<N> getNodes(W way);24 /** returns a node's longitude */ 25 public double getLon(N node); 29 26 30 relation's members */31 M> getMembers(R relation);27 /** returns a way's nodes */ 28 public Iterable<N> getNodes(W way); 32 29 33 node's tags */34 TagGroup getTagsN(N node);30 /** returns a relation's members */ 31 public Iterable<M> getMembers(R relation); 35 32 36 way's tags */37 W(W way);33 /** returns a node's tags */ 34 public TagGroup getTagsN(N node); 38 35 39 relation's tags */40 R(R relation);36 /** returns a way's tags */ 37 public TagGroup getTagsW(W way); 41 38 42 member's role*/43 String getRole(M member);39 /** returns a relation's tags */ 40 public TagGroup getTagsR(R relation); 44 41 45 /** returns a relation member's member object */ 46 public Object getMember(M member); 47 48 /** returns whether a relation member is a node */ 49 public boolean isNMember(M member); 50 51 /** returns whether a relation member is a way */ 52 public boolean isWMember(M member); 53 54 /** returns whether a relation member is a relation */ 55 public boolean isRMember(M member); 56 57 /** 58 * adds an observer. 59 * Does nothing if the parameter is already an observer of this DataSource. 60 * 61 * @param observer observer object, != null 62 */ 63 public void addObserver(DataSourceObserver observer); 42 /** returns a relation member's role */ 43 public String getRole(M member); 64 44 65 /** 66 * deletes an observer that has been added using {@link #addObserver(DataSourceObserver)}. 67 * Does nothing if the parameter isn't currently an observer of this DataSource. 68 * 69 * @param observer observer object, != null 70 */ 71 public void deleteObserver(DataSourceObserver observer); 45 /** returns a relation member's member object */ 46 public Object getMember(M member); 47 48 /** returns whether a relation member is a node */ 49 public boolean isNMember(M member); 50 51 /** returns whether a relation member is a way */ 52 public boolean isWMember(M member); 53 54 /** returns whether a relation member is a relation */ 55 public boolean isRMember(M member); 56 57 /** 58 * adds an observer. 59 * Does nothing if the parameter is already an observer of this DataSource. 60 * 61 * @param observer observer object, != null 62 */ 63 public void addObserver(DataSourceObserver observer); 64 65 /** 66 * deletes an observer that has been added using {@link #addObserver(DataSourceObserver)}. 67 * Does nothing if the parameter isn't currently an observer of this DataSource. 68 * 69 * @param observer observer object, != null 70 */ 71 public void deleteObserver(DataSourceObserver observer); 72 72 73 73 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/data/DataSourceObserver.java
r19216 r23189 8 8 public interface DataSourceObserver { 9 9 10 11 12 13 14 10 /** 11 * informs this observer about changes in an observed data source 12 * @param dataSource observed data source that has changed; != null 13 */ 14 public void update(DataSource<?, ?, ?, ?> dataSource); 15 15 16 16 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/data/MapBasedTagGroup.java
r16520 r23189 13 13 public class MapBasedTagGroup implements TagGroup { 14 14 15 15 private final Map<String, String> tagMap; 16 16 17 18 19 20 21 22 23 24 17 /** 18 * @param tagMap map from keys to values; != null; 19 * must not be modified after being used as parameter 20 */ 21 public MapBasedTagGroup(Map<String, String> tagMap) { 22 if (tagMap == null) { 23 throw new IllegalArgumentException(); 24 } 25 25 26 27 26 this.tagMap = tagMap; 27 } 28 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 29 /** 30 * @param tags tags to add to the group; != null, each != null 31 */ 32 public MapBasedTagGroup(Iterable<Tag> tags) { 33 if (tags == null) { 34 throw new IllegalArgumentException(); 35 } 36 this.tagMap = new HashMap<String, String>(); 37 for (Tag tag : tags) { 38 if (tag == null) { 39 throw new IllegalArgumentException(); 40 } else { 41 this.tagMap.put(tag.key, tag.value); 42 } 43 } 44 } 45 45 46 47 48 49 50 51 52 53 54 55 56 57 58 46 /** 47 * @param tags tags to add to the group; each != null 48 */ 49 public MapBasedTagGroup(Tag... tags) { 50 this.tagMap = new HashMap<String, String>(tags.length); 51 for (Tag tag : tags) { 52 if (tag == null) { 53 throw new IllegalArgumentException(); 54 } else { 55 this.tagMap.put(tag.key, tag.value); 56 } 57 } 58 } 59 59 60 61 62 63 60 public String getValue(String key) { 61 assert key != null; 62 return tagMap.get(key); 63 } 64 64 65 66 67 68 65 public boolean containsKey(String key) { 66 assert key != null; 67 return tagMap.containsKey(key); 68 } 69 69 70 71 72 73 70 public boolean containsValue(String value) { 71 assert value != null; 72 return tagMap.containsValue(value); 73 } 74 74 75 76 77 78 75 public boolean contains(Tag tag) { 76 assert tag != null; 77 return tag.value.equals(tagMap.get(tag.key)); 78 } 79 79 80 81 82 80 public int size() { 81 return tagMap.size(); 82 } 83 83 84 85 86 87 88 84 /** 85 * returns an Iterator providing access to all Tags. 86 * The Iterator does not support the {@link Iterator#remove()} method. 87 */ 88 public Iterator<Tag> iterator() { 89 89 90 90 Collection<Tag> tagCollection = new LinkedList<Tag>(); 91 91 92 93 94 92 for (String key : tagMap.keySet()) { 93 tagCollection.add(new Tag(key, tagMap.get(key))); 94 } 95 95 96 96 return Collections.unmodifiableCollection(tagCollection).iterator(); 97 97 98 98 } 99 99 100 101 102 103 100 @Override 101 public String toString() { 102 return tagMap.toString(); 103 } 104 104 105 105 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/data/Tag.java
r16520 r23189 6 6 public class Tag { 7 7 8 9 8 /** key of the tag; != null */ 9 public final String key; 10 10 11 12 11 /** value of the tag; != null */ 12 public final String value; 13 13 14 15 16 17 18 14 public Tag(String key, String value) { 15 assert key != null && value != null; 16 this.key = key; 17 this.value = value; 18 } 19 19 20 21 22 23 24 25 26 27 28 20 @Override 21 public boolean equals(Object obj) { 22 if (!(obj instanceof Tag)) { 23 return false; 24 } else { 25 Tag otherTag = (Tag)obj; 26 return key.equals(otherTag.key) && value.equals(otherTag.value); 27 } 28 } 29 29 30 31 32 33 30 @Override 31 public int hashCode() { 32 return key.hashCode() + value.hashCode(); 33 } 34 34 35 36 37 38 35 @Override 36 public String toString() { 37 return key + "=" + value; 38 } 39 39 40 40 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/data/TagGroup.java
r16520 r23189 8 8 public interface TagGroup extends Iterable<Tag> { 9 9 10 11 12 13 14 10 /** 11 * returns the value for the given key or null if no tag in this group uses that key 12 * @param key key whose value will be returned; != null 13 */ 14 public String getValue(String key); 15 15 16 17 18 19 20 16 /** 17 * returns true if this tag group contains a tag with the given key 18 * @param key key to check for; != null 19 */ 20 public boolean containsKey(String key); 21 21 22 23 24 25 26 22 /** 23 * returns true if this tag group contains at least one tag with the given value 24 * @param value value to check for; != null 25 */ 26 public boolean containsValue(String value); 27 27 28 29 30 31 32 28 /** 29 * returns true if this tag group contains the given tag 30 * @param tag tag to check for; != null 31 */ 32 public boolean contains(Tag tag); 33 33 34 35 36 37 34 /** 35 * returns the number of tags in this group 36 */ 37 public int size(); 38 38 39 39 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/ConnectorEvaluationGroup.java
r18130 r23189 16 16 public class ConnectorEvaluationGroup extends EvaluationGroup { 17 17 18 19 18 private final Set<Segment> segments; 19 private final List<SegmentNode> borderNodes; 20 20 21 22 23 24 25 26 27 21 /** 22 * @param segments set of Segments, must not be modified 23 * after being used as constructor parameter; != null 24 * @param borderNodes nodes that are used as starting/target nodes for sequences; != null 25 */ 26 public ConnectorEvaluationGroup(Set<Segment> segments, Set<SegmentNode> borderNodes) { 27 assert segments != null && borderNodes != null; 28 28 29 30 31 29 this.segments = segments; 30 this.borderNodes = new ArrayList<SegmentNode>(borderNodes); 31 } 32 32 33 34 35 36 37 38 39 33 /** 34 * returns all nodes that can be used as start/target nodes 35 * @return border nodes; != null 36 */ 37 public Collection<SegmentNode> getBorderNodes() { 38 return borderNodes; 39 } 40 40 41 42 43 44 45 46 47 41 /** 42 * returns all segments in the group 43 * @return segment set; != null 44 */ 45 public Set<Segment> getSegments() { 46 return segments; 47 } 48 48 49 50 51 52 53 54 55 56 57 58 59 60 49 /** 50 * returns a segment sequence that runs from an inbound to an outbound 51 * segment or null if no connection is possible. 52 * {@link EvaluationGroup#evaluate(Collection)} needs be called before this method. 53 * 54 * @param startNode start of the potential sequence; must be border node; != null 55 * @param targetNode target of the potential sequence; must be border node; != null 56 * @return sequence of segments or null 57 */ 58 public List<Segment> getSegmentSequence(SegmentNode startNode, SegmentNode targetNode) { 59 assert startNode != null && borderNodes.contains(startNode); 60 assert targetNode != null && borderNodes.contains(targetNode); 61 61 62 62 if (!evaluated) { throw new IllegalStateException("group not yet evaluated"); } 63 63 64 65 64 int inboundIndex = borderNodes.indexOf(startNode); 65 int outboundIndex = borderNodes.indexOf(targetNode); 66 66 67 68 67 return segmentSequences[inboundIndex][outboundIndex]; 68 } 69 69 70 71 70 @Override 71 protected void evaluateImpl(Collection<Restriction> restrictions) { 72 72 73 73 /* find segment sequences from inbound to outbound segments */ 74 74 75 76 75 @SuppressWarnings("unchecked") //cannot create generic array without cast 76 List<Segment>[][] sequenceArray = new List[borderNodes.size()][borderNodes.size()]; 77 77 78 79 78 for (int startIndex = 0; startIndex < borderNodes.size(); startIndex ++) { 79 for (int targetIndex = 0; targetIndex < borderNodes.size(); targetIndex ++) { 80 80 81 82 83 81 List<Segment> sequence = 82 findSegmentSequence(borderNodes.get(startIndex), 83 borderNodes.get(targetIndex), restrictions); 84 84 85 85 sequenceArray[startIndex][targetIndex] = sequence; 86 86 87 88 87 } 88 } 89 89 90 91 90 segmentSequences = sequenceArray; 91 } 92 92 93 94 95 96 97 93 @Override 94 protected boolean isUsableNode(SegmentNode node) { 95 return shareElement(segments, node.getInboundSegments()) 96 || shareElement(segments, node.getOutboundSegments()); 97 } 98 98 99 100 101 102 99 @Override 100 protected boolean isUsableSegment(Segment segment) { 101 return segments.contains(segment); 102 } 103 103 104 105 106 107 104 @Override 105 public String toString() { 106 return "ConnectorEG " + segments; 107 } 108 108 109 109 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/EvaluationGroup.java
r16520 r23189 19 19 abstract class EvaluationGroup { 20 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 21 protected boolean evaluated = false; 22 23 /** 24 * array of sequences. 25 * First index is inbound segment/start node index, 26 * second index is outbound segment/target node index. 27 * Will contain the segment sequence after evaluation or null if none exists. 28 */ 29 protected List<Segment>[][] segmentSequences; 30 31 private static final List<Segment> EMPTY_SEGMENT_LIST = 32 Collections.unmodifiableList(new ArrayList<Segment>(0)); 33 34 private static final List<Restriction> EMPTY_RESTRICTION_LIST = 35 Collections.unmodifiableList(new ArrayList<Restriction>(0)); 36 37 private static class State { 38 SegmentNode currentNode; 39 Set<SegmentNode> visitedNodes; 40 Collection<Restriction> activeRestrictions; 41 List<Segment> segmentHistory; 42 } 43 44 45 /** 46 * tries to find a legal sequence of segments between two segment nodes. 47 * 48 * @return list of segments if connection is possible, null otherwise. 49 */ 50 protected List<Segment> findSegmentSequence( 51 SegmentNode firstNode, SegmentNode lastNode, 52 Collection<Restriction> restrictions) { 53 54 return findSegmentSequence(firstNode, lastNode, restrictions, 55 EMPTY_RESTRICTION_LIST, EMPTY_RESTRICTION_LIST); 56 57 } 58 59 /** 60 * tries to find a legal sequence of segments between two segments. 61 * 62 * @return list of segments if connection is possible, null otherwise. 63 * The list does NOT include firstSegment and lastSegment, 64 * but they are considered for restrictions. 65 */ 66 protected List<Segment> findSegmentSequence( 67 Segment firstSegment, Segment lastSegment, 68 Collection<Restriction> restrictions) { 69 70 if (firstSegment == lastSegment) { 71 72 return EMPTY_SEGMENT_LIST; 73 74 } else { 75 76 Collection<Restriction> initiallyActiveRestrictions = 77 activeRestrictionsAfterSegment(firstSegment, EMPTY_RESTRICTION_LIST, restrictions); 78 79 Collection<Restriction> restrictionsForbiddenAtLastNode = new HashSet<Restriction>(); 80 for (Restriction restriction : restrictions) { 81 if (restriction.getTos().contains(lastSegment)) { 82 restrictionsForbiddenAtLastNode.add(restriction); 83 } 84 } 85 86 return findSegmentSequence( 87 firstSegment.getNode2(), lastSegment.getNode1(), restrictions, 88 initiallyActiveRestrictions, restrictionsForbiddenAtLastNode); 89 } 90 91 } 92 93 /** 94 * tries to find a legal sequence of segments between two segment nodes. 95 * 96 * @param restrictions all restrictions that have to be taken into account 97 * @param initiallyActiveRestrictions restrictions that are already active at firstNode 98 * @param restrictionsForbiddenAtLastNode restrictions that must NOT be active at lastNode 99 * @return list of segments if connection is possible, null otherwise. 100 */ 101 private List<Segment> findSegmentSequence( 102 SegmentNode firstNode, SegmentNode lastNode, 103 Collection<Restriction> restrictions, 104 Collection<Restriction> initiallyActiveRestrictions, 105 Collection<Restriction> restrictionsForbiddenAtLastNode) { 106 107 if (firstNode == lastNode 108 && !shareElement(initiallyActiveRestrictions, restrictionsForbiddenAtLastNode)) { 109 return EMPTY_SEGMENT_LIST; 110 } 111 112 Queue<State> stateQueue = new LinkedList<State>(); 113 stateQueue.add(createStartingState(firstNode, initiallyActiveRestrictions)); 114 115 /* search for a possible segment sequence */ 116 117 while (stateQueue.size() > 0) { 118 119 State state = stateQueue.poll(); 120 121 Collection<State> subsequentStates = createSubsequentStates(state, restrictions); 122 123 for (State subsequentState : subsequentStates) { 124 if (subsequentState.currentNode == lastNode 125 && !shareElement(subsequentState.activeRestrictions, 126 restrictionsForbiddenAtLastNode)) { 127 return subsequentState.segmentHistory; 128 } 129 } 130 131 stateQueue.addAll(subsequentStates); 132 133 } 134 135 return null; 136 } 137 138 private static State createStartingState(SegmentNode firstNode, 139 Collection<Restriction> initiallyActiveRestrictions) { 140 141 State startingState = new State(); 142 startingState.currentNode = firstNode; 143 startingState.activeRestrictions = initiallyActiveRestrictions; 144 startingState.segmentHistory = EMPTY_SEGMENT_LIST; 145 startingState.visitedNodes = new HashSet<SegmentNode>(); 146 startingState.visitedNodes.add(firstNode); 147 148 return startingState; 149 } 150 151 private List<State> createSubsequentStates(State state, Collection<Restriction> allRestrictions) { 152 153 List<State> subsequentStates = new ArrayList<State>(); 154 155 for (Segment segment : state.currentNode.getOutboundSegments()) { 156 157 if (isUsableSegment(segment) && 158 isLegalSegment(segment, state.activeRestrictions)) { 159 160 State newState = new State(); 161 162 newState.activeRestrictions = activeRestrictionsAfterSegment( 163 segment, state.activeRestrictions, allRestrictions); 164 165 newState.segmentHistory = new ArrayList<Segment>(state.segmentHistory.size() + 1); 166 newState.segmentHistory.addAll(state.segmentHistory); 167 newState.segmentHistory.add(segment); 168 169 newState.currentNode = segment.getNode2(); 170 171 newState.visitedNodes = new HashSet<SegmentNode>(state.visitedNodes); 172 newState.visitedNodes.add(newState.currentNode); 173 174 /* add state to queue, 175 * but avoid cycles as well as leaving the node set 176 */ 177 178 if (!state.visitedNodes.contains(newState.currentNode) 179 && isUsableNode(newState.currentNode)) { 180 181 subsequentStates.add(newState); 182 183 } 184 } 185 } 186 187 return subsequentStates; 188 } 189 190 /** 191 * returns all restrictions from a collection that have a segment as from member 192 * @return segment list; != null; must not be modified. 193 * May throw an exception when modifying is attempted. 194 */ 195 private static List<Restriction> getRestrictionsStartedBySegment( 196 Collection<Restriction> restrictions, Segment segment) { 197 198 List<Restriction> result = EMPTY_RESTRICTION_LIST; 199 for (Restriction restriction : restrictions) { 200 if (restriction.getFrom() == segment) { 201 if (result == EMPTY_RESTRICTION_LIST) { 202 result = new ArrayList<Restriction>(restrictions.size()); 203 } 204 result.add(restriction); 205 } 206 } 207 208 return result; 209 } 210 211 private static Collection<Restriction> activeRestrictionsAfterSegment(Segment segment, 212 Collection<Restriction> activeRestrictionsBeforeSegment, 213 Collection<Restriction> allRestrictions) { 214 215 Collection<Restriction> result = EMPTY_RESTRICTION_LIST; 216 217 for (Restriction restriction : activeRestrictionsBeforeSegment) { 218 if (restriction.getVias().contains(segment)) { 219 if (result == EMPTY_RESTRICTION_LIST) { 220 result = new ArrayList<Restriction>(allRestrictions.size()); 221 } 222 result.add(restriction); 223 } 224 } 225 226 Collection<Restriction> newRestrictions = 227 getRestrictionsStartedBySegment(allRestrictions, segment); 228 229 if (newRestrictions.size() > 0) { 230 if (result == EMPTY_RESTRICTION_LIST) { 231 result = newRestrictions; 232 } else { 233 result.addAll(newRestrictions); 234 } 235 } 236 237 return result; 238 } 239 240 private static boolean isLegalSegment( 241 Segment segment, Collection<Restriction> activeRestrictions) { 242 243 for (Restriction restriction : activeRestrictions) { 244 if (restriction.getTos().contains(segment)) { 245 return false; 246 } 247 } 248 249 return true; 250 } 251 252 /** returns true iff at least one element is contained in both collections */ 253 protected static boolean shareElement( 254 Collection<?> collection1, Collection<?> collection2) { 255 for (Object element : collection1) { 256 if (collection2.contains(element)) { 257 return true; 258 } 259 } 260 return false; 261 } 262 263 public final void evaluate(Collection<Restriction> restrictions) { 264 265 if (evaluated) { return; } 266 267 evaluateImpl(restrictions); 268 269 evaluated = true; 270 } 271 272 /** 273 * finds in- and outbound segments (if necessary) and segment sequences. 274 * After calling this method, the group must be correctly evaluated 275 * (see {@link #isCorrectlyEvaluated()}). 276 * 277 * @param restrictions restrictions that are used when determining possible connections, 278 * will not be modified; != null 279 */ 280 abstract protected void evaluateImpl(Collection<Restriction> restrictions); 281 282 /** 283 * returns whether a node can be used while finding a segment sequence 284 * @param node node to check; != null 285 */ 286 abstract protected boolean isUsableNode(SegmentNode node); 287 288 /** 289 * returns whether a segment can be used while finding a segment sequence 290 * @param segment segment to check; != null 291 */ 292 abstract protected boolean isUsableSegment(Segment segment); 293 293 294 294 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/GraphEdge.java
r18130 r23189 12 12 public interface GraphEdge { 13 13 14 15 14 /** returns the node this edge starts at; != null */ 15 GraphNode getStartNode(); 16 16 17 18 17 /** returns the node this edge leads to; != null */ 18 GraphNode getTargetNode(); 19 19 20 21 22 23 24 25 20 /** returns all property types for which property values are available */ 21 Collection<GraphEdgePropertyType<?>> getAvailableProperties(); 22 23 /** TODO */ 24 <V> V getPropertyValue(GraphEdgePropertyType<V> property); 25 26 26 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/GraphNode.java
r16520 r23189 13 13 public interface GraphNode { 14 14 15 16 17 18 15 /** 16 * returns all edges that lead to this GraphNode; != null 17 */ 18 public Collection<GraphEdge> getInboundEdges(); 19 19 20 21 22 23 20 /** 21 * returns all edges that start at this GraphNode; != null 22 */ 23 public Collection<GraphEdge> getOutboundEdges(); 24 24 25 26 27 28 29 30 31 25 /** 26 * returns the SegmentNode this GraphNode is based on 27 * 28 * @return SegmentNode, must be one of the nodes of the Segment returned 29 * by {@link #getSegment()}; != null 30 */ 31 public SegmentNode getSegmentNode(); 32 32 33 34 35 36 37 38 33 /** 34 * returns the Segment this GraphNode is based on 35 * 36 * @return Segment; != null 37 */ 38 public Segment getSegment(); 39 39 40 40 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/JunctionEvaluationGroup.java
r18130 r23189 15 15 public class JunctionEvaluationGroup extends EvaluationGroup { 16 16 17 17 private final Set<SegmentNode> segmentNodes; 18 18 19 20 19 protected List<Segment> inboundSegments; 20 protected List<Segment> outboundSegments; 21 21 22 23 24 25 26 27 28 29 22 /** 23 * @param segmentNodes set of SegmentNodes, must not be modified 24 * after being used as constructor parameter; != null 25 */ 26 public JunctionEvaluationGroup(Set<SegmentNode> segmentNodes) { 27 assert segmentNodes != null; 28 this.segmentNodes = segmentNodes; 29 } 30 30 31 32 33 34 35 36 37 38 39 40 31 /** 32 * returns all segments that can be used to enter this group. 33 * {@link #evaluate(Iterable)} needs be called before this method. 34 * 35 * @return segment collection; != null 36 */ 37 public Collection<Segment> getInboundSegments() { 38 if (!evaluated) { throw new IllegalStateException("group not yet evaluated"); } 39 return inboundSegments; 40 } 41 41 42 43 44 45 46 47 48 49 50 51 42 /** 43 * returns all segments that can be used to leave this group. 44 * {@link #evaluate(Iterable)} needs be called before this method. 45 * 46 * @return segment collection; != null 47 */ 48 public Collection<Segment> getOutboundSegments() { 49 if (!evaluated) { throw new IllegalStateException("group not yet evaluated"); } 50 return outboundSegments; 51 } 52 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 53 /** 54 * returns a segment sequence that runs from an inbound to an outbound 55 * segment or null if no connection is possible. 56 * {@link EvaluationGroup#evaluate(Collection)} needs be called before this method. 57 * 58 * @param inboundSegment start of the potential sequence; 59 * must be inbound segment; != null 60 * @param outboundSegment target of the potential sequence; 61 * must be outbound segment; != null 62 * @return sequence of segments or null 63 */ 64 public List<Segment> getSegmentSequence(Segment inboundSegment, Segment outboundSegment) { 65 assert inboundSegment != null && inboundSegments.contains(inboundSegment); 66 assert outboundSegment != null && outboundSegments.contains(outboundSegment); 67 67 68 68 if (!evaluated) { throw new IllegalStateException("group not yet evaluated"); } 69 69 70 71 70 int inboundIndex = inboundSegments.indexOf(inboundSegment); 71 int outboundIndex = outboundSegments.indexOf(outboundSegment); 72 72 73 74 73 return segmentSequences[inboundIndex][outboundIndex]; 74 } 75 75 76 77 76 @Override 77 protected void evaluateImpl(final Collection<Restriction> restrictions) { 78 78 79 79 assert restrictions != null; 80 80 81 82 81 /* find inbound and outbound segments. An inbound segment is a segment whose target 82 * is in the set and whose start node isn't (analogous for outbound segments) */ 83 83 84 85 84 inboundSegments = new ArrayList<Segment>(); 85 outboundSegments = new ArrayList<Segment>(); 86 86 87 88 89 90 91 92 93 94 95 96 97 98 87 for (SegmentNode segmentNode : segmentNodes) { 88 for (Segment segment : segmentNode.getInboundSegments()) { 89 if (!segmentNodes.contains(segment.getNode1())) { 90 inboundSegments.add(segment); 91 } 92 } 93 for (Segment segment : segmentNode.getOutboundSegments()) { 94 if (!segmentNodes.contains(segment.getNode2())) { 95 outboundSegments.add(segment); 96 } 97 } 98 } 99 99 100 100 /* find segment sequences from inbound to outbound segments */ 101 101 102 103 102 @SuppressWarnings("unchecked") //cannot create generic array without cast 103 List<Segment>[][] sequenceArray = new List[inboundSegments.size()][outboundSegments.size()]; 104 104 105 106 105 for (int inboundIndex = 0; inboundIndex < inboundSegments.size(); inboundIndex ++) { 106 for (int outboundIndex = 0; outboundIndex < outboundSegments.size(); outboundIndex ++) { 107 107 108 109 110 108 List<Segment> sequence = 109 findSegmentSequence(inboundSegments.get(inboundIndex), 110 outboundSegments.get(outboundIndex), restrictions); 111 111 112 112 sequenceArray[inboundIndex][outboundIndex] = sequence; 113 113 114 115 114 } 115 } 116 116 117 117 segmentSequences = sequenceArray; 118 118 119 119 } 120 120 121 122 123 124 121 @Override 122 protected boolean isUsableNode(SegmentNode node) { 123 return segmentNodes.contains(node); 124 } 125 125 126 127 128 129 130 126 @Override 127 protected boolean isUsableSegment(Segment segment) { 128 return segmentNodes.contains(segment.getNode1()) 129 && segmentNodes.contains(segment.getNode2()); 130 } 131 131 132 133 134 135 132 @Override 133 public String toString() { 134 return "JunctionEG " + segmentNodes; 135 } 136 136 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/TSBasedWayGraph.java
r18130 r23189 23 23 public class TSBasedWayGraph implements WayGraph, TransitionStructureObserver { 24 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 25 private static final GraphEdgePropertyType<?>[] PROPERTY_TYPES = 26 {GraphEdgeSegments.PROPERTY}; 27 //TODO: -> parameter 28 29 private static class GraphNodeImpl implements GraphNode { 30 private final SegmentNode node; 31 private final Segment segment; 32 private final List<GraphEdge> incomingEdges = new ArrayList<GraphEdge>(); 33 private final List<GraphEdge> outgoingEdges = new ArrayList<GraphEdge>(); 34 public GraphNodeImpl(SegmentNode node, Segment segment) { 35 assert node != null && segment != null; 36 assert segment.getNode1() == node || segment.getNode2() == node; 37 this.node = node; 38 this.segment = segment; 39 } 40 public SegmentNode getSegmentNode() { 41 return node; 42 } 43 public Segment getSegment() { 44 return segment; 45 } 46 public void addIncomingEdge(GraphEdge edge) { 47 assert edge != null; 48 incomingEdges.add(edge); 49 } 50 public Collection<GraphEdge> getInboundEdges() { 51 return incomingEdges; 52 } 53 public void addOutgoingEdge(GraphEdge edge) { 54 assert edge != null; 55 outgoingEdges.add(edge); 56 } 57 public Collection<GraphEdge> getOutboundEdges() { 58 return outgoingEdges; 59 } 60 @Override 61 public String toString() { 62 return "(" + node + "; " + segment + ")"; 63 } 64 } 65 66 private static class GraphEdgeImpl implements GraphEdge { 67 68 private final GraphNode startNode; 69 private final GraphNode targetNode; 70 private final Map<GraphEdgePropertyType<?>, Object> properties; 71 72 public GraphEdgeImpl(GraphNode startNode, GraphNode targetNode, 73 Map<GraphEdgePropertyType<?>, Object> properties) { 74 assert startNode != null && targetNode != null && properties != null; 75 this.startNode = startNode; 76 this.targetNode = targetNode; 77 this.properties = properties; 78 } 79 80 public GraphNode getStartNode() { 81 return startNode; 82 } 83 public GraphNode getTargetNode() { 84 return targetNode; 85 } 86 87 public Collection<GraphEdgePropertyType<?>> getAvailableProperties() { 88 return properties.keySet(); 89 } 90 public <V> V getPropertyValue(GraphEdgePropertyType<V> property) { 91 V result = (V) properties.get(property); 92 return result; 93 } 94 95 @Override 96 public String toString() { 97 return "(" + startNode + "-->" + targetNode + ")"; 98 } 99 100 }; 101 102 private final Set<WayGraphObserver> observers = new HashSet<WayGraphObserver>(); 103 104 private final TransitionStructure transitionStructure; 105 106 private Collection<GraphNode> nodes; 107 private List<GraphEdge> edges; 108 109 /** 110 * create a WayGraph based on a {@link TransitionStructure} 111 * @param transitionStructure transition structure this graph is to be based on; != null 112 */ 113 public TSBasedWayGraph(TransitionStructure transitionStructure) { 114 assert transitionStructure != null; 115 116 this.transitionStructure = transitionStructure; 117 transitionStructure.addObserver(this); 118 119 createNodesAndEdges(); 120 } 121 122 public Collection<GraphEdge> getEdges() { 123 return edges; 124 } 125 126 public Collection<GraphNode> getNodes() { 127 return nodes; 128 } 129 130 private void createNodesAndEdges() { 131 132 Collection<EvaluationGroup> evaluationGroups = 133 createEvaluationGroups(transitionStructure); 134 135 for (EvaluationGroup evaluationGroup : evaluationGroups) { 136 evaluationGroup.evaluate(transitionStructure.getRestrictions()); 137 } 138 139 createNodesAndEdgesFromEvaluationGroups(evaluationGroups); 140 141 evaluationGroups = null; 142 } 143 144 private static Collection<EvaluationGroup> createEvaluationGroups( 145 TransitionStructure transitionStructure) { 146 147 Map<SegmentNode, Set<SegmentNode>> nodeSetMap = 148 new HashMap<SegmentNode, Set<SegmentNode>>(); 149 150 /* first step: everything that is part of the same restriction goes into the same set */ 151 152 for (Restriction restriction : transitionStructure.getRestrictions()) { 153 154 /* group every node in via segments (which includes the 155 * last node of from and the first node of to) into a set */ 156 157 SegmentNode firstNode = restriction.getFrom().getNode2(); 158 createSetIfHasNone(firstNode, nodeSetMap); 159 160 for (Segment segment : restriction.getVias()) { 161 putInSameSet(segment.getNode1(), firstNode, nodeSetMap); 162 putInSameSet(segment.getNode2(), firstNode, nodeSetMap); 163 } 164 165 for (Segment segment : restriction.getTos()) { 166 putInSameSet(segment.getNode1(), firstNode, nodeSetMap); 167 } 168 169 } 170 171 /* second step: create own sets for each junction and end point 172 * (node connected with more than / less than two nodes). */ 173 174 for (SegmentNode node : transitionStructure.getNodes()) { 175 176 if (!nodeSetMap.containsKey(node) 177 && !isConnectedWithExactly2Nodes(node)) { 178 179 createSetIfHasNone(node, nodeSetMap); 180 181 } 182 183 } 184 185 /* third step: create segment sets for all segments that are not in one of the node sets 186 * (that is, at least one node is not part of a junction evaluation group 187 * or the nodes are part of different junction evaluation groups) */ 188 189 Map<Segment, Set<Segment>> segmentSetMap = 190 new HashMap<Segment, Set<Segment>>(); 191 192 for (Segment segment : transitionStructure.getSegments()) { 193 194 SegmentNode node1 = segment.getNode1(); 195 SegmentNode node2 = segment.getNode2(); 196 197 if (!nodeSetMap.containsKey(node1) || !nodeSetMap.containsKey(node2) 198 || nodeSetMap.get(node1) != nodeSetMap.get(node2)) { 199 200 createSetIfHasNone(segment, segmentSetMap); 201 202 for (Segment subsequentSegment : segment.getNode2().getOutboundSegments()) { 203 if (!nodeSetMap.containsKey(node2) 204 || subsequentSegment.getNode2() == node1) { 205 putInSameSet(subsequentSegment, segment, segmentSetMap); 206 } 207 } 208 //note that segments leading to this segment will share sets anyway, 209 //because this segment is a subsequent segment of them 210 211 212 } 213 214 } 215 216 /* create EvaluationGroup objects */ 217 218 Collection<EvaluationGroup> evaluationGroups = 219 new ArrayList<EvaluationGroup>(nodeSetMap.size() + segmentSetMap.size()); 220 221 Set<Set<SegmentNode>> nodeSets = new HashSet<Set<SegmentNode>>(nodeSetMap.values()); 222 for (Set<SegmentNode> nodeSet : nodeSets) { 223 evaluationGroups.add(new JunctionEvaluationGroup(nodeSet)); 224 } 225 226 HashSet<Set<Segment>> hashSets = new HashSet<Set<Segment>>(segmentSetMap.values()); 227 for (Set<Segment> segmentSet : hashSets) { 228 Set<SegmentNode> borderNodes = new HashSet<SegmentNode>(); 229 for (Segment segment : segmentSet) { 230 if (nodeSetMap.containsKey(segment.getNode1())) { 231 borderNodes.add(segment.getNode1()); 232 } 233 if (nodeSetMap.containsKey(segment.getNode2())) { 234 borderNodes.add(segment.getNode2()); 235 } 236 } 237 evaluationGroups.add(new ConnectorEvaluationGroup(segmentSet, borderNodes)); 238 } 239 240 return evaluationGroups; 241 } 242 243 private void createNodesAndEdgesFromEvaluationGroups( 244 Collection<EvaluationGroup> evaluationGroups) { 245 246 nodes = new LinkedList<GraphNode>(); 247 edges = new LinkedList<GraphEdge>(); 248 249 //map from Segments to GraphNodes; 250 //for those GraphNodes representing an "approaching node on segment" state 251 final Map<Segment, GraphNodeImpl> segment2GNMap_approaching = 252 new HashMap<Segment, GraphNodeImpl>(); 253 254 //map from Segments to GraphNodes; 255 //for those GraphNodes representing a "leaving node on segment" state 256 final Map<Segment, GraphNodeImpl> segment2GNMap_leaving = 257 new HashMap<Segment, GraphNodeImpl>(); 258 259 //map from SegmentNodes to GraphNode collections; 260 //for those GraphNodes representing an "approaching node on segment" state 261 final Map<SegmentNode, Collection<GraphNodeImpl>> segNode2GNMap_approaching = 262 new HashMap<SegmentNode, Collection<GraphNodeImpl>>(); 263 264 //map from SegmentNodes to GraphNodes collections; 265 //for those GraphNodes representing a "leaving node on segment" state 266 final Map<SegmentNode, Collection<GraphNodeImpl>> segNode2GNMap_leaving = 267 new HashMap<SegmentNode, Collection<GraphNodeImpl>>(); 268 269 270 271 /* create graph nodes and edges for junction evaluation groups */ 272 273 for (EvaluationGroup evaluationGroup : evaluationGroups) { 274 if (evaluationGroup instanceof JunctionEvaluationGroup) { 275 276 JunctionEvaluationGroup junctionEG = (JunctionEvaluationGroup) evaluationGroup; 277 278 //create graph nodes 279 for (Segment segment : junctionEG.getInboundSegments()) { 280 GraphNodeImpl graphNode = new GraphNodeImpl(segment.getNode2(), segment); 281 nodes.add(graphNode); 282 segment2GNMap_approaching.put(segment, graphNode); 283 addToCollectionMap(segNode2GNMap_approaching, segment.getNode2(), graphNode); 284 } 285 for (Segment segment : junctionEG.getOutboundSegments()) { 286 GraphNodeImpl graphNode = new GraphNodeImpl(segment.getNode1(), segment); 287 nodes.add(graphNode); 288 segment2GNMap_leaving.put(segment, graphNode); 289 addToCollectionMap(segNode2GNMap_leaving, segment.getNode1(), graphNode); 290 } 291 292 //create graph edges for all segment sequences between in- and outbound edges 293 for (Segment inboundSegment : junctionEG.getInboundSegments()) { 294 for (Segment outboundSegment : junctionEG.getOutboundSegments()) { 295 296 List<Segment> segmentSequence = 297 junctionEG.getSegmentSequence(inboundSegment, outboundSegment); 298 299 if (segmentSequence != null) { 300 301 createGraphEdge( 302 segment2GNMap_approaching.get(inboundSegment), 303 segment2GNMap_leaving.get(outboundSegment), 304 segmentSequence, 305 junctionEG); 306 307 } 308 } 309 } 310 311 } 312 } 313 314 /* create graph edges for connector evaluation groups. 315 * Because GraphNodes are created for pairs of SegmentNodes (from connector groups) 316 * and Segments (from junction groups), the GraphNodes already exist. 317 */ 318 319 for (EvaluationGroup evaluationGroup : evaluationGroups) { 320 if (evaluationGroup instanceof ConnectorEvaluationGroup) { 321 322 ConnectorEvaluationGroup connectorEG = (ConnectorEvaluationGroup) evaluationGroup; 323 324 for (SegmentNode startNode : connectorEG.getBorderNodes()) { 325 for (SegmentNode targetNode : connectorEG.getBorderNodes()) { 326 327 if (segNode2GNMap_leaving.containsKey(startNode) 328 && segNode2GNMap_approaching.containsKey(targetNode)) { 329 330 for (GraphNodeImpl startGraphNode : segNode2GNMap_leaving.get(startNode)) { 331 for (GraphNodeImpl targetGraphNode : segNode2GNMap_approaching.get(targetNode)) { 332 333 if (connectorEG.getSegments().contains(startGraphNode.getSegment()) 334 && connectorEG.getSegments().contains(targetGraphNode.getSegment())) { 335 336 List<Segment> segmentSequence = 337 connectorEG.getSegmentSequence(startNode, targetNode); 338 339 if (segmentSequence != null) { 340 createGraphEdge( 341 startGraphNode, 342 targetGraphNode, 343 segmentSequence, 344 connectorEG); 345 } 346 347 } 348 349 } 350 } 351 352 } 353 354 } 355 } 356 357 } 358 } 359 360 } 361 362 private void createGraphEdge( 363 GraphNodeImpl startNode, GraphNodeImpl targetNode, 364 List<Segment> segments, ConnectorEvaluationGroup evaluationGroup) { 365 366 Map<GraphEdgePropertyType<?>, Object> properties = 367 new HashMap<GraphEdgePropertyType<?>, Object>(); //TODO: replace HashMap with List-based solution 368 369 for (GraphEdgePropertyType<?> propertyType : PROPERTY_TYPES) { 370 Object value = propertyType.evaluate(evaluationGroup, segments, transitionStructure); 371 properties.put(propertyType, value); 372 } 373 374 createGraphEdge(startNode, targetNode, properties); 375 376 } 377 378 private void createGraphEdge( 379 GraphNodeImpl startNode, GraphNodeImpl targetNode, 380 List<Segment> segments, JunctionEvaluationGroup evaluationGroup) { 381 382 Map<GraphEdgePropertyType<?>, Object> properties = 383 new HashMap<GraphEdgePropertyType<?>, Object>(); //TODO: replace HashMap with List-based solution 384 385 for (GraphEdgePropertyType<?> propertyType : PROPERTY_TYPES) { 386 Object value = propertyType.evaluate(evaluationGroup, segments, transitionStructure); 387 properties.put(propertyType, value); 388 } 389 390 createGraphEdge(startNode, targetNode, properties); 391 392 } 393 394 /** 395 * creates a GraphEdge; 396 * adds it to its nodes' collections and {@link #edges} collection. 397 */ 398 private void createGraphEdge(GraphNodeImpl startNode, GraphNodeImpl targetNode, 399 Map<GraphEdgePropertyType<?>, Object> properties) { 400 401 GraphEdge newEdge = new GraphEdgeImpl(startNode, targetNode, properties); 402 403 startNode.addOutgoingEdge(newEdge); 404 targetNode.addIncomingEdge(newEdge); 405 406 edges.add(newEdge); 407 408 } 409 410 private static boolean isConnectedWithExactly2Nodes(SegmentNode node) { 411 412 Set<SegmentNode> connectedNodes = new HashSet<SegmentNode>(2); 413 414 for (Segment segment : node.getInboundSegments()) { 415 connectedNodes.add(segment.getNode1()); 416 } 417 for (Segment segment : node.getOutboundSegments()) { 418 connectedNodes.add(segment.getNode2()); 419 } 420 421 return connectedNodes.size() == 2; 422 } 423 424 /** 425 * creates a set for an object if none exists in a map. 426 * The set will contain the object and be added to the map with the object being its key. 427 */ 428 private static <T> void createSetIfHasNone(T object, Map<T, Set<T>> objectSetMap) { 429 430 if (!objectSetMap.containsKey(object)) { 431 @SuppressWarnings("unchecked") //no set with generic parameter can be created directly 432 Set<T> set = new HashSet(); 433 set.add(object); 434 objectSetMap.put(object, set); 435 } 436 437 } 438 439 /** 440 * puts an object in another object's set. 441 * If both nodes have sets already, these sets are merged. 442 * The objectSetMap is modified accordingly. 443 * 444 * @param object object that might or might not be in a set; != null 445 * @param objectInSet object that is guaranteed to be in a set; != null 446 * @param objectSetMap map from objects to the one set they are part of; != null 447 */ 448 private static <T> void putInSameSet(T object, T objectInSet, Map<T, Set<T>> objectSetMap) { 449 assert object != null && objectInSet != null && objectSetMap != null; 450 assert objectSetMap.containsKey(objectInSet); 451 452 Set<T> set = objectSetMap.get(objectInSet); 453 454 if (objectSetMap.containsKey(object)) { 455 456 /* merge the two sets */ 457 Set<T> oldSet = objectSetMap.get(object); 458 for (T objectFromOldSet : oldSet) { 459 set.add(objectFromOldSet); 460 objectSetMap.put(objectFromOldSet, set); 461 } 462 463 } else { 464 465 /* add object to objectInSet's set */ 466 set.add(object); 467 objectSetMap.put(object, set); 468 469 } 470 471 } 472 473 private static <K, E> void addToCollectionMap(final Map<K, Collection<E>> map, K key, E entry) { 474 if (!map.containsKey(key)) { 475 Collection<E> newCollection = new ArrayList<E>(); 476 map.put(key, newCollection); 477 } 478 map.get(key).add(entry); 479 } 480 481 public void update(TransitionStructure transitionStructure) { 482 createNodesAndEdges(); 483 notifyObservers(); 484 } 485 486 public void addObserver(WayGraphObserver observer) { 487 observers.add(observer); 488 } 489 490 public void deleteObserver(WayGraphObserver observer) { 491 observers.remove(observer); 492 } 493 494 private void notifyObservers() { 495 for (WayGraphObserver observer : observers) { 496 observer.update(this); 497 } 498 } 499 499 500 500 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/WayGraph.java
r16520 r23189 8 8 public interface WayGraph { 9 9 10 11 10 Collection<GraphNode> getNodes(); 11 Collection<GraphEdge> getEdges(); 12 12 13 14 15 16 17 18 19 13 /** 14 * adds an observer. 15 * Does nothing if the parameter is already an observer of this WayGraph. 16 * 17 * @param observer observer object, != null 18 */ 19 public void addObserver(WayGraphObserver observer); 20 20 21 22 23 24 25 26 27 21 /** 22 * deletes an observer that has been added using {@link #addObserver(WayGraphObserver)}. 23 * Does nothing if the parameter isn't currently an observer of this WayGraph. 24 * 25 * @param observer observer object, != null 26 */ 27 public void deleteObserver(WayGraphObserver observer); 28 28 29 29 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/graph/WayGraphObserver.java
r16520 r23189 7 7 public interface WayGraphObserver { 8 8 9 10 11 12 13 9 /** 10 * informs this observer about changes in an observed graph 11 * @param wayGraph observed graph that has changed; != null 12 */ 13 public void update(WayGraph wayGraph); 14 14 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/GraphEdgePropertyType.java
r18130 r23189 17 17 */ 18 18 public interface GraphEdgePropertyType<V> { 19 20 /**21 * determines the property value for segments created from junction groups22 */23 public V evaluate(JunctionEvaluationGroup junctionGroup,24 List<Segment> segmentSequence,25 TransitionStructure transitionStructure);26 19 27 /** 28 * determines the property value for segments created from connector groups 29 */ 30 public V evaluate(ConnectorEvaluationGroup connectorGroup, 31 List<Segment> segmentSequence, 32 TransitionStructure transitionStructure); 33 20 /** 21 * determines the property value for segments created from junction groups 22 */ 23 public V evaluate(JunctionEvaluationGroup junctionGroup, 24 List<Segment> segmentSequence, 25 TransitionStructure transitionStructure); 26 27 /** 28 * determines the property value for segments created from connector groups 29 */ 30 public V evaluate(ConnectorEvaluationGroup connectorGroup, 31 List<Segment> segmentSequence, 32 TransitionStructure transitionStructure); 33 34 34 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/GraphEdgeSegments.java
r18130 r23189 12 12 * property for the graph that is being constructed will preserve information 13 13 * from the {@link TransitionStructure}. 14 * 14 * 15 15 * TODO: for some purposes, segments are not needed (only coordinate lists; 16 16 * without properties etc.) 17 17 */ 18 18 public final class GraphEdgeSegments implements GraphEdgePropertyType<List<Segment>> { 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 19 20 public static final GraphEdgeSegments PROPERTY = new GraphEdgeSegments(); 21 22 /** 23 * private constructor to make sure that {@link #INSTANCE} is the only instance 24 */ 25 private GraphEdgeSegments() { } 26 27 public List<Segment> evaluate(JunctionEvaluationGroup junctionGroup, 28 List<Segment> segmentSequence, TransitionStructure transitionStructure) { 29 return segmentSequence; 30 } 31 32 public List<Segment> evaluate(ConnectorEvaluationGroup connectorGroup, 33 List<Segment> segmentSequence, TransitionStructure transitionStructure) { 34 return segmentSequence; 35 } 36 37 37 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadIncline.java
r19216 r23189 8 8 public class RoadIncline implements RoadPropertyType<Float> { 9 9 10 11 12 13 10 public <N, W, R, M> Float evaluateN(N node, AccessParameters accessParameters, 11 DataSource<N,W,R,M> dataSource) { 12 return null; 13 }; 14 14 15 16 17 15 public <N, W, R, M> Float evaluateW(W way, boolean forward, AccessParameters accessParameters, 16 DataSource<N,W,R,M> dataSource) { 17 assert way != null && accessParameters != null && dataSource != null; 18 18 19 20 19 TagGroup tags = dataSource.getTagsW(way); 20 String inclineString = tags.getValue("incline"); 21 21 22 23 24 25 26 27 28 29 30 22 if (inclineString != null) { 23 Float incline = ValueStringParser.parseIncline(inclineString); 24 if (incline != null) { 25 if (!forward) { 26 incline = -incline; 27 } 28 return incline; 29 } 30 } 31 31 32 33 32 return null; 33 }; 34 34 35 36 35 public boolean isUsable(Object propertyValue, AccessParameters accessParameters) { 36 assert propertyValue instanceof Float; 37 37 38 38 float incline = (Float)propertyValue; 39 39 40 41 42 43 40 Float maxInclineUp = 41 accessParameters.getVehiclePropertyValue(VehiclePropertyTypes.MAX_INCLINE_UP); 42 Float maxInclineDown = 43 accessParameters.getVehiclePropertyValue(VehiclePropertyTypes.MAX_INCLINE_DOWN); 44 44 45 46 47 48 49 50 51 52 45 if (maxInclineUp != null && incline > maxInclineUp) { 46 return false; 47 } else if (maxInclineDown != null && -incline > maxInclineDown) { 48 return false; 49 } else { 50 return true; 51 } 52 } 53 53 54 54 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxaxleload.java
r20243 r23189 6 6 7 7 public class RoadMaxaxleload extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMaxaxleload() { 9 super("maxaxleload", AXLELOAD, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseWeight(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxheight.java
r20243 r23189 6 6 7 7 public class RoadMaxheight extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMaxheight() { 9 super("maxheight", HEIGHT, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseMeasure(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxlength.java
r20243 r23189 6 6 7 7 public class RoadMaxlength extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMaxlength() { 9 super("maxlength", LENGTH, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseMeasure(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxspeed.java
r19216 r23189 8 8 public class RoadMaxspeed implements RoadPropertyType<Float> { 9 9 10 10 private DataSource<?, ?, ?, ?> lastDataSource; 11 11 12 13 14 15 16 12 /** 13 * (re)creates information like boundaries if data source has changed 14 * since last call to {@link #evaluate(Object, boolean, AccessParameters, DataSource)} 15 */ 16 private <N, W, R, M> void initializeIfNecessary(DataSource<N, W, R, M> dataSource) { 17 17 18 18 if (dataSource != lastDataSource) { 19 19 20 21 22 23 24 25 26 20 /* 21 * 22 * currently no activities; 23 * place boundaries or similar features can be handled here 24 * once there is consensus on the topic of implicit maxspeeds, trafficzones etc. 25 * 26 */ 27 27 28 29 30 28 lastDataSource = dataSource; 29 } 30 } 31 31 32 33 34 32 public <N, W, R, M> Float evaluateN(N node, AccessParameters accessParameters, 33 DataSource<N, W, R, M> dataSource) { 34 assert node != null && accessParameters != null && dataSource != null; 35 35 36 36 initializeIfNecessary(dataSource); 37 37 38 39 38 return evaluateTags(dataSource.getTagsN(node)); 39 } 40 40 41 42 43 41 public <N, W, R, M> Float evaluateW(W way, boolean forward, AccessParameters accessParameters, 42 DataSource<N, W, R, M> dataSource) { 43 assert way != null && accessParameters != null && dataSource != null; 44 44 45 45 initializeIfNecessary(dataSource); 46 46 47 48 47 return evaluateTags(dataSource.getTagsW(way)); 48 } 49 49 50 51 50 private Float evaluateTags(TagGroup tags) { 51 String maxspeedString = tags.getValue("maxspeed"); 52 52 53 53 if (maxspeedString != null) { 54 54 55 56 57 58 55 Float maxspeed = ValueStringParser.parseSpeed(maxspeedString); 56 if (maxspeed != null) { 57 return maxspeed; 58 } 59 59 60 60 } 61 61 62 63 62 return null; 63 } 64 64 65 66 67 68 65 public boolean isUsable(Object propertyValue, AccessParameters accessParameters) { 66 assert propertyValue instanceof Float; 67 return true; 68 } 69 69 70 70 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxweight.java
r20243 r23189 6 6 7 7 public class RoadMaxweight extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMaxweight() { 9 super("maxweight", WEIGHT, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseWeight(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxwidth.java
r20243 r23189 6 6 7 7 public class RoadMaxwidth extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMaxwidth() { 9 super("maxwidth", WIDTH, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseMeasure(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadMinspeed.java
r20243 r23189 6 6 7 7 public class RoadMinspeed extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadMinspeed() { 9 super("minspeed", SPEED, LimitType.MINIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseSpeed(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadPropertyType.java
r19216 r23189 14 14 public interface RoadPropertyType<V> { 15 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 16 /** 17 * determines the property value for way-based segments. 18 * Uses the way the segment is created from. 19 * 20 * @param way way that is to be evaluated; != null 21 * @param forward chooses whether the property is evaluated 22 * in (true) or against (false) way direction 23 * @param accessParameters access parameters for properties that depend on vehicle/situation 24 * @param dataSource object providing access to all data; != null 25 * @return value of this property for the way; 26 * null if property cannot be determined / does not apply 27 */ 28 public <N, W, R, M> V evaluateW(W way, boolean forward, 29 AccessParameters accessParameters, DataSource<N, W, R, M> dataSource); 30 30 31 32 33 34 35 36 37 38 39 40 41 42 31 /** 32 * determines the property value for node-based segments. 33 * Uses the node the segment is created from. 34 * 35 * @param way node that is to be evaluated; != null 36 * @param accessParameters access parameters for properties that depend on vehicle/situation 37 * @param dataSource object providing access to all data; != null 38 * @return value of this property for the way; 39 * null if property cannot be determined / does not apply 40 */ 41 public <N, W, R, M> V evaluateN(N node, 42 AccessParameters accessParameters, DataSource<N, W, R, M> dataSource); 43 43 44 45 46 47 48 49 50 51 44 /** 45 * checks whether a segment with a given value for this property can be used by a vehicle 46 * with a certain set of access parameters 47 * 48 * @param object value of this property for the segment; 49 * MUST be of type V; != null 50 */ 51 public boolean isUsable(Object object, AccessParameters accessParameters); 52 52 53 53 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadSurface.java
r19216 r23189 9 9 public class RoadSurface implements RoadPropertyType<String> { 10 10 11 12 13 14 11 public <N, W, R, M> String evaluateN(N node, AccessParameters accessParameters, 12 DataSource<N,W,R,M> dataSource) { 13 return null; 14 }; 15 15 16 17 18 16 public <N, W, R, M> String evaluateW(W way, boolean forward, AccessParameters accessParameters, 17 DataSource<N,W,R,M> dataSource) { 18 assert way != null && accessParameters != null && dataSource != null; 19 19 20 21 20 TagGroup tags = dataSource.getTagsW(way); 21 return tags.getValue("surface"); 22 22 23 23 }; 24 24 25 26 25 public boolean isUsable(Object propertyValue, AccessParameters accessParameters) { 26 assert propertyValue instanceof String; 27 27 28 28 String surface = (String)propertyValue; 29 29 30 31 30 Collection<String> surfaceBlacklist = 31 accessParameters.getVehiclePropertyValue(VehiclePropertyTypes.SURFACE_BLACKLIST); 32 32 33 34 35 36 37 38 33 if (surfaceBlacklist != null && surfaceBlacklist.contains(surface)) { 34 return false; 35 } else { 36 return true; 37 } 38 } 39 39 40 40 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadTracktype.java
r19216 r23189 7 7 public class RoadTracktype implements RoadPropertyType<Integer> { 8 8 9 10 11 12 9 public <N, W, R, M> Integer evaluateN(N node, AccessParameters accessParameters, 10 DataSource<N,W,R,M> dataSource) { 11 return null; 12 }; 13 13 14 15 16 14 public <N, W, R, M> Integer evaluateW(W way, boolean forward, AccessParameters accessParameters, 15 DataSource<N,W,R,M> dataSource) { 16 assert way != null && accessParameters != null && dataSource != null; 17 17 18 19 18 TagGroup tags = dataSource.getTagsW(way); 19 String tracktypeString = tags.getValue("tracktype"); 20 20 21 22 23 24 25 26 27 28 29 30 31 32 33 21 if (tracktypeString != null) { 22 if ("grade1".equals(tracktypeString)) { 23 return 1; 24 } else if ("grade2".equals(tracktypeString)) { 25 return 2; 26 } else if ("grade3".equals(tracktypeString)) { 27 return 3; 28 } else if ("grade4".equals(tracktypeString)) { 29 return 4; 30 } else if ("grade5".equals(tracktypeString)) { 31 return 5; 32 } 33 } 34 34 35 36 35 return null; 36 }; 37 37 38 39 38 public boolean isUsable(Object propertyValue, AccessParameters accessParameters) { 39 assert propertyValue instanceof Integer; 40 40 41 41 int tracktype = (Integer)propertyValue; 42 42 43 44 43 Integer maxTracktype = 44 accessParameters.getVehiclePropertyValue(VehiclePropertyTypes.MAX_TRACKTYPE); 45 45 46 47 48 49 50 51 46 if (maxTracktype != null && tracktype > maxTracktype) { 47 return false; 48 } else { 49 return true; 50 } 51 } 52 52 53 53 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadValueLimit.java
r20243 r23189 11 11 abstract public class RoadValueLimit implements RoadPropertyType<Float> { 12 12 13 13 protected static enum LimitType {MINIMUM, MAXIMUM}; 14 14 15 16 15 private final String keyName; 16 private final VehiclePropertyType<Float> vehicleProperty; 17 17 18 18 private final LimitType upperLimit; 19 19 20 21 22 23 24 25 26 27 28 29 20 /** 21 * @param keyName key that is used to add this property to a way; value must be in 22 * format readable by {@link ValueStringParser#parseOsmDecimal(String)}; 23 * != null 24 * @param vehicleProperty vehicle property that is limited by this road property; != null 25 * @param upperLimit type of limit; != null 26 */ 27 protected RoadValueLimit(String keyName, VehiclePropertyType<Float> vehicleProperty, 28 LimitType upperLimit) { 29 assert keyName != null && vehicleProperty != null && upperLimit != null; 30 30 31 32 33 34 31 this.keyName = keyName; 32 this.vehicleProperty = vehicleProperty; 33 this.upperLimit = upperLimit; 34 } 35 35 36 36 protected abstract Float parse(String valueString); 37 37 38 39 40 41 42 38 public <N, W, R, M> Float evaluateW(W way, boolean forward, 39 AccessParameters accessParameters, DataSource<N, W, R, M> dataSource) { 40 assert way != null && accessParameters != null && dataSource != null; 41 return evaluateTags(dataSource.getTagsW(way)); 42 } 43 43 44 45 46 47 48 44 public <N, W, R, M> Float evaluateN(N node, 45 AccessParameters accessParameters, DataSource<N, W, R, M> dataSource) { 46 assert node != null && accessParameters != null && dataSource != null; 47 return evaluateTags(dataSource.getTagsN(node)); 48 } 49 49 50 51 52 53 54 55 56 57 58 50 private final Float evaluateTags(TagGroup tags) { 51 String valueString = tags.getValue(keyName); 52 if (valueString != null) { 53 Float value = parse(valueString); 54 return value; 55 } else { 56 return null; 57 } 58 } 59 59 60 61 60 public boolean isUsable(Object propertyValue, AccessParameters accessParameters) { 61 assert propertyValue instanceof Float; 62 62 63 63 Float vehicleValue = accessParameters.getVehiclePropertyValue(vehicleProperty); 64 64 65 66 67 68 69 70 71 72 73 74 65 if (vehicleValue != null) { 66 switch(upperLimit) { 67 case MINIMUM: return vehicleValue >= (Float) propertyValue; 68 case MAXIMUM: return vehicleValue <= (Float) propertyValue; 69 default: throw new Error("unhandled LimitType"); 70 } 71 } else { 72 return true; 73 } 74 } 75 75 76 76 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/RoadWidth.java
r20243 r23189 6 6 7 7 public class RoadWidth extends RoadValueLimit { 8 9 10 11 12 13 14 8 public RoadWidth() { 9 super("width", WIDTH, LimitType.MAXIMUM); 10 } 11 @Override 12 protected Float parse(String valueString) { 13 return ValueStringParser.parseMeasure(valueString); 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/VehiclePropertyType.java
r16520 r23189 11 11 public interface VehiclePropertyType<V> { 12 12 13 14 15 16 17 13 /** 14 * determines whether a value is valid. 15 * null is never a valid value and must not be used as parameter. 16 */ 17 public boolean isValidValue(Object value); 18 18 19 19 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/property/VehiclePropertyTypes.java
r16520 r23189 9 9 public final class VehiclePropertyTypes { 10 10 11 12 11 /** prevents instantiation */ 12 private VehiclePropertyTypes() { } 13 13 14 15 16 17 18 14 private static final class NonnegativeFloatProperty implements VehiclePropertyType<Float> { 15 public boolean isValidValue(Object value) { 16 return value instanceof Float && (Float)value >= 0; 17 } 18 } 19 19 20 21 20 /** length of a vehicle in meters; negative values are invalid */ 21 public static final VehiclePropertyType<Float> LENGTH = new NonnegativeFloatProperty(); 22 22 23 24 23 /** width of a vehicle in meters; negative values are invalid */ 24 public static final VehiclePropertyType<Float> WIDTH = new NonnegativeFloatProperty(); 25 25 26 27 26 /** height of a vehicle in meters; negative values are invalid */ 27 public static final VehiclePropertyType<Float> HEIGHT = new NonnegativeFloatProperty(); 28 28 29 30 29 /** weight of a vehicle in tons; negative values are invalid */ 30 public static final VehiclePropertyType<Float> WEIGHT = new NonnegativeFloatProperty(); 31 31 32 33 32 /** axleload of a vehicle in tons; negative values are invalid */ 33 public static final VehiclePropertyType<Float> AXLELOAD = new NonnegativeFloatProperty(); 34 34 35 36 35 /** speed a vehicle can reach in km/h; negative values are invalid */ 36 public static final VehiclePropertyType<Float> SPEED = new NonnegativeFloatProperty(); 37 37 38 39 38 /** maximum incline a vehicle can go up; negative values are invalid */ 39 public static final VehiclePropertyType<Float> MAX_INCLINE_UP = new NonnegativeFloatProperty(); 40 40 41 42 41 /** maximum incline a vehicle can go down; negative values are invalid */ 42 public static final VehiclePropertyType<Float> MAX_INCLINE_DOWN = new NonnegativeFloatProperty(); 43 43 44 45 46 44 /** surface types ("surface" key values) the vehicle cannot use */ 45 public static final VehiclePropertyType<Collection<String>> SURFACE_BLACKLIST = new VehiclePropertyType<Collection<String>>() { 46 public boolean isValidValue(Object value) { 47 47 48 49 50 48 if (!(value instanceof Collection)) { 49 return false; 50 } 51 51 52 53 54 55 56 52 for (Object contentObject : (Collection<?>)value) { 53 if (!(contentObject instanceof String)) { 54 return false; 55 } 56 } 57 57 58 59 60 58 return true; 59 } 60 }; 61 61 62 63 64 65 66 67 68 69 70 71 62 /** 63 * maximum tracktype grade the vehicle can use; 64 * values are integers from = to 5 65 * (values of key "tracktype" without "grade_" prefix, 0 is for "none") 66 */ 67 public static final VehiclePropertyType<Integer> MAX_TRACKTYPE = new VehiclePropertyType<Integer>() { 68 public boolean isValidValue(Object value) { 69 return value instanceof Integer && (Integer)value >= 0 && (Integer)value <= 5; 70 } 71 }; 72 72 73 73 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/GenericTransitionStructure.java
r19216 r23189 30 30 public class GenericTransitionStructure<N, W, R, M> implements TransitionStructure, DataSourceObserver { 31 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 32 private static final Collection<Segment> EMPTY_SEGMENT_LIST = 33 Collections.unmodifiableList(new ArrayList<Segment>(0)); 34 private static final Collection<Restriction> EMPTY_RESTRICTION_COLLECTION = 35 new ArrayList<Restriction>(0); 36 37 private static class SegmentNodeImpl implements SegmentNode { 38 private final double lat; 39 private final double lon; 40 private final List<Segment> inboundSegments = new LinkedList<Segment>(); 41 private final List<Segment> outboundSegments = new LinkedList<Segment>(); 42 private final Map<RoadPropertyType<?>, Object> properties; 43 public SegmentNodeImpl(double lat, double lon, Map<RoadPropertyType<?>, Object> properties) { 44 assert properties != null; 45 this.lat = lat; 46 this.lon = lon; 47 this.properties = properties; 48 } 49 public double getLat() { 50 return lat; 51 } 52 public double getLon() { 53 return lon; 54 } 55 public void addInboundSegment(Segment segment) { 56 inboundSegments.add(segment); 57 } 58 public void addOutboundSegment(Segment segment) { 59 outboundSegments.add(segment); 60 } 61 public Collection<Segment> getOutboundSegments() { 62 return outboundSegments; 63 } 64 public Collection<Segment> getInboundSegments() { 65 return inboundSegments; 66 } 67 68 public <P> void setProperty(RoadPropertyType<P> property, P value) { 69 properties.put(property, value); 70 } 71 public Collection<RoadPropertyType<?>> getAvailableProperties() { 72 return properties.keySet(); 73 } 74 public <P> P getPropertyValue(RoadPropertyType<P> property) { 75 @SuppressWarnings("unchecked") //cast is safe due to type parameter of setProperty 76 P result = (P) properties.get(property); 77 return result; 78 } 79 public Map<RoadPropertyType<?>, Object> getProperties() { 80 return properties; 81 } 82 83 @Override 84 public String toString() { 85 return "(" + lat + ", " + lon + ")"; 86 } 87 } 88 89 private static class SegmentImpl implements Segment { 90 private final SegmentNode node1; 91 private final SegmentNode node2; 92 private final Map<RoadPropertyType<?>, Object> properties; 93 public SegmentImpl(SegmentNode node1, SegmentNode node2, Map<RoadPropertyType<?>, Object> properties) { 94 this.node1 = node1; 95 this.node2 = node2; 96 this.properties = properties; 97 } 98 public SegmentNode getNode1() { 99 return node1; 100 } 101 public SegmentNode getNode2() { 102 return node2; 103 } 104 public <P> void setProperty(RoadPropertyType<P> property, P value) { 105 properties.put(property, value); 106 } 107 public Collection<RoadPropertyType<?>> getAvailableProperties() { 108 return properties.keySet(); 109 } 110 public <P> P getPropertyValue(RoadPropertyType<P> property) { 111 @SuppressWarnings("unchecked") //cast is safe due to type parameter of setProperty 112 P result = (P) properties.get(property); 113 return result; 114 } 115 116 @Override 117 public String toString() { 118 return "(" + node1 + "->" + node2 + ")"; 119 } 120 } 121 122 private static class RestrictionImpl implements Restriction { 123 private final Segment from; 124 private final Collection<Segment> vias; 125 private final Collection<Segment> tos; 126 127 /** constructor, will directly use collection references, collections must not be changed after usage as constructor param */ 128 public RestrictionImpl(Segment from, Collection<Segment> vias, Collection<Segment> tos) { 129 this.from = from; 130 this.vias = Collections.unmodifiableCollection(vias); 131 this.tos = Collections.unmodifiableCollection(tos); 132 } 133 134 public Segment getFrom() { 135 return from; 136 } 137 public Collection<Segment> getVias() { 138 return vias; 139 } 140 public Collection<Segment> getTos() { 141 return tos; 142 } 143 144 @Override 145 public String toString() { 146 return from + " -> " + vias + " -> " + tos; 147 } 148 } 149 150 private final Set<TransitionStructureObserver> observers = new HashSet<TransitionStructureObserver>(); 151 152 private final Collection<RoadPropertyType<?>> properties; 153 154 private final DataSource<N, W, R, M> dataSource; 155 156 private AccessParameters accessParameters; 157 private AccessRuleset ruleset; 158 159 private AccessEvaluator<N, W> accessEvaluator; 160 161 private Collection<SegmentNode> nodes = null; 162 private Collection<Segment> segments = new LinkedList<Segment>(); 163 private Collection<Restriction> restrictions = new LinkedList<Restriction>(); 164 165 public GenericTransitionStructure( 166 AccessParameters accessParameters, AccessRuleset ruleset, 167 DataSource<N, W, R, M> dataSource, 168 Collection<RoadPropertyType<?>> properties) { 169 170 assert accessParameters != null && ruleset != null; 171 assert dataSource != null; 172 assert properties != null; 173 174 this.dataSource = dataSource; 175 176 this.properties = properties; 177 178 setAccessParametersAndRuleset(accessParameters, ruleset); 179 180 dataSource.addObserver(this); 181 } 182 183 /** 184 * sets new access parameters and/or a new ruleset. 185 * Causes a data update if at least one is actually changed. 186 * 187 * @param accessParameters new access parameters, null indicates no change 188 * @param ruleset new ruleset, null indicates no change 189 */ 190 public void setAccessParametersAndRuleset(AccessParameters accessParameters, AccessRuleset ruleset) { 191 192 if (accessParameters != null) { 193 this.accessParameters = accessParameters; 194 } 195 if (ruleset != null) { 196 this.ruleset = ruleset; 197 } 198 199 if (accessParameters != null || ruleset != null) { 200 201 assert dataSource != null; 202 203 accessEvaluator = new RulesetAccessEvaluator<N, W, R, M>( 204 dataSource, 205 this.ruleset, 206 this.accessParameters); 207 208 updateData(); 209 notifyObservers(); 210 211 } 212 213 } 214 215 public Collection<SegmentNode> getNodes() { 216 return nodes; 217 } 218 219 public Collection<Segment> getSegments() { 220 return segments; 221 } 222 223 public Collection<Restriction> getRestrictions() { 224 return restrictions; 225 } 226 227 /** 228 * creates nodes, segments and restrictions based on the data source 229 */ 230 protected void updateData() { 231 232 ArrayList<SegmentNode> nodes = new ArrayList<SegmentNode>(); 233 ArrayList<Segment> segments = new ArrayList<Segment>(); 234 235 Map<N, SegmentNodeImpl> nodeCreationMap = new HashMap<N, SegmentNodeImpl>(); 236 Map<W, List<Segment>> waySegmentMap = new HashMap<W, List<Segment>>(); 237 238 /* create segments (nodes are created only when included in a segment) */ 239 240 for (W way : dataSource.getWays()) { 241 createSegmentsAndSegmentNodes(way, accessEvaluator, nodes, segments, nodeCreationMap, waySegmentMap); 242 } 243 244 nodes.trimToSize(); 245 segments.trimToSize(); 246 247 /* create restrictions */ 248 249 Collection<Restriction> restrictions = 250 createRestrictionsFromTurnRestrictions(dataSource.getRelations(), nodeCreationMap, waySegmentMap); 251 252 restrictions.addAll(createRestrictionsFromBarrierNodes(nodeCreationMap, waySegmentMap)); 253 254 /* keep data and inform observers */ 255 256 this.nodes = nodes; 257 this.segments = segments; 258 this.restrictions = restrictions; 259 260 notifyObservers(); 261 262 } 263 264 /** 265 * creates all Segments and SegmentNodes for a way 266 * 267 * @param way way to create Segments and SegmentNodes from; != null 268 * @param wayAccessEvaluator evaluator object that decides whether way is usable; != null 269 * @param nodes collection of SegmentNodes, new SegmentNodes will be added here; != null 270 * @param segments collection of Segments, new Segments will be added here; != null 271 * @param nodeCreationMap map providing the SegmentNode that has been created from a Node, 272 * if new SegmentNodes are created, they will be added appropriately; != null 273 * @param waySegmentMap map providing the Segments that have been created from a Way, 274 * if new Segments are created, they will be added appropriately; != null 275 */ 276 private void createSegmentsAndSegmentNodes(W way, AccessEvaluator<N, W> wayAccessEvaluator, 277 Collection<SegmentNode> nodes, Collection<Segment> segments, 278 Map<N, SegmentNodeImpl> nodeCreationMap, Map<W, List<Segment>> waySegmentMap) { 279 280 assert way != null && wayAccessEvaluator != null && nodes != null && segments != null && nodeCreationMap != null && waySegmentMap != null; 281 282 /* calculate property values */ 283 284 Map<RoadPropertyType<?>, Object> forwardPropertyValues = getWayPropertyMap(way, true); 285 Map<RoadPropertyType<?>, Object> backwardPropertyValues = getWayPropertyMap(way, false); 286 287 /* create segments from the way if it can be accessed and isn't incomplete or deleted */ 288 289 boolean forwardAccess = wayAccessEvaluator.wayUsable(way, true, forwardPropertyValues); 290 boolean backwardAccess = wayAccessEvaluator.wayUsable(way, false, backwardPropertyValues); 291 292 if (forwardAccess || backwardAccess) { 293 294 if (!waySegmentMap.containsKey(way)) { 295 waySegmentMap.put(way, new LinkedList<Segment>()); 296 } 297 298 /* create segments from all pairs of subsequent nodes */ 299 300 N previousNode = null; 301 for (N node : dataSource.getNodes(way)) { 302 if (previousNode != null) { 303 304 SegmentNodeImpl node1 = 305 getOrCreateSegmentNodeForNode(previousNode, nodes, nodeCreationMap); 306 SegmentNodeImpl node2 = 307 getOrCreateSegmentNodeForNode(node, nodes, nodeCreationMap); 308 309 if (forwardAccess) { 310 SegmentImpl segment = new SegmentImpl(node1, node2, forwardPropertyValues); 311 segments.add(segment); 312 waySegmentMap.get(way).add(segment); 313 node1.addOutboundSegment(segment); 314 node2.addInboundSegment(segment); 315 } 316 if (backwardAccess) { //no "else if" because both can be valid 317 SegmentImpl segment = new SegmentImpl(node2, node1, backwardPropertyValues); 318 segments.add(segment); 319 waySegmentMap.get(way).add(segment); 320 node1.addInboundSegment(segment); 321 node2.addOutboundSegment(segment); 322 } 323 324 } 325 previousNode = node; 326 } 327 328 } 329 } 330 331 /** 332 * if no segment node for a node exists in the nodeCreationMap, 333 * creates a segment node for it and adds it to the nodeCreationMap and the nodes collection 334 * and returns it; otherwise returns the existing segment node. 335 */ 336 private SegmentNodeImpl getOrCreateSegmentNodeForNode(N node, 337 Collection<SegmentNode> nodes, Map<N, SegmentNodeImpl> nodeCreationMap) { 338 339 SegmentNodeImpl segmentNode = nodeCreationMap.get(node); 340 341 if (segmentNode == null) { 342 343 Map<RoadPropertyType<?>, Object> nodePropertyValues = getNodePropertyMap(node); 344 segmentNode = new SegmentNodeImpl(dataSource.getLat(node), dataSource.getLon(node), 345 nodePropertyValues); 346 347 nodeCreationMap.put(node, segmentNode); 348 nodes.add(segmentNode); 349 350 } 351 352 return segmentNode; 353 } 354 355 /** 356 * creates all Restrictions from a collection of Relations. 357 * Only "type=restriction" relations are relevant for restrictions. 358 * 359 * @param relations Relations to create Restrictions from. 360 * They can have any type key, as filtering is done inside this method. 361 * @param nodeCreationMap map providing the SegmentNode that has been created from a Node, 362 * will not be modified; != null 363 * @param waySegmentMap map providing the Segments that have been created from a Way, 364 * will not be modified; != null 365 * @return Restrictions created from the Relations; != null, but may be empty 366 */ 367 private Collection<Restriction> createRestrictionsFromTurnRestrictions( 368 Iterable<R> relations, 369 Map<N, SegmentNodeImpl> nodeCreationMap, 370 Map<W, List<Segment>> waySegmentMap) { 371 372 assert relations != null && nodeCreationMap != null && waySegmentMap != null; 373 374 Collection<Restriction> results = new LinkedList<Restriction>(); 375 376 for (R relation : relations) { 377 378 TagGroup tags = dataSource.getTagsR(relation); 379 380 if ("restriction".equals(tags.getValue("type")) 381 && tags.getValue("restriction") != null ) { 382 383 //evaluate relation 384 if (tags.getValue("restriction").startsWith("no_")) { 385 results.addAll(createRestrictionsFromRestrictionRelation(relation, true, nodeCreationMap, waySegmentMap)); 386 } else if (tags.getValue("restriction").startsWith("only_")) { 387 results.addAll(createRestrictionsFromRestrictionRelation(relation, false, nodeCreationMap, waySegmentMap)); 388 } 389 390 } 391 } 392 393 return results; 394 } 395 396 @SuppressWarnings("unchecked") //several generic casts that are checked with isInstance 397 private Collection<Restriction> createRestrictionsFromRestrictionRelation( 398 R relation, 399 boolean restrictive, 400 Map<N, SegmentNodeImpl> nodeCreationMap, 401 Map<W, List<Segment>> waySegmentMap) { 402 403 /* collect information about the relation */ 404 405 W fromWay = null; 406 Collection<N> viaNodes = new LinkedList<N>(); 407 Collection<W> viaWays = new LinkedList<W>(); 408 Collection<W> toWays = new LinkedList<W>(); 409 410 for (M member : dataSource.getMembers(relation)) { 411 412 if ("from".equals(dataSource.getRole(member))) { 413 if (fromWay != null || !dataSource.isWMember(member)) { 414 //broken restriction 415 return EMPTY_RESTRICTION_COLLECTION; 416 } else { 417 fromWay = (W)dataSource.getMember(member); 418 } 419 } else if ("to".equals(dataSource.getRole(member))) { 420 if (!dataSource.isWMember(member)) { 421 //broken restriction 422 return EMPTY_RESTRICTION_COLLECTION; 423 } else { 424 toWays.add((W)dataSource.getMember(member)); 425 } 426 } else if ("via".equals(dataSource.getRole(member))) { 427 if (dataSource.isWMember(member)) { 428 viaWays.add((W)dataSource.getMember(member)); 429 } else if (dataSource.isNMember(member)) { 430 viaNodes.add((N)dataSource.getMember(member)); 431 } 432 } 433 434 } 435 436 if (fromWay != null && toWays.size() > 0 && 437 (viaNodes.size() > 0 || viaWays.size() > 0)) { 438 439 return createRestrictionsFromRestrictionRelationMembers( 440 restrictive, nodeCreationMap, waySegmentMap, 441 fromWay, viaNodes, viaWays, toWays); 442 443 } else { 444 return new ArrayList<Restriction>(0); 445 } 446 } 447 448 private Collection<Restriction> createRestrictionsFromRestrictionRelationMembers( 449 boolean restrictive, 450 Map<N, SegmentNodeImpl> nodeCreationMap, Map<W, List<Segment>> waySegmentMap, 451 W fromWay, Collection<N> viaNodes, Collection<W> viaWays, Collection<W> toWays) { 452 453 Collection<SegmentNode> nodesCreatedFromViaNodes = new ArrayList<SegmentNode>(viaNodes.size()); 454 for (N viaNode : viaNodes) { 455 if (nodeCreationMap.containsKey(viaNode)) { 456 nodesCreatedFromViaNodes.add(nodeCreationMap.get(viaNode)); 457 } 458 } 459 460 /* check completeness of restriction to avoid dealing with incomplete restriction info */ 461 462 if (!waySegmentMap.containsKey(fromWay)) { 463 //broken restriction 464 return EMPTY_RESTRICTION_COLLECTION; 465 } 466 467 for (W viaWay : viaWays) { 468 if (!waySegmentMap.containsKey(viaWay)) { 469 //broken restriction 470 return EMPTY_RESTRICTION_COLLECTION; 471 } 472 } 473 474 for (W toWay : toWays) { 475 if (!waySegmentMap.containsKey(toWay)) { 476 //broken restriction 477 return EMPTY_RESTRICTION_COLLECTION; 478 } 479 } 480 481 /* find all via segments: 482 * via segments are segments created from via ways 483 * or segments starting and ending with nodes created from via nodes */ 484 485 ArrayList<Segment> viaSegments = new ArrayList<Segment>(); 486 487 for (W viaWay : viaWays) { 488 viaSegments.addAll(waySegmentMap.get(viaWay)); 489 } 490 491 for (SegmentNode nodeCreatedFromViaNode : nodesCreatedFromViaNodes) { 492 for (Segment segment : nodeCreatedFromViaNode.getOutboundSegments()) { 493 if (nodesCreatedFromViaNodes.contains(segment.getNode2())) { 494 viaSegments.add(segment); 495 } 496 } 497 } 498 499 viaSegments.trimToSize(); 500 501 /* create a set with all nodes that are based on via members */ 502 503 Set<SegmentNode> nodesCreatedFromViaMembers 504 = new HashSet<SegmentNode>(nodesCreatedFromViaNodes); 505 506 for (W viaWay : viaWays) { 507 for (N viaWayNode : dataSource.getNodes(viaWay)) { 508 nodesCreatedFromViaMembers.add(nodeCreationMap.get(viaWayNode)); 509 } 510 } 511 512 /* 513 * find from segment and to segments: 514 * Such a segment contains a node based on a via member. 515 * Each way should contain only one possible segment 516 * connecting to via members (due to splitting). 517 */ 518 519 Segment fromSegment = null; 520 Collection<Segment> toSegments = new ArrayList<Segment>(); 521 522 for (Segment possibleFromSegment : waySegmentMap.get(fromWay)) { 523 if (nodesCreatedFromViaMembers.contains(possibleFromSegment.getNode2())) { 524 525 if (fromSegment == null) { 526 fromSegment = possibleFromSegment; 527 } else { 528 //broken restriction 529 return EMPTY_RESTRICTION_COLLECTION; 530 } 531 532 } 533 } 534 if (fromSegment == null) { 535 //broken restriction 536 return EMPTY_RESTRICTION_COLLECTION; 537 } 538 539 if (restrictive) { 540 541 for (W toWay : toWays) { 542 if (waySegmentMap.containsKey(toWay)) { 543 Segment toSegment = null; 544 for (Segment possibleToSegment : waySegmentMap.get(toWay)) { 545 if (nodesCreatedFromViaMembers.contains(possibleToSegment.getNode1())) { 546 547 if (toSegment == null) { 548 toSegment = possibleToSegment; 549 } else { 550 //broken restriction 551 return EMPTY_RESTRICTION_COLLECTION; 552 } 553 554 } 555 } 556 if (toSegment == null) { 557 //broken restriction 558 return EMPTY_RESTRICTION_COLLECTION; 559 } else { 560 toSegments.add(toSegment); 561 } 562 } 563 } 564 565 } else { //!restrictive 566 567 /* forbidden "to" segments are all segments that start at a "via" node 568 * and are neither a via segment nor created from an allowed "to" way */ 569 570 for (SegmentNode toStartingNode : nodesCreatedFromViaMembers) { 571 for (Segment outboundSegment : toStartingNode.getOutboundSegments()) { 572 573 if (!viaSegments.contains(outboundSegment)) { 574 575 boolean isAllowed = false; 576 577 for (W toWay : toWays) { 578 if (waySegmentMap.get(toWay).contains(outboundSegment)) { 579 isAllowed = true; 580 break; 581 } 582 } 583 584 if (!isAllowed) { 585 toSegments.add(outboundSegment); 586 } 587 588 } 589 590 } 591 } 592 593 } 594 595 /* create restriction */ 596 597 Collection<Restriction> results = new ArrayList<Restriction>(1); 598 results.add(new RestrictionImpl(fromSegment, viaSegments, toSegments)); 599 return results; 600 } 601 602 /** 603 * creates Restrictions from barrier nodes (nodes that are considered impassable by the 604 * {@link #accessEvaluator}). These restrictions prevent moving from a segment before the 605 * barrier node to a segment after the barrier node. 606 * 607 * @param nodeCreationMap map providing the SegmentNode that has been created from a node, 608 * will not be modified; != null 609 * @param waySegmentMap map providing the Segments that have been created from a way, 610 * will not be modified; != null 611 * @return Restrictions created from barrier nodes; != null, but may be empty 612 */ 613 private Collection<Restriction> createRestrictionsFromBarrierNodes( 614 Map<N, SegmentNodeImpl> nodeCreationMap, 615 Map<W, List<Segment>> waySegmentMap) { 616 617 assert nodeCreationMap != null; 618 assert waySegmentMap != null; 619 620 Collection<Restriction> results = new LinkedList<Restriction>(); 621 622 for (N node : nodeCreationMap.keySet()) { 623 624 if (!accessEvaluator.nodeUsable(node, nodeCreationMap.get(node).getProperties())) { 625 626 SegmentNode barrierNode = nodeCreationMap.get(node); 627 628 for (Segment inboundSegment : barrierNode.getInboundSegments()) { 629 for (Segment outboundSegment : barrierNode.getOutboundSegments()) { 630 results.add(new RestrictionImpl(inboundSegment, EMPTY_SEGMENT_LIST, Arrays.asList(outboundSegment))); 631 } 632 } 633 634 } 635 636 } 637 638 return results; 639 } 640 641 /** 642 * determines the values of all RoadPropertyTypes from {@link #properties} for a way and 643 * creates a map with the types that have non-null values as keys, property values as content 644 */ 645 private Map<RoadPropertyType<?>, Object> getWayPropertyMap(W way, boolean forward) { 646 Map<RoadPropertyType<?>, Object> propertyValues; 647 propertyValues = new HashMap<RoadPropertyType<?>, Object>(); 648 for (RoadPropertyType<?> property : properties) { 649 Object value = property.evaluateW(way, forward, accessParameters, dataSource); 650 if (value != null) { 651 propertyValues.put(property, value); 652 } 653 } 654 return propertyValues; 655 } 656 657 /** 658 * determines the values of all RoadPropertyTypes from {@link #properties} for a node and 659 * creates a map with the types that have non-null values as keys, property values as content 660 */ 661 private Map<RoadPropertyType<?>, Object> getNodePropertyMap(N node) { 662 Map<RoadPropertyType<?>, Object> propertyValues; 663 propertyValues = new HashMap<RoadPropertyType<?>, Object>(); 664 for (RoadPropertyType<?> property : properties) { 665 Object value = property.evaluateN(node, accessParameters, dataSource); 666 if (value != null) { 667 propertyValues.put(property, value); 668 } 669 } 670 return propertyValues; 671 } 672 673 public void update(DataSource<?, ?, ?, ?> dataSource) { 674 assert this.dataSource == dataSource; 675 updateData(); 676 } 677 678 public void addObserver(TransitionStructureObserver observer) { 679 observers.add(observer); 680 } 681 682 public void deleteObserver(TransitionStructureObserver observer) { 683 observers.remove(observer); 684 } 685 686 protected void notifyObservers() { 687 for (TransitionStructureObserver observer : observers) { 688 observer.update(this); 689 } 690 } 691 691 692 692 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/Restriction.java
r16520 r23189 10 10 public interface Restriction { 11 11 12 13 14 15 16 12 /** 13 * returns the starting segment that will trigger the restriction when used; 14 * != null 15 */ 16 public Segment getFrom(); 17 17 18 19 20 21 22 23 24 18 /** 19 * returns the "via" segments. 20 * The restriction will remain active as long as only via segments are used. 21 * 22 * @return unmodifiable collection of segments; != null 23 */ 24 public Collection<Segment> getVias(); 25 25 26 27 28 29 30 31 32 26 /** 27 * returns the forbidden "to" segments. 28 * The restriction prevents leaving the via segment set by using one of the to segments. 29 * 30 * @return unmodifiable collection of segments; != null 31 */ 32 public Collection<Segment> getTos(); 33 33 34 34 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/Segment.java
r16520 r23189 6 6 public interface Segment extends TransitionStructureElement { 7 7 8 9 10 11 8 /** 9 * returns the node this segment starts at; != null 10 */ 11 public SegmentNode getNode1(); 12 12 13 14 15 16 13 /** 14 * returns the node this segment leads to; != null 15 */ 16 public SegmentNode getNode2(); 17 17 18 18 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/SegmentNode.java
r16520 r23189 8 8 public interface SegmentNode extends TransitionStructureElement { 9 9 10 11 10 /** returns the node's latitude */ 11 public double getLat(); 12 12 13 14 13 /** returns the node's longitude */ 14 public double getLon(); 15 15 16 17 16 /** returns all segments that end at this node */ 17 Collection<Segment> getInboundSegments(); 18 18 19 20 19 /** returns all segments that start at this node */ 20 Collection<Segment> getOutboundSegments(); 21 21 22 22 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/TransitionStructure.java
r16520 r23189 9 9 public interface TransitionStructure { 10 10 11 12 13 11 public Collection<SegmentNode> getNodes(); 12 public Collection<Segment> getSegments(); 13 public Collection<Restriction> getRestrictions(); 14 14 15 16 17 18 19 20 21 15 /** 16 * adds an observer. 17 * Does nothing if the parameter is already an observer of this TransitionStructure. 18 * 19 * @param observer observer object, != null 20 */ 21 public void addObserver(TransitionStructureObserver observer); 22 22 23 24 25 26 27 28 29 23 /** 24 * deletes an observer that has been added using {@link #addObserver(TransitionStructureObserver)}. 25 * Does nothing if the parameter isn't currently an observer of this TransitionStructure. 26 * 27 * @param observer observer object, != null 28 */ 29 public void deleteObserver(TransitionStructureObserver observer); 30 30 31 31 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/TransitionStructureElement.java
r16520 r23189 10 10 public interface TransitionStructureElement { 11 11 12 13 14 15 16 17 12 /** 13 * returns the types of this object's properties 14 * 15 * @return property type collection; != null 16 */ 17 public Collection<RoadPropertyType<?>> getAvailableProperties(); 18 18 19 20 21 22 23 24 25 19 /** 20 * returns the value of a property for this object 21 * 22 * @param propertyType property type to return value for; != null 23 * @return property value of the property for this segment; null if not available 24 */ 25 public <P> P getPropertyValue(RoadPropertyType<P> propertyType); 26 26 27 27 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/transition/TransitionStructureObserver.java
r16520 r23189 7 7 public interface TransitionStructureObserver { 8 8 9 10 11 12 13 9 /** 10 * informs this observer about changes in an observed transition structure 11 * @param transitionStructure observed transition structure that has changed; != null 12 */ 13 public void update(TransitionStructure transitionStructure); 14 14 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/util/GraphUtil.java
r16520 r23189 11 11 public final class GraphUtil { 12 12 13 14 13 /** prevents instantiation */ 14 private GraphUtil() { } 15 15 16 17 18 19 20 16 /** 17 * checks whether a node is an "end node" 18 * (a node whose {@link SegmentNode} is connected to at most one other {@link SegmentNode}) 19 */ 20 public static final boolean isEndNode(GraphNode node) { 21 21 22 22 SegmentNode ownSegmentNode = node.getSegmentNode(); 23 23 24 24 SegmentNode connectedNode = null; 25 25 26 27 28 29 30 31 32 33 34 35 26 for (Segment inboundSegment : node.getSegmentNode().getInboundSegments()) { 27 SegmentNode otherSegmentNode = inboundSegment.getNode1(); 28 if (otherSegmentNode != ownSegmentNode) { 29 if (connectedNode == null) { 30 connectedNode = otherSegmentNode; 31 } else if (connectedNode != otherSegmentNode) { 32 return false; 33 } 34 } 35 } 36 36 37 38 39 40 41 42 43 44 45 46 37 for (Segment outboundSegment : node.getSegmentNode().getOutboundSegments()) { 38 SegmentNode otherSegmentNode = outboundSegment.getNode2(); 39 if (otherSegmentNode != ownSegmentNode) { 40 if (connectedNode == null) { 41 connectedNode = otherSegmentNode; 42 } else if (connectedNode != otherSegmentNode) { 43 return false; 44 } 45 } 46 } 47 47 48 48 return true; 49 49 50 50 } 51 51 52 52 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/util/TagCondition.java
r16520 r23189 9 9 public interface TagCondition { 10 10 11 12 13 14 15 16 11 /** 12 * returns true if the tags match the condition 13 * 14 * @param tags tags to check against the condition; != null 15 */ 16 boolean matches(TagGroup tags); 17 17 18 18 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/util/TagConditionLogic.java
r16520 r23189 11 11 public final class TagConditionLogic { 12 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 13 /** prevents instantiation */ 14 private TagConditionLogic(){ } 15 16 /** 17 * creates a condition that is fulfilled if the set of tags contains a given tag 18 * 19 * @param tag tag that must be in the tag collection; != null 20 */ 21 public static TagCondition tag(final Tag tag) { 22 assert tag != null; 23 return new TagCondition() { 24 public boolean matches(TagGroup tags) { 25 return tags.contains(tag); 26 } 27 @Override 28 public String toString() { 29 return tag.toString(); 30 } 31 }; 32 } 33 34 /** 35 * creates a condition that is fulfilled if the set of tags contains a tag with the given key 36 * 37 * @param key the key to look for; != null 38 */ 39 public static TagCondition key(final String key) { 40 assert key != null; 41 return new TagCondition() { 42 public boolean matches(TagGroup tags) { 43 return tags.containsKey(key); 44 } 45 @Override 46 public String toString() { 47 return key; 48 } 49 }; 50 } 51 52 /** 53 * combines conditions using a boolean "and" 54 * 55 * @param condition first condition; != null 56 * @param conditions more conditions; each != null 57 */ 58 public static TagCondition and(final TagCondition condition, final TagCondition... conditions) { 59 return new TagCondition() { 60 public boolean matches(TagGroup tags) { 61 for (TagCondition c : conditions) { 62 if (!c.matches(tags)) { 63 return false; 64 } 65 } 66 return condition.matches(tags); 67 } 68 @Override 69 public String toString() { 70 StringBuilder result = new StringBuilder(); 71 result.append("("); 72 result.append(condition); 73 for (TagCondition c : conditions) { 74 result.append(" && "); 75 result.append(c); 76 } 77 result.append(")"); 78 return result.toString(); 79 } 80 }; 81 } 82 83 /** 84 * combines conditions using a boolean "and" 85 * 86 * @param conditions collection of conditions, must contain at least one element; != null 87 */ 88 public static TagCondition and(final Collection<TagCondition> conditions) { 89 if (conditions.size() == 0) { 90 throw new IllegalArgumentException("collection must contain at least one condition"); 91 } 92 return new TagCondition() { 93 public boolean matches(TagGroup tags) { 94 for (TagCondition c : conditions) { 95 if (!c.matches(tags)) { 96 return false; 97 } 98 } 99 return true; 100 } 101 @Override 102 public String toString() { 103 StringBuilder result = new StringBuilder(); 104 result.append("("); 105 boolean firstCondition = true; 106 for (TagCondition c : conditions) { 107 if (!firstCondition) { 108 result.append(" && "); 109 } 110 firstCondition = false; 111 result.append(c); 112 } 113 result.append(")"); 114 return result.toString(); 115 } 116 }; 117 } 118 119 /** 120 * combines conditions using a boolean "or" 121 * 122 * @param condition first condition; != null 123 * @param conditions more conditions; each != null 124 */ 125 public static TagCondition or(final TagCondition condition, final TagCondition... conditions) { 126 return new TagCondition() { 127 public boolean matches(TagGroup tags) { 128 for (TagCondition c : conditions) { 129 if (c.matches(tags)) { 130 return true; 131 } 132 } 133 return condition.matches(tags); 134 } 135 @Override 136 public String toString() { 137 StringBuilder result = new StringBuilder(); 138 result.append("("); 139 result.append(condition); 140 for (TagCondition c : conditions) { 141 result.append(" || "); 142 result.append(c); 143 } 144 result.append(")"); 145 return result.toString(); 146 } 147 }; 148 } 149 150 /** 151 * combines conditions using a boolean "or" 152 * 153 * @param conditions collection of conditions, must contain at least one element; != null 154 */ 155 public static TagCondition or(final Collection<TagCondition> conditions) { 156 if (conditions.size() == 0) { 157 throw new IllegalArgumentException("collection must contain at least one condition"); 158 } 159 return new TagCondition() { 160 public boolean matches(TagGroup tags) { 161 for (TagCondition c : conditions) { 162 if (c.matches(tags)) { 163 return true; 164 } 165 } 166 return false; 167 } 168 @Override 169 public String toString() { 170 StringBuilder result = new StringBuilder(); 171 result.append("("); 172 boolean firstCondition = true; 173 for (TagCondition c : conditions) { 174 if (!firstCondition) { 175 result.append(" || "); 176 } 177 firstCondition = false; 178 result.append(c); 179 } 180 result.append(")"); 181 return result.toString(); 182 } 183 }; 184 } 185 186 /** 187 * inverts a condition 188 * 189 * @param condition condition to invert, != null 190 */ 191 public static TagCondition not(final TagCondition condition) { 192 return new TagCondition() { 193 public boolean matches(TagGroup tags) { 194 return !condition.matches(tags); 195 } 196 @Override 197 public String toString() { 198 return "!" + condition; 199 } 200 }; 201 } 202 202 203 203 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/util/ValueStringParser.java
r20243 r23189 6 6 public final class ValueStringParser { 7 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 8 /** prevents instantiation */ 9 private ValueStringParser() { } 10 11 /** pattern that splits into a part before and after a decimal point */ 12 private static final Pattern DEC_POINT_PATTERN = Pattern.compile("^(\\-?\\d+)\\.(\\d+)$"); 13 14 public static final Float parseOsmDecimal(String value, boolean allowNegative) { 15 16 /* positive integer */ 17 18 try { 19 20 int weight = Integer.parseInt(value); 21 if (weight >= 0 || allowNegative) { 22 return (float)weight; 23 } 24 25 } catch (NumberFormatException nfe) {} 26 27 /* positive number with decimal point */ 28 29 Matcher matcher = DEC_POINT_PATTERN.matcher(value); 30 31 if (matcher.matches()) { 32 33 String stringBeforePoint = matcher.group(1); 34 String stringAfterPoint = matcher.group(2); 35 36 if (stringBeforePoint.length() > 0 || stringAfterPoint.length() > 0) { 37 38 try { 39 40 float beforePoint = Integer.parseInt(stringBeforePoint); 41 float afterPoint = Integer.parseInt(stringAfterPoint); 42 43 double result = Math.signum(beforePoint) * 44 (Math.abs(beforePoint) 45 + Math.pow(10, -stringAfterPoint.length()) * afterPoint); 46 47 if (result >= 0 || allowNegative) { 48 return (float)result; 49 } 50 51 } catch (NumberFormatException nfe) {} 52 53 } 54 } 55 56 return null; 57 } 58 59 private static final Pattern KMH_PATTERN = Pattern.compile("^(\\d+)\\s*km/h$"); 60 private static final Pattern MPH_PATTERN = Pattern.compile("^(\\d+)\\s*mph$"); 61 62 private static final float KM_PER_MILE = 1.609344f; 63 64 /** 65 * parses a speed value given e.g. for the "maxspeed" key. 66 * 67 * @return speed in km/h; null if value had syntax errors 68 */ 69 public static final Float parseSpeed(String value) { 70 71 /* try numeric speed (implied km/h) */ 72 73 Float speed = parseOsmDecimal(value, false); 74 if (speed != null) { 75 return speed; 76 } 77 78 /* try km/h speed */ 79 80 Matcher kmhMatcher = KMH_PATTERN.matcher(value); 81 if (kmhMatcher.matches()) { 82 String kmhString = kmhMatcher.group(1); 83 try { 84 return (float)Integer.parseInt(kmhString); 85 } catch (NumberFormatException nfe) {} 86 } 87 88 /* try mph speed */ 89 90 Matcher mphMatcher = MPH_PATTERN.matcher(value); 91 if (mphMatcher.matches()) { 92 String mphString = mphMatcher.group(1); 93 try { 94 int mph = Integer.parseInt(mphString); 95 return KM_PER_MILE * mph; 96 } catch (NumberFormatException nfe) {} 97 } 98 99 /* all possibilities failed */ 100 101 return null; 102 } 103 104 private static final Pattern M_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*m$"); 105 private static final Pattern KM_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*km$"); 106 private static final Pattern MI_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*mi$"); 107 private static final Pattern FEET_INCHES_PATTERN = Pattern.compile("^([\\d]+)'\\s*([\\d]+)\""); 108 109 private static final double M_PER_MI = 1609.344; 110 private static final double M_PER_INCH = 0.0254f; 111 112 /** 113 * parses a measure value given e.g. for the "width" or "length" key. 114 * 115 * @return measure in m; null if value had syntax errors 116 */ 117 public static final Float parseMeasure(String value) { 118 119 /* try numeric measure (implied m) */ 120 121 Float measure = parseOsmDecimal(value, false); 122 if (measure != null) { 123 return measure; 124 } 125 126 /* try m measure */ 127 128 Matcher mMatcher = M_PATTERN.matcher(value); 129 if (mMatcher.matches()) { 130 String mString = mMatcher.group(1); 131 return parseOsmDecimal(mString, false); 132 } 133 134 /* try km measure */ 135 136 Matcher kmMatcher = KM_PATTERN.matcher(value); 137 if (kmMatcher.matches()) { 138 String kmString = kmMatcher.group(1); 139 float km = parseOsmDecimal(kmString, false); 140 return 1000 * km; 141 } 142 143 /* try mi measure */ 144 145 Matcher miMatcher = MI_PATTERN.matcher(value); 146 if (miMatcher.matches()) { 147 String miString = miMatcher.group(1); 148 float mi = parseOsmDecimal(miString, false); 149 return (float)(M_PER_MI * mi); 150 } 151 152 /* try feet/inches measure */ 153 154 Matcher feetInchesMatcher = FEET_INCHES_PATTERN.matcher(value); 155 if (feetInchesMatcher.matches()) { 156 String feetString = feetInchesMatcher.group(1); 157 String inchesString = feetInchesMatcher.group(2); 158 try { 159 int feet = Integer.parseInt(feetString); 160 int inches = Integer.parseInt(inchesString); 161 if (feet >= 0 && inches >= 0 && inches < 12) { 162 return (float)(M_PER_INCH * (12 * feet + inches)); 163 } 164 } catch (NumberFormatException nfe) {} 165 } 166 167 /* all possibilities failed */ 168 169 return null; 170 } 171 172 private static final Pattern T_PATTERN = Pattern.compile("^([\\d\\.]+)\\s*t$"); 173 174 /** 175 * parses a weight value given e.g. for the "maxweight" or "maxaxleload" key. 176 * 177 * @return weight in t; null if value had syntax errors 178 */ 179 public static Float parseWeight(String value) { 180 181 /* try numeric weight (implied t) */ 182 183 Float weight = parseOsmDecimal(value, false); 184 if (weight != null) { 185 return weight; 186 } 187 188 /* try t weight */ 189 190 Matcher tMatcher = T_PATTERN.matcher(value); 191 if (tMatcher.matches()) { 192 String tString = tMatcher.group(1); 193 return parseOsmDecimal(tString, false); 194 } 195 196 /* all possibilities failed */ 197 198 return null; 199 200 } 201 202 private static final Pattern INCLINE_PATTERN = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)\\s*%$"); 203 204 /** 205 * parses an incline value as given for the "incline" key. 206 * 207 * @return incline in percents; null if value had syntax errors 208 */ 209 public static final Float parseIncline(String value) { 210 211 Matcher inclineMatcher = INCLINE_PATTERN.matcher(value); 212 if (inclineMatcher.matches()) { 213 String inclineString = inclineMatcher.group(1); 214 return parseOsmDecimal(inclineString, true); 215 } 216 217 return null; 218 } 219 219 220 220 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/ColorScheme.java
r16520 r23189 11 11 public interface ColorScheme { 12 12 13 14 15 16 17 13 /** 14 * returns the color to be used for a node in a WayGraph 15 * @param edge GraphNode to determine the color for; != null 16 */ 17 public Color getNodeColor(GraphNode node); 18 18 19 20 21 22 23 19 /** 20 * returns the color to be used for an edge in a WayGraph 21 * @param segment segment to determine the color for; != null 22 */ 23 public Color getSegmentColor(Segment segment); 24 24 25 25 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/DefaultNodePositioner.java
r16520 r23189 11 11 public class DefaultNodePositioner implements NodePositioner { 12 12 13 13 public LatLonCoords getPosition(GraphNode node) { 14 14 15 15 SegmentNode segmentNode = node.getSegmentNode(); 16 16 17 18 17 if (2 >= segmentNode.getInboundSegments().size() 18 + segmentNode.getOutboundSegments().size() ) { 19 19 20 21 22 20 return new LatLonCoords( 21 node.getSegmentNode().getLat(), 22 node.getSegmentNode().getLon()); 23 23 24 24 } else { 25 25 26 27 26 SegmentNode node1 = node.getSegment().getNode1(); 27 SegmentNode node2 = node.getSegment().getNode2(); 28 28 29 29 assert segmentNode == node1 || segmentNode == node2; 30 30 31 31 LatLonCoords result; 32 32 33 34 35 36 37 38 39 40 41 33 if (segmentNode == node1) { 34 result = new LatLonCoords( 35 (2 * node1.getLat() + node2.getLat()) / 3, 36 (2 * node1.getLon() + node2.getLon()) / 3); 37 } else { 38 result = new LatLonCoords( 39 (node1.getLat() + 2 * node2.getLat()) / 3, 40 (node1.getLon() + 2 * node2.getLon()) / 3); 41 } 42 42 43 44 45 43 return result; 44 } 45 } 46 46 47 47 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/EndNodeColorScheme.java
r16520 r23189 12 12 public class EndNodeColorScheme implements ColorScheme { 13 13 14 15 16 14 private final Color nodeColor; 15 private final Color endNodeColor; 16 private final Color segmentColor; 17 17 18 19 20 21 22 18 public EndNodeColorScheme(Color nodeColor, Color endNodeColor, Color segmentColor) { 19 this.nodeColor = nodeColor; 20 this.endNodeColor = endNodeColor; 21 this.segmentColor = segmentColor; 22 } 23 23 24 25 26 24 public Color getNodeColor(GraphNode node) { 25 return GraphUtil.isEndNode(node) ? endNodeColor : nodeColor; 26 } 27 27 28 29 30 28 public Color getSegmentColor(Segment segment) { 29 return segmentColor; 30 } 31 31 32 32 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/FloatPropertyColorScheme.java
r18130 r23189 22 22 public class FloatPropertyColorScheme implements ColorScheme { 23 23 24 25 26 24 private final Class<? extends RoadPropertyType<Float>> propertyClass; 25 private final Map<Float, Color> colorMap; 26 private final Color defaultColor; 27 27 28 29 30 31 32 33 34 35 36 37 28 /** 29 * @param propertyClass property type to get values for; != null 30 * @param colorMap map from some values to colors. 31 * Colors for all other values are interpolated. 32 * This map will be copied and not used directly later. != null 33 * @param defaultColor color that is used when the property is not available; != null 34 */ 35 public FloatPropertyColorScheme(Class<? extends RoadPropertyType<Float>> propertyClass, 36 Map<Float, Color> colorMap, Color defaultColor) { 37 assert propertyClass != null && colorMap != null && defaultColor != null; 38 38 39 40 41 42 39 this.propertyClass = propertyClass; 40 this.colorMap = new HashMap<Float, Color>(colorMap); 41 this.defaultColor = defaultColor; 42 } 43 43 44 45 44 public Color getSegmentColor(Segment segment) { 45 assert segment != null; 46 46 47 48 49 50 51 52 53 54 55 56 47 Float propertyValue = null; 48 Collection<RoadPropertyType<?>> availableProperties = segment.getAvailableProperties(); 49 for (RoadPropertyType<?> property : availableProperties) { 50 if (propertyClass.isInstance(property)) { 51 @SuppressWarnings("unchecked") //has been checked using isInstance 52 RoadPropertyType<Float> floatProperty = (RoadPropertyType<Float>)property; 53 propertyValue = segment.getPropertyValue(floatProperty); 54 break; 55 } 56 } 57 57 58 59 60 61 62 63 58 if (propertyValue != null) { 59 return getColorForValue(propertyValue); 60 } else { 61 return defaultColor; 62 } 63 } 64 64 65 65 public Color getNodeColor(GraphNode node) { 66 66 67 67 List<Color> segmentColors = new ArrayList<Color>(); 68 68 69 70 71 for (GraphEdge edge : node.getInboundEdges()) {72 List<Segment> edgeSegments = edge.getPropertyValue(GraphEdgeSegments.PROPERTY);73 if (edgeSegments.size() > 0) {74 Segment firstSegment = edgeSegments.get(0);75 segmentColors.add(getSegmentColor(firstSegment));76 }77 }78 for (GraphEdge edge : node.getOutboundEdges()) {79 List<Segment> edgeSegments = edge.getPropertyValue(GraphEdgeSegments.PROPERTY);80 if (edgeSegments.size() > 0) {81 Segment lastSegment = edgeSegments.get(edgeSegments.size()-1);82 segmentColors.add(getSegmentColor(lastSegment));83 }84 }85 69 86 if (segmentColors.size() > 0) {87 return averageColor(segmentColors);88 } else {89 return Color.WHITE;90 }91 70 92 } 71 for (GraphEdge edge : node.getInboundEdges()) { 72 List<Segment> edgeSegments = edge.getPropertyValue(GraphEdgeSegments.PROPERTY); 73 if (edgeSegments.size() > 0) { 74 Segment firstSegment = edgeSegments.get(0); 75 segmentColors.add(getSegmentColor(firstSegment)); 76 } 77 } 78 for (GraphEdge edge : node.getOutboundEdges()) { 79 List<Segment> edgeSegments = edge.getPropertyValue(GraphEdgeSegments.PROPERTY); 80 if (edgeSegments.size() > 0) { 81 Segment lastSegment = edgeSegments.get(edgeSegments.size()-1); 82 segmentColors.add(getSegmentColor(lastSegment)); 83 } 84 } 93 85 94 /** 95 * returns the color for a value 96 * @param value value to get color for; != null 97 * @return color; != null 98 */ 99 protected Color getColorForValue(Float value) { 100 assert value != null; 86 if (segmentColors.size() > 0) { 87 return averageColor(segmentColors); 88 } else { 89 return Color.WHITE; 90 } 101 91 102 if (colorMap.containsKey(value)) { 92 } 103 93 104 return colorMap.get(value); 94 /** 95 * returns the color for a value 96 * @param value value to get color for; != null 97 * @return color; != null 98 */ 99 protected Color getColorForValue(Float value) { 100 assert value != null; 105 101 106 } else{102 if (colorMap.containsKey(value)) { 107 103 108 LinkedList<Float> valuesWithDefinedColor = new LinkedList<Float>(colorMap.keySet()); 109 Collections.sort(valuesWithDefinedColor); 104 return colorMap.get(value); 110 105 111 if (value <= valuesWithDefinedColor.getFirst()){106 } else { 112 107 113 return colorMap.get(valuesWithDefinedColor.getFirst()); 108 LinkedList<Float> valuesWithDefinedColor = new LinkedList<Float>(colorMap.keySet()); 109 Collections.sort(valuesWithDefinedColor); 114 110 115 } elseif (value>= valuesWithDefinedColor.getLast()) {111 if (value <= valuesWithDefinedColor.getFirst()) { 116 112 117 Last());113 return colorMap.get(valuesWithDefinedColor.getFirst()); 118 114 119 } else{115 } else if (value >= valuesWithDefinedColor.getLast()) { 120 116 121 /* interpolate */ 117 return colorMap.get(valuesWithDefinedColor.getLast()); 122 118 123 Float lowerValue = valuesWithDefinedColor.getFirst(); 124 Float higherValue = null; 119 } else { 125 120 126 for (Float v : valuesWithDefinedColor) { 127 if (v >= value) { 128 higherValue = v; 129 break; 130 } 131 lowerValue = v; 132 } 121 /* interpolate */ 133 122 134 assert lowerValue != null && higherValue != null; 123 Float lowerValue = valuesWithDefinedColor.getFirst(); 124 Float higherValue = null; 135 125 136 Color lowerColor = colorMap.get(lowerValue); 137 Color higherColor = colorMap.get(higherValue); 126 for (Float v : valuesWithDefinedColor) { 127 if (v >= value) { 128 higherValue = v; 129 break; 130 } 131 lowerValue = v; 132 } 138 133 139 float weightHigherColor = (value -lowerValue) / (higherValue- lowerValue);134 assert lowerValue != null && higherValue != null; 140 135 141 return weightedAverageColor(lowerColor, higherColor, weightHigherColor); 136 Color lowerColor = colorMap.get(lowerValue); 137 Color higherColor = colorMap.get(higherValue); 142 138 143 } 139 float weightHigherColor = (value - lowerValue) / (higherValue - lowerValue); 144 140 145 } 141 return weightedAverageColor(lowerColor, higherColor, weightHigherColor); 146 142 147 143 } 148 144 149 /** 150 * returns an average of all colors that have been passed as parameter 151 * 152 * @param colors colors to calculate average from; not empty or null 153 * @return average color; != null 154 */ 155 private static Color averageColor(List<Color> colors) { 156 assert colors != null && colors.size() > 0; 145 } 157 146 158 float weightPerColor = 1.0f / colors.size(); 147 } 159 148 160 Color average = new Color(0,0,0); 149 /** 150 * returns an average of all colors that have been passed as parameter 151 * 152 * @param colors colors to calculate average from; not empty or null 153 * @return average color; != null 154 */ 155 private static Color averageColor(List<Color> colors) { 156 assert colors != null && colors.size() > 0; 161 157 162 for (Color color : colors) { 163 average = new Color( 164 Math.min(Math.round(average.getRed() + weightPerColor*color.getRed()), 255), 165 Math.min(Math.round(average.getGreen() + weightPerColor*color.getGreen()), 255), 166 Math.min(Math.round(average.getBlue() + weightPerColor*color.getBlue()), 255)); 167 } 158 float weightPerColor = 1.0f / colors.size(); 168 159 169 return average; 170 } 160 Color average = new Color(0,0,0); 171 161 172 /** 173 * returns a weighted average of two colors 174 * 175 * @param color1 first color for the average; != null 176 * @param color2 second color for the average; != null 177 * @param weightColor2 weight of color2; must be in [0..1] 178 * @return average color; != null 179 */ 180 private static Color weightedAverageColor(Color color1, Color color2, float weightColor2) { 181 assert color1 != null && color2 != null; 182 assert 0 <= weightColor2 && weightColor2 <= 1; 162 for (Color color : colors) { 163 average = new Color( 164 Math.min(Math.round(average.getRed() + weightPerColor*color.getRed()), 255), 165 Math.min(Math.round(average.getGreen() + weightPerColor*color.getGreen()), 255), 166 Math.min(Math.round(average.getBlue() + weightPerColor*color.getBlue()), 255)); 167 } 183 168 184 return new Color( 185 Math.round((1 - weightColor2) * color1.getRed() + weightColor2 * color2.getRed()), 186 Math.round((1 - weightColor2) * color1.getGreen() + weightColor2 * color2.getGreen()), 187 Math.round((1 - weightColor2) * color1.getBlue() + weightColor2 * color2.getBlue())); 188 } 169 return average; 170 } 171 172 /** 173 * returns a weighted average of two colors 174 * 175 * @param color1 first color for the average; != null 176 * @param color2 second color for the average; != null 177 * @param weightColor2 weight of color2; must be in [0..1] 178 * @return average color; != null 179 */ 180 private static Color weightedAverageColor(Color color1, Color color2, float weightColor2) { 181 assert color1 != null && color2 != null; 182 assert 0 <= weightColor2 && weightColor2 <= 1; 183 184 return new Color( 185 Math.round((1 - weightColor2) * color1.getRed() + weightColor2 * color2.getRed()), 186 Math.round((1 - weightColor2) * color1.getGreen() + weightColor2 * color2.getGreen()), 187 Math.round((1 - weightColor2) * color1.getBlue() + weightColor2 * color2.getBlue())); 188 } 189 189 190 190 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/InclineColorScheme.java
r16520 r23189 12 12 public class InclineColorScheme extends FloatPropertyColorScheme { 13 13 14 14 private static final Map<Float, Color> COLOR_MAP; 15 15 16 17 18 19 20 21 16 static { 17 COLOR_MAP = new HashMap<Float, Color>(); 18 COLOR_MAP.put(-30f, Color.BLUE); 19 COLOR_MAP.put(0f, Color.WHITE); 20 COLOR_MAP.put(30f, Color.RED); 21 } 22 22 23 24 25 23 public InclineColorScheme() { 24 super(RoadIncline.class, COLOR_MAP, Color.GRAY); 25 } 26 26 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/LatLonCoords.java
r16520 r23189 6 6 public final class LatLonCoords { 7 7 8 9 8 private final double lat; 9 private final double lon; 10 10 11 12 13 14 11 public LatLonCoords(double lat, double lon) { 12 this.lat = lat; 13 this.lon = lon; 14 } 15 15 16 17 18 16 public double getLat() { 17 return lat; 18 } 19 19 20 21 22 20 public double getLon() { 21 return lon; 22 } 23 23 24 24 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/MaxheightColorScheme.java
r16520 r23189 12 12 public class MaxheightColorScheme extends FloatPropertyColorScheme { 13 13 14 14 private static final Map<Float, Color> COLOR_MAP; 15 15 16 17 18 19 20 21 16 static { 17 COLOR_MAP = new HashMap<Float, Color>(); 18 COLOR_MAP.put(0f, new Color(0, 0, 50)); 19 COLOR_MAP.put(10f, new Color(100, 100, 255)); 20 COLOR_MAP.put(30f, new Color(200, 200, 255)); 21 } 22 22 23 24 25 23 public MaxheightColorScheme() { 24 super(RoadMaxheight.class, COLOR_MAP, Color.WHITE); 25 } 26 26 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/MaxspeedColorScheme.java
r16520 r23189 12 12 public class MaxspeedColorScheme extends FloatPropertyColorScheme { 13 13 14 14 private static final Map<Float, Color> COLOR_MAP; 15 15 16 17 18 19 20 21 22 23 16 static { 17 COLOR_MAP = new HashMap<Float, Color>(); 18 COLOR_MAP.put(0f, new Color(50, 0, 0)); 19 COLOR_MAP.put(30f, Color.RED); 20 COLOR_MAP.put(60f, Color.YELLOW); 21 COLOR_MAP.put(90f, Color.GREEN); 22 COLOR_MAP.put(150f, Color.BLUE); 23 } 24 24 25 26 27 25 public MaxspeedColorScheme() { 26 super(RoadMaxspeed.class, COLOR_MAP, Color.GRAY); 27 } 28 28 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/MaxweightColorScheme.java
r16520 r23189 12 12 public class MaxweightColorScheme extends FloatPropertyColorScheme { 13 13 14 14 private static final Map<Float, Color> COLOR_MAP; 15 15 16 17 18 19 20 21 16 static { 17 COLOR_MAP = new HashMap<Float, Color>(); 18 COLOR_MAP.put(0f, new Color(0, 0, 50)); 19 COLOR_MAP.put(20f, new Color(100, 100, 255)); 20 COLOR_MAP.put(50f, new Color(200, 200, 255)); 21 } 22 22 23 24 25 23 public MaxweightColorScheme() { 24 super(RoadMaxweight.class, COLOR_MAP, Color.WHITE); 25 } 26 26 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/NodePositioner.java
r16520 r23189 9 9 public interface NodePositioner { 10 10 11 11 LatLonCoords getPosition(GraphNode node); 12 12 13 13 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/NonMovingNodePositioner.java
r16520 r23189 5 5 public class NonMovingNodePositioner implements NodePositioner { 6 6 7 8 9 10 11 7 public LatLonCoords getPosition(GraphNode node) { 8 return new LatLonCoords( 9 node.getSegmentNode().getLat(), 10 node.getSegmentNode().getLon()); 11 } 12 12 13 13 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/core/visualisation/SingleColorScheme.java
r16520 r23189 12 12 public class SingleColorScheme implements ColorScheme { 13 13 14 15 14 private final Color nodeColor; 15 private final Color segmentColor; 16 16 17 18 19 20 17 public SingleColorScheme(Color nodeColor, Color segmentColor) { 18 this.nodeColor = nodeColor; 19 this.segmentColor = segmentColor; 20 } 21 21 22 23 24 22 public Color getNodeColor(GraphNode node) { 23 return nodeColor; 24 } 25 25 26 27 28 26 public Color getSegmentColor(Segment segment) { 27 return segmentColor; 28 } 29 29 30 30 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/GraphViewPlugin.java
r19441 r23189 52 52 public class GraphViewPlugin extends Plugin implements LayerChangeListener, Observer { 53 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 54 private static final Collection<RoadPropertyType<?>> PROPERTIES; 55 56 static { 57 PROPERTIES = new LinkedList<RoadPropertyType<?>>(); 58 PROPERTIES.add(new RoadIncline()); 59 PROPERTIES.add(new RoadMaxaxleload()); 60 PROPERTIES.add(new RoadMaxheight()); 61 PROPERTIES.add(new RoadMaxlength()); 62 PROPERTIES.add(new RoadMaxspeed()); 63 PROPERTIES.add(new RoadMaxweight()); 64 PROPERTIES.add(new RoadMaxwidth()); 65 PROPERTIES.add(new RoadMinspeed()); 66 PROPERTIES.add(new RoadSurface()); 67 PROPERTIES.add(new RoadTracktype()); 68 PROPERTIES.add(new RoadWidth()); 69 } 70 71 private final GraphViewPreferences preferences; 72 73 private JOSMTransitionStructure transitionStructure; 74 private GraphViewLayer graphViewLayer; 75 76 /** creates the plugin */ 77 public GraphViewPlugin(PluginInformation info) { 78 super(info); 79 preferences = GraphViewPreferences.getInstance(); 80 this.preferences.addObserver(this); 81 82 } 83 84 /** allows creation/update of GraphViewLayer */ 85 public void createGraphViewLayer() { 86 87 try { 88 89 if (graphViewLayer != null) { 90 91 AccessRuleset accessRuleset = getAccessRuleset(); 92 93 if (accessRuleset == null) { 94 JOptionPane.showMessageDialog(Main.parent, "No ruleset has been selected!", "No ruleset", JOptionPane.ERROR_MESSAGE); 95 } else { 96 transitionStructure.setAccessParametersAndRuleset(preferences.getCurrentParameterBookmark(), accessRuleset); 97 transitionStructure.forceUpdate(); 98 } 99 100 } else { 101 102 AccessRuleset accessRuleset = getAccessRuleset(); 103 104 if (accessRuleset == null) { 105 JOptionPane.showMessageDialog(Main.parent, "No ruleset has been selected!", 106 "No ruleset", JOptionPane.ERROR_MESSAGE); 107 } else { 108 109 transitionStructure = new JOSMTransitionStructure( 110 preferences.getCurrentParameterBookmark(), 111 accessRuleset, 112 PROPERTIES); 113 114 WayGraph graph = new TSBasedWayGraph(transitionStructure); 115 116 graphViewLayer = new GraphViewLayer(); 117 graphViewLayer.setWayGraph(graph); 118 graphViewLayer.setColorScheme(preferences.getCurrentColorScheme()); 119 graphViewLayer.setNodePositioner(new DefaultNodePositioner()); 120 121 Main.main.addLayer(graphViewLayer); 122 123 } 124 125 } 126 127 } catch (AccessRulesetSyntaxException e) { 128 JOptionPane.showMessageDialog(Main.parent, "syntax exception in access ruleset:\n" + e); 129 e.printStackTrace(); 130 } catch (FileNotFoundException e) { 131 JOptionPane.showMessageDialog(Main.parent, "file not found:\n" + e); 132 e.printStackTrace(); 133 } catch (IOException e) { 134 JOptionPane.showMessageDialog(Main.parent, "problem when accessing a file:\n" + e); 135 e.printStackTrace(); 136 } 137 138 } 139 140 /** allows update of GraphViewLayer */ 141 public void updateGraphViewLayer() { 142 143 try { 144 145 if (graphViewLayer != null) { 146 147 AccessRuleset accessRuleset = getAccessRuleset(); 148 149 if (accessRuleset == null) { 150 JOptionPane.showMessageDialog(Main.parent, "No ruleset has been selected!", 151 "No ruleset", JOptionPane.ERROR_MESSAGE); 152 } else { 153 transitionStructure.setAccessParametersAndRuleset( 154 preferences.getCurrentParameterBookmark(), accessRuleset); 155 transitionStructure.forceUpdate(); 156 } 157 158 } 159 160 } catch (AccessRulesetSyntaxException e) { 161 JOptionPane.showMessageDialog(Main.parent, "syntax exception in access ruleset:\n" + e); 162 e.printStackTrace(); 163 } catch (FileNotFoundException e) { 164 JOptionPane.showMessageDialog(Main.parent, "file not found:\n" + e); 165 e.printStackTrace(); 166 } catch (IOException e) { 167 JOptionPane.showMessageDialog(Main.parent, "problem when accessing a file:\n" + e); 168 e.printStackTrace(); 169 } 170 171 } 172 173 /** repaints the GraphViewLayer without recalculating the graph (visual update) */ 174 public void repaintGraphViewLayer() { 175 176 if (graphViewLayer != null) { 177 Main.panel.repaint(); 178 } 179 180 } 181 182 /** 183 * @return ruleset read from a source as specified by preferences, null if the preferences 184 * don't specify a ruleset source 185 * @throws AccessRulesetSyntaxException 186 * @throws IOException 187 * @throws FileNotFoundException 188 */ 189 private AccessRuleset getAccessRuleset() 190 throws AccessRulesetSyntaxException, IOException, FileNotFoundException { 191 192 InputStream rulesetInputStream; 193 194 if (preferences.getUseInternalRulesets()) { 195 196 InternalRuleset ruleset = preferences.getCurrentInternalRuleset(); 197 198 if (ruleset == null) { 199 return null; 200 } 201 202 ClassLoader classLoader = this.getClass().getClassLoader(); 203 URL rulesetURL = classLoader.getResource(ruleset.getResourceName()); 204 205 if (rulesetURL != null) { 206 rulesetInputStream = rulesetURL.openStream(); 207 } else { 208 throw new FileNotFoundException("couldn't find built-in ruleset " + ruleset); 209 } 210 211 } else { 212 213 File rulesetFile = preferences.getCurrentRulesetFile(); 214 215 if (rulesetFile == null) { 216 return null; 217 } 218 219 rulesetInputStream = new FileInputStream(rulesetFile); 220 221 } 222 223 return AccessRulesetReader.readAccessRuleset(rulesetInputStream); 224 225 } 226 227 @Override 228 public PreferenceSetting getPreferenceSetting() { 229 return new GraphViewPreferenceEditor(); 230 } 231 232 @Override 233 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 234 if (newFrame != null) { 235 if (oldFrame == null) { 236 final GraphViewDialog laneDialog 237 = new GraphViewDialog(this); 238 newFrame.addToggleDialog(laneDialog); 239 } 240 MapView.addLayerChangeListener(this); 241 } else { 242 MapView.removeLayerChangeListener(this); 243 } 244 } 245 246 public void layerRemoved(Layer oldLayer) { 247 if (oldLayer == graphViewLayer) { 248 graphViewLayer = null; 249 } else if (oldLayer == Main.map.mapView.getEditLayer()) { //data layer removed 250 if (graphViewLayer != null) { 251 Main.map.mapView.removeLayer(graphViewLayer); 252 graphViewLayer = null; 253 } 254 } 255 } 256 257 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 258 //do nothing 259 } 260 261 public void layerAdded(Layer newLayer) { 262 //do nothing 263 } 264 265 public void update(Observable arg0, Object arg1) { 266 if (arg0 == preferences) { 267 if (graphViewLayer != null) { 268 graphViewLayer.setColorScheme(preferences.getCurrentColorScheme()); 269 } 270 } 271 } 272 272 273 273 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/data/JOSMDataSource.java
r21610 r23189 26 26 public class JOSMDataSource implements DataSource<Node, Way, Relation, RelationMember> { 27 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 28 public double getLat(Node node) { 29 return node.getCoor().lat(); 30 } 31 32 public double getLon(Node node) { 33 return node.getCoor().lon(); 34 } 35 36 public Iterable<RelationMember> getMembers(Relation relation) { 37 return relation.getMembers(); 38 } 39 40 public Iterable<Node> getNodes(Way way) { 41 return new FilteredOsmPrimitiveIterable<Node>(way.getNodes()); 42 } 43 44 public Iterable<Node> getNodes() { 45 return new FilteredOsmPrimitiveIterable<Node>(Main.main.getCurrentDataSet().getNodes()); 46 } 47 48 public Iterable<Relation> getRelations() { 49 return new FilteredRelationIterable(Main.main.getCurrentDataSet().getRelations()); 50 } 51 52 public Iterable<Way> getWays() { 53 return new FilteredOsmPrimitiveIterable<Way>(Main.main.getCurrentDataSet().getWays()); 54 } 55 56 public TagGroup getTagsN(Node node) { 57 return getTags(node); 58 } 59 60 public TagGroup getTagsW(Way way) { 61 return getTags(way); 62 } 63 64 public TagGroup getTagsR(Relation relation) { 65 return getTags(relation); 66 } 67 68 private TagGroup getTags(OsmPrimitive primitive) { 69 if (primitive.getKeys() == null) { 70 return EMPTY_TAG_GROUP; 71 } else { 72 return new MapBasedTagGroup(primitive.getKeys()); 73 } 74 } 75 76 public Object getMember(RelationMember member) { 77 return member.getMember(); 78 } 79 80 public String getRole(RelationMember member) { 81 return member.getRole(); 82 } 83 84 public boolean isNMember(RelationMember member) { 85 return member.getMember() instanceof Node; 86 } 87 88 public boolean isWMember(RelationMember member) { 89 return member.getMember() instanceof Way; 90 } 91 92 public boolean isRMember(RelationMember member) { 93 return member.getMember() instanceof Relation; 94 } 95 96 97 private static final TagGroup EMPTY_TAG_GROUP; 98 static { 99 Map<String, String> emptyMap = new HashMap<String, String>(0); 100 EMPTY_TAG_GROUP = new MapBasedTagGroup(emptyMap); 101 } 102 103 /** 104 * Iterable of OsmPrimitive objects based on an existing Iterable, 105 * will filter incomplete and deleted objects from the iterator. 106 * 107 * @param <P> OsmPrimitive subtype 108 */ 109 public static class FilteredOsmPrimitiveIterable<P extends OsmPrimitive> implements Iterable<P> { 110 111 private final Iterable<P> originalIterable; 112 113 public FilteredOsmPrimitiveIterable(Iterable<P> originalIterable) { 114 this.originalIterable = originalIterable; 115 } 116 117 /** returns an iterator. The iterator does not support {@link Iterator#remove()}. */ 118 public Iterator<P> iterator() { 119 return new FilteredIterator(originalIterable.iterator()); 120 } 121 122 private class FilteredIterator implements Iterator<P> { 123 124 private final Iterator<P> originalIterator; 125 126 private P next; 127 128 public FilteredIterator(Iterator<P> originalIterator) { 129 this.originalIterator = originalIterator; 130 updateNext(); 131 } 132 133 public boolean hasNext() { 134 return next != null; 135 } 136 137 public P next() { 138 if (next != null) { 139 P result = next; 140 updateNext(); 141 return result; 142 } else { 143 throw new NoSuchElementException(); 144 } 145 } 146 147 public void remove() { 148 throw new UnsupportedOperationException(); 149 } 150 151 private void updateNext() { 152 next = null; 153 while (originalIterator.hasNext()) { 154 P originalNext = originalIterator.next(); 155 if (accept(originalNext)) { 156 next = originalNext; 157 break; 158 } 159 } 160 } 161 162 } 163 164 protected boolean accept(P primitive) { 165 return !primitive.isDeleted() && !primitive.isIncomplete(); 166 } 167 } 168 169 /** 170 * Relation-specific variant of the FilteredOsmPrimitiveIterable, 171 * also checks completeness of relation's members 172 */ 173 public static class FilteredRelationIterable extends FilteredOsmPrimitiveIterable<Relation> { 174 175 public FilteredRelationIterable(Iterable<Relation> originalIterable) { 176 super(originalIterable); 177 } 178 179 @Override 180 protected boolean accept(Relation relation) { 181 boolean complete = true; 182 for (org.openstreetmap.josm.data.osm.RelationMember member : relation.getMembers()) { 183 if (member.getMember() == null || member.getMember().isDeleted() || member.getMember().isIncomplete()) { 184 complete = false; 185 } 186 } 187 return complete && super.accept(relation); 188 } 189 } 190 191 static class RelationMemberImpl { 192 private final String role; 193 private final Object member; 194 public RelationMemberImpl(org.openstreetmap.josm.data.osm.RelationMember originalMember) { 195 this.role = originalMember.getRole(); 196 this.member = originalMember.getMember(); 197 } 198 public String getRole() { 199 return role; 200 } 201 public Object getMember() { 202 return member; 203 } 204 } 205 206 private final Set<DataSourceObserver> observers = new HashSet<DataSourceObserver>(); 207 208 public void addObserver(DataSourceObserver observer) { 209 observers.add(observer); 210 } 211 212 public void deleteObserver(DataSourceObserver observer) { 213 observers.remove(observer); 214 } 215 215 216 216 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/data/JOSMTransitionStructure.java
r19216 r23189 17 17 public class JOSMTransitionStructure extends GenericTransitionStructure<Node, Way, Relation, RelationMember> { 18 18 19 19 private static final JOSMDataSource DATA_SOURCE = new JOSMDataSource(); 20 20 21 22 21 public JOSMTransitionStructure(AccessParameters accessParameters, AccessRuleset ruleset, 22 Collection<RoadPropertyType<?>> properties) { 23 23 24 25 26 24 super(accessParameters, ruleset, 25 DATA_SOURCE, 26 properties); 27 27 28 28 } 29 29 30 31 32 33 30 /** causes an update (as if the DataSource had noticed a change) */ 31 public void forceUpdate() { 32 super.update(DATA_SOURCE); 33 } 34 34 35 35 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/dialogs/AccessParameterDialog.java
r16520 r23189 38 38 public class AccessParameterDialog extends JDialog { 39 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 40 public static interface BookmarkAction { 41 public void execute(String name, PreferenceAccessParameters parameters); 42 } 43 44 /** 45 * map that contains all float value vehicle properties (as those can be treated uniformly) 46 * and their labels 47 */ 48 private static final Map<VehiclePropertyType<Float>, String> FLOAT_PROPERTIES; 49 50 static { 51 FLOAT_PROPERTIES = new LinkedHashMap<VehiclePropertyType<Float>, String>(); 52 FLOAT_PROPERTIES.put(VehiclePropertyTypes.HEIGHT, "height (m)"); 53 FLOAT_PROPERTIES.put(VehiclePropertyTypes.WIDTH, "width (m)"); 54 FLOAT_PROPERTIES.put(VehiclePropertyTypes.LENGTH, "length (m)"); 55 FLOAT_PROPERTIES.put(VehiclePropertyTypes.SPEED, "speed (km/h)"); 56 FLOAT_PROPERTIES.put(VehiclePropertyTypes.WEIGHT, "weight (t)"); 57 FLOAT_PROPERTIES.put(VehiclePropertyTypes.AXLELOAD, "axleload (t)"); 58 } 59 60 private static final Collection<Character> FORBIDDEN_CHARS = 61 Arrays.asList(',', ';', '{', '}', '=', '|'); 62 63 private class BookmarkNamePanel extends JPanel { 64 65 private final JTextField bookmarkNameTextField; 66 67 public BookmarkNamePanel(String initialName) { 68 super(); 69 this.setBorder(BorderFactory.createTitledBorder("bookmark name")); 70 71 this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); 72 73 bookmarkNameTextField = new JTextField(initialName); 74 this.add(bookmarkNameTextField); 75 76 } 77 78 public String getBookmarkName() { 79 80 String name = bookmarkNameTextField.getText(); 81 82 if (existingBookmarkNames.contains(name)) { 83 JOptionPane.showMessageDialog(this, "Bookmark name already exists!"); 84 return null; 85 } 86 87 for (char nameChar : name.toCharArray()) { 88 if (FORBIDDEN_CHARS.contains(nameChar)) { 89 JOptionPane.showMessageDialog(this, "Bookmark name must not contain '" + 90 nameChar + "'!"); 91 return null; 92 } 93 } 94 95 return name; 96 } 97 } 98 99 private static class AccessClassPanel extends JPanel { 100 101 private final JTextField accessClassTextField; 102 103 public AccessClassPanel(PreferenceAccessParameters initialParameters) { 104 super(); 105 this.setBorder(BorderFactory.createTitledBorder("access class")); 106 107 this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); 108 109 accessClassTextField = new JTextField(initialParameters.getAccessClass()); 110 this.add(accessClassTextField); 111 112 } 113 114 public String getAccessClass() { 115 116 String name = accessClassTextField.getText(); 117 118 for (char nameChar : name.toCharArray()) { 119 if (FORBIDDEN_CHARS.contains(nameChar)) { 120 JOptionPane.showMessageDialog(this, "Access class must not contain '" + 121 nameChar + "'!"); 122 return null; 123 } 124 } 125 126 return name; 127 } 128 } 129 130 private static class AccessTypesPanel extends JPanel { 131 132 private static final int COLS = 4; 133 134 private final Map<AccessType, JCheckBox> accessTypeCheckBoxes = 135 new EnumMap<AccessType, JCheckBox>(AccessType.class); 136 137 public AccessTypesPanel(PreferenceAccessParameters initialParameters) { 138 super(); 139 this.setBorder(BorderFactory.createTitledBorder("access types")); 140 141 this.setLayout( 142 new GridLayout(((COLS-1 + AccessType.values().length) / COLS), COLS)); 143 144 for (AccessType accessType : AccessType.values()) { 145 JCheckBox checkBox = new JCheckBox(accessType.toString()); 146 checkBox.setSelected(initialParameters.getAccessTypeUsable(accessType)); 147 accessTypeCheckBoxes.put(accessType, checkBox); 148 this.add(checkBox); 149 } 150 151 } 152 153 public Collection<AccessType> getUsableAccessTypes() { 154 155 Collection<AccessType> usableAccessTypes = new LinkedList<AccessType>(); 156 157 for (AccessType accessType : AccessType.values()) { 158 if (accessTypeCheckBoxes.get(accessType).isSelected()) { 159 usableAccessTypes.add(accessType); 160 } 161 } 162 163 return usableAccessTypes; 164 } 165 } 166 167 private static class VehiclePropertiesPanel extends JPanel { 168 169 private static final int COLS = 2; 170 171 private final Map<VehiclePropertyType<Float>, JTextField> floatPropertyTextFields = 172 new HashMap<VehiclePropertyType<Float>, JTextField>(); 173 174 public VehiclePropertiesPanel(PreferenceAccessParameters initialParameters) { 175 super(); 176 this.setBorder(BorderFactory.createTitledBorder("vehicle properties")); 177 178 this.setLayout(new GridLayout(((COLS-1 + FLOAT_PROPERTIES.size()) / COLS), 179 2*COLS)); 180 181 for (VehiclePropertyType<Float> vehicleProperty : FLOAT_PROPERTIES.keySet()) { 182 183 JLabel label = new JLabel(FLOAT_PROPERTIES.get(vehicleProperty)); 184 this.add(label); 185 186 JTextField textField = new JTextField(); 187 188 String vehiclePropertyString = 189 initialParameters.getVehiclePropertyString(vehicleProperty); 190 if (vehiclePropertyString != null) { 191 textField.setText(vehiclePropertyString); 192 } 193 194 floatPropertyTextFields.put(vehicleProperty, textField); 195 this.add(textField); 196 } 197 198 } 199 200 public Map<VehiclePropertyType<?>, String> getVehiclePropertyStrings() { 201 202 Map<VehiclePropertyType<?>, String> vehiclePropertyStrings = 203 new HashMap<VehiclePropertyType<?>, String>(); 204 205 for (VehiclePropertyType<Float> vehicleProperty : floatPropertyTextFields.keySet()) { 206 String textFieldContent = floatPropertyTextFields.get(vehicleProperty).getText(); 207 if (textFieldContent.trim().length() > 0) { 208 vehiclePropertyStrings.put(vehicleProperty, textFieldContent); 209 } 210 } 211 212 return vehiclePropertyStrings; 213 } 214 } 215 216 private static class RoadQualityPanel extends JPanel { 217 218 private JTextField inclineUpTextField; 219 private JTextField inclineDownTextField; 220 private JTextField surfaceTextField; 221 private JTextField tracktypeTextField; 222 223 public RoadQualityPanel(PreferenceAccessParameters initialParameters) { 224 super(); 225 this.setBorder(BorderFactory.createTitledBorder("road requirements")); 226 227 228 this.setLayout(new GridLayout(4, 2)); 229 230 /* incline up */ 231 { 232 JLabel inclineUpLabel = new JLabel("max. incline up (%, pos.)"); 233 inclineUpLabel.setToolTipText("maximum incline the vehicle can go up"); 234 this.add(inclineUpLabel); 235 236 inclineUpTextField = new JTextField(); 237 238 String vehiclePropertyString = 239 initialParameters.getVehiclePropertyString(MAX_INCLINE_UP); 240 if (vehiclePropertyString != null) { 241 inclineUpTextField.setText(vehiclePropertyString); 242 } 243 inclineUpTextField.setToolTipText("maximum incline the vehicle can go up"); 244 245 this.add(inclineUpTextField); 246 } 247 248 /* incline down */ 249 { 250 JLabel inclineDownLabel = new JLabel("max. incline down (%, pos.)"); 251 inclineDownLabel.setToolTipText("maximum incline the vehicle can go down"); 252 this.add(inclineDownLabel); 253 254 inclineDownTextField = new JTextField(); 255 256 String vehiclePropertyString = 257 initialParameters.getVehiclePropertyString(MAX_INCLINE_DOWN); 258 if (vehiclePropertyString != null) { 259 inclineDownTextField.setText(vehiclePropertyString); 260 } 261 inclineDownTextField.setToolTipText("maximum incline the vehicle can go down"); 262 263 this.add(inclineDownTextField); 264 } 265 266 /* surface */ 267 { 268 JLabel surfaceLabel = new JLabel("surface blacklist"); 269 surfaceLabel.setToolTipText("list of surfaces the vehicle cannot use, " 270 + "values are separated by semicolons (;)"); 271 this.add(surfaceLabel); 272 273 surfaceTextField = new JTextField(); 274 275 String vehiclePropertyString = 276 initialParameters.getVehiclePropertyString(SURFACE_BLACKLIST); 277 278 if (vehiclePropertyString != null) { 279 surfaceTextField.setText(vehiclePropertyString); 280 } 281 282 surfaceTextField.setToolTipText("list of surfaces the vehicle cannot use, " 283 + "values are separated by semicolons (;)"); 284 285 this.add(surfaceTextField); 286 } 287 288 /* tracktype */ 289 { 290 JLabel tracktypeLabel = new JLabel("max. tracktype grade"); 291 tracktypeLabel.setToolTipText("worst tracktype (1-5) the vehicle can still use," 292 + " 0 for none"); 293 this.add(tracktypeLabel); 294 295 tracktypeTextField = new JTextField(); 296 297 String vehiclePropertyString = 298 initialParameters.getVehiclePropertyString(MAX_TRACKTYPE); 299 if (vehiclePropertyString != null) { 300 tracktypeTextField.setText(vehiclePropertyString); 301 } 302 tracktypeTextField.setToolTipText("worst tracktype (1-5) the vehicle can still use," 303 + " 0 for none"); 304 305 this.add(tracktypeTextField); 306 } 307 308 } 309 310 public Map<VehiclePropertyType<?>, String> getVehiclePropertyStrings() { 311 312 Map<VehiclePropertyType<?>, String> vehiclePropertyStrings = 313 new HashMap<VehiclePropertyType<?>, String>(); 314 315 String incUpString = inclineUpTextField.getText(); 316 if (incUpString.trim().length() > 0) { 317 vehiclePropertyStrings.put(MAX_INCLINE_UP, incUpString); 318 } 319 320 String incDownString = inclineDownTextField.getText(); 321 if (incDownString.trim().length() > 0) { 322 vehiclePropertyStrings.put(MAX_INCLINE_DOWN, incDownString); 323 } 324 325 String surfaceString = surfaceTextField.getText(); 326 if (surfaceString.trim().length() > 0) { 327 vehiclePropertyStrings.put(SURFACE_BLACKLIST, surfaceString); 328 } 329 330 String tracktypeString = tracktypeTextField.getText(); 331 if (tracktypeString.trim().length() > 0) { 332 vehiclePropertyStrings.put(MAX_TRACKTYPE, tracktypeString); 333 } 334 335 return vehiclePropertyStrings; 336 } 337 } 338 339 private class OkCancelPanel extends JPanel { 340 341 public OkCancelPanel() { 342 343 new BoxLayout(this, BoxLayout.X_AXIS); 344 345 JButton okButton = new JButton(existingBookmark?"Change bookmark":"Create bookmark"); 346 okButton.addActionListener(new ActionListener() { 347 public void actionPerformed(ActionEvent e) { 348 String bookmarkName = bookmarkNamePanel.getBookmarkName(); 349 if (bookmarkName != null) { 350 PreferenceAccessParameters parameters = getAccessParameters(); 351 if (parameters != null) { 352 okAction.execute(bookmarkName, parameters); 353 AccessParameterDialog.this.dispose(); 354 } 355 } 356 } 357 }); 358 this.add(okButton); 359 360 JButton cancelButton = new JButton("Cancel"); 361 cancelButton.addActionListener(new ActionListener() { 362 public void actionPerformed(ActionEvent e) { 363 AccessParameterDialog.this.dispose(); 364 } 365 }); 366 this.add(cancelButton); 367 368 } 369 370 } 371 372 private boolean existingBookmark = false; 373 private final Collection<String> existingBookmarkNames; 374 375 private final BookmarkAction okAction; 376 377 private final BookmarkNamePanel bookmarkNamePanel; 378 private final AccessClassPanel accessClassPanel; 379 private final AccessTypesPanel accessTypesPanel; 380 private final VehiclePropertiesPanel vehiclePropertiesPanel; 381 private final RoadQualityPanel roadQualityPanel; 382 383 public AccessParameterDialog(final Frame owner, boolean existingBookmark, String initialName, 384 Collection<String> existingBookmarkNames, 385 PreferenceAccessParameters initialAccessParameters, BookmarkAction okAction) { 386 super(owner, "edit access parameters", true); 387 388 this.existingBookmark = existingBookmark; 389 this.existingBookmarkNames = existingBookmarkNames; 390 this.okAction = okAction; 391 392 GridBagLayout layout = new GridBagLayout(); 393 this.setLayout(layout); 394 395 GridBagConstraints gbc = new GridBagConstraints(); 396 gbc.gridx = 0; 397 gbc.weighty = 1; 398 gbc.fill = GridBagConstraints.BOTH; 399 400 bookmarkNamePanel = new BookmarkNamePanel(initialName); 401 gbc.gridy = 0; 402 layout.setConstraints(bookmarkNamePanel, gbc); 403 this.add(bookmarkNamePanel); 404 405 accessClassPanel = new AccessClassPanel(initialAccessParameters); 406 gbc.gridy = 1; 407 layout.setConstraints(accessClassPanel, gbc); 408 this.add(accessClassPanel); 409 410 accessTypesPanel = new AccessTypesPanel(initialAccessParameters); 411 gbc.gridy = 2; 412 layout.setConstraints(accessTypesPanel, gbc); 413 this.add(accessTypesPanel); 414 415 vehiclePropertiesPanel = new VehiclePropertiesPanel(initialAccessParameters); 416 gbc.gridy = 3; 417 layout.setConstraints(vehiclePropertiesPanel, gbc); 418 this.add(vehiclePropertiesPanel); 419 420 roadQualityPanel = new RoadQualityPanel(initialAccessParameters); 421 gbc.gridy = 4; 422 layout.setConstraints(roadQualityPanel, gbc); 423 this.add(roadQualityPanel); 424 425 JPanel okCancelPanel = new OkCancelPanel(); 426 gbc.gridy = 5; 427 gbc.weighty = 0; 428 gbc.fill = GridBagConstraints.HORIZONTAL; 429 layout.setConstraints(okCancelPanel, gbc); 430 this.add(okCancelPanel); 431 432 this.pack(); 433 } 434 435 private PreferenceAccessParameters getAccessParameters() { 436 437 String accessClass = accessClassPanel.getAccessClass(); 438 Collection<AccessType> usableAccessTypes = accessTypesPanel.getUsableAccessTypes(); 439 Map<VehiclePropertyType<?>, String> vehiclePropertyStrings = 440 vehiclePropertiesPanel.getVehiclePropertyStrings(); 441 Map<VehiclePropertyType<?>, String> additionalVehiclePropertyStrings = 442 roadQualityPanel.getVehiclePropertyStrings(); 443 444 if (accessClass != null && usableAccessTypes != null && vehiclePropertyStrings != null 445 && additionalVehiclePropertyStrings != null) { 446 447 vehiclePropertyStrings.putAll(additionalVehiclePropertyStrings); 448 449 try { 450 return new PreferenceAccessParameters(accessClass, usableAccessTypes, vehiclePropertyStrings); 451 } catch (PropertyValueSyntaxException e) { 452 JOptionPane.showMessageDialog(this, e.getMessage()); 453 return null; 454 } 455 456 } else { 457 return null; 458 } 459 } 460 460 461 461 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/dialogs/GraphViewDialog.java
r16520 r23189 44 44 public class GraphViewDialog extends ToggleDialog implements Observer { 45 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 46 private static final int HEIGHT = 150; 47 48 /** map from labels to available color schemes */ 49 private final LinkedHashMap<String, ColorScheme> availableColorSchemes; 50 51 52 private final GraphViewPreferences preferences; 53 private final GraphViewPlugin plugin; 54 55 private final JComboBox rulesetComboBox; 56 private final JComboBox bookmarkComboBox; 57 private final JComboBox colorSchemeComboBox; 58 59 /** 60 * list of ruleset files in the order currently used by rulesetComboBox; 61 * null if internal rulesets are used 62 */ 63 private List<File> rulesetFiles; 64 65 public GraphViewDialog(final GraphViewPlugin plugin) { 66 67 super("Graph View Dialog", "graphview", 68 "Open the dialog for graph view configuration.", (Shortcut)null, HEIGHT); 69 70 this.preferences = GraphViewPreferences.getInstance(); 71 this.plugin = plugin; 72 73 availableColorSchemes = new LinkedHashMap<String, ColorScheme>(); 74 75 availableColorSchemes.put("default", 76 new PreferencesColorScheme(preferences)); 77 availableColorSchemes.put("end nodes", 78 new EndNodeColorScheme(Color.GRAY, Color.RED, Color.GRAY)); 79 availableColorSchemes.put("maxspeed", 80 new MaxspeedColorScheme()); 81 availableColorSchemes.put("maxweight", 82 new MaxweightColorScheme()); 83 availableColorSchemes.put("maxheight", 84 new MaxheightColorScheme()); 85 availableColorSchemes.put("incline", 86 new InclineColorScheme()); 87 88 JPanel selectionPanel = new JPanel(); 89 GridBagLayout selectionLayout = new GridBagLayout(); 90 selectionPanel.setLayout(selectionLayout); 91 92 GridBagConstraints gbcLabel = new GridBagConstraints(); 93 gbcLabel.gridx = 0; 94 gbcLabel.anchor = GridBagConstraints.WEST; 95 gbcLabel.insets = new Insets(0, 5, 0, 5); 96 97 GridBagConstraints gbcComboBox = new GridBagConstraints(); 98 gbcComboBox.gridx = 1; 99 gbcComboBox.fill = GridBagConstraints.HORIZONTAL; 100 gbcComboBox.weightx = 1; 101 102 103 /* create ruleset label and combo box */ 104 { 105 JLabel rulesetLabel = new JLabel("ruleset:"); 106 gbcLabel.gridy = 0; 107 selectionLayout.setConstraints(rulesetLabel, gbcLabel); 108 selectionPanel.add(rulesetLabel); 109 110 rulesetComboBox = new JComboBox(); 111 rulesetComboBox.addActionListener(rulesetActionListener); 112 gbcComboBox.gridy = 0; 113 selectionLayout.setConstraints(rulesetComboBox, gbcComboBox); 114 selectionPanel.add(rulesetComboBox); 115 } 116 117 /* create bookmark label and combo box */ 118 { 119 JLabel bookmarkLabel = new JLabel("parameters:"); 120 gbcLabel.gridy = 1; 121 selectionLayout.setConstraints(bookmarkLabel, gbcLabel); 122 selectionPanel.add(bookmarkLabel); 123 124 bookmarkComboBox = new JComboBox(); 125 bookmarkComboBox.addActionListener(bookmarkActionListener); 126 gbcComboBox.gridy = 1; 127 selectionLayout.setConstraints(bookmarkComboBox, gbcComboBox); 128 selectionPanel.add(bookmarkComboBox); 129 } 130 131 /* create color scheme label and combo box */ 132 { 133 JLabel colorSchemeLabel = new JLabel("coloring:"); 134 gbcLabel.gridy = 2; 135 selectionLayout.setConstraints(colorSchemeLabel, gbcLabel); 136 selectionPanel.add(colorSchemeLabel); 137 138 colorSchemeComboBox = new JComboBox(); 139 for (String colorSchemeName : availableColorSchemes.keySet()) { 140 colorSchemeComboBox.addItem(colorSchemeName); 141 ColorScheme colorScheme = availableColorSchemes.get(colorSchemeName); 142 if (colorScheme.getClass().equals(preferences.getCurrentColorScheme().getClass())) { 143 colorSchemeComboBox.setSelectedItem(colorSchemeName); 144 } 145 } 146 colorSchemeComboBox.addActionListener(colorSchemeActionListener); 147 gbcComboBox.gridy = 2; 148 selectionLayout.setConstraints(colorSchemeComboBox, gbcComboBox); 149 selectionPanel.add(colorSchemeComboBox); 150 } 151 152 this.add(BorderLayout.CENTER, selectionPanel); 153 154 155 JPanel buttonPanel = new JPanel(); 156 JButton showLayerButton = new JButton("create/update graph"); 157 showLayerButton.addActionListener(new ActionListener() { 158 public void actionPerformed(ActionEvent e) { 159 plugin.createGraphViewLayer(); 160 } 161 }); 162 buttonPanel.add(showLayerButton); 163 164 this.add(BorderLayout.SOUTH, buttonPanel); 165 166 updateSelections(); 167 this.preferences.addObserver(this); 168 169 } 170 171 private final ActionListener rulesetActionListener = new ActionListener() { 172 public void actionPerformed(ActionEvent e) { 173 if (rulesetComboBox.getSelectedItem() != null) { 174 int selectedRulesetIndex = rulesetComboBox.getSelectedIndex(); 175 if (rulesetFiles != null) { 176 File selectedRulesetFile = rulesetFiles.get(selectedRulesetIndex); 177 preferences.setCurrentRulesetFile(selectedRulesetFile); 178 preferences.distributeChanges(); 179 plugin.updateGraphViewLayer(); 180 } else { 181 if (selectedRulesetIndex < InternalRuleset.values().length) { 182 InternalRuleset selectedIRR = InternalRuleset.values()[selectedRulesetIndex]; 183 preferences.setCurrentInternalRuleset(selectedIRR); 184 preferences.distributeChanges(); 185 plugin.updateGraphViewLayer(); 186 } 187 } 188 } 189 } 190 }; 191 192 private final ActionListener bookmarkActionListener = new ActionListener() { 193 public void actionPerformed(ActionEvent e) { 194 String selectedBookmarkName = (String)bookmarkComboBox.getSelectedItem(); 195 if (selectedBookmarkName != null) { 196 preferences.setCurrentParameterBookmarkName(selectedBookmarkName); 197 preferences.distributeChanges(); 198 plugin.updateGraphViewLayer(); 199 } 200 } 201 }; 202 203 private final ActionListener colorSchemeActionListener = new ActionListener() { 204 public void actionPerformed(ActionEvent e) { 205 assert availableColorSchemes.containsKey(colorSchemeComboBox.getSelectedItem()); 206 String colorSchemeLabel = (String)colorSchemeComboBox.getSelectedItem(); 207 preferences.setCurrentColorScheme(availableColorSchemes.get(colorSchemeLabel)); 208 preferences.distributeChanges(); 209 plugin.repaintGraphViewLayer(); 210 } 211 }; 212 213 public void update(Observable observable, Object param) { 214 if (observable == preferences) { 215 updateSelections(); 216 } 217 } 218 219 protected void updateSelections() { 220 221 /* update rulesets */ 222 223 rulesetComboBox.removeActionListener(rulesetActionListener); 224 225 if (preferences.getUseInternalRulesets()) { 226 227 rulesetFiles = null; 228 229 rulesetComboBox.removeAllItems(); 230 for (int i=0; i < InternalRuleset.values().length; i++) { 231 InternalRuleset ruleset = InternalRuleset.values()[i]; 232 rulesetComboBox.addItem(ruleset.toString()); 233 if (ruleset == preferences.getCurrentInternalRuleset()) { 234 rulesetComboBox.setSelectedIndex(i); 235 } 236 } 237 238 if (preferences.getCurrentInternalRuleset() == null) { 239 rulesetComboBox.addItem(""); 240 rulesetComboBox.setSelectedIndex(InternalRuleset.values().length); 241 } 242 243 } else { 244 245 rulesetFiles = new LinkedList<File>(); 246 247 File[] filesInRulesetFolder = preferences.getRulesetFolder().listFiles(); 248 249 if (filesInRulesetFolder != null) { 250 for (File possibleRulesetFile : filesInRulesetFolder) { 251 try { 252 AccessRulesetReader.readAccessRuleset(new FileInputStream(possibleRulesetFile)); 253 rulesetFiles.add(possibleRulesetFile); 254 } catch (IOException ioe) { 255 //don't add to rulesetFiles 256 } 257 } 258 } 259 260 Collections.sort(rulesetFiles); 261 262 rulesetComboBox.removeAllItems(); 263 for (int i=0; i < rulesetFiles.size(); i++) { 264 File rulesetFile = rulesetFiles.get(i); 265 rulesetComboBox.addItem(rulesetFile.getName()); 266 if (rulesetFile.equals(preferences.getCurrentRulesetFile())) { 267 rulesetComboBox.setSelectedIndex(i); 268 } 269 } 270 271 } 272 273 rulesetComboBox.addActionListener(rulesetActionListener); 274 275 /* update bookmarks */ 276 277 bookmarkComboBox.removeActionListener(bookmarkActionListener); 278 279 String activeBookmarkName = preferences.getCurrentParameterBookmarkName(); 280 Set<String> bookmarkNames = new HashSet<String>(preferences.getParameterBookmarks().keySet()); 281 282 bookmarkComboBox.removeAllItems(); 283 for (String bookmarkName : bookmarkNames) { 284 bookmarkComboBox.addItem(bookmarkName); 285 if (bookmarkName.equals(activeBookmarkName)) { 286 bookmarkComboBox.setSelectedItem(bookmarkName); 287 } 288 } 289 290 bookmarkComboBox.addActionListener(bookmarkActionListener); 291 292 } 293 293 294 294 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/dialogs/GraphViewPreferenceEditor.java
r19292 r23189 33 33 public class GraphViewPreferenceEditor implements PreferenceSetting { 34 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 35 private File rulesetFolder; 36 private Map<String, PreferenceAccessParameters> parameterBookmarks; 37 38 private JPanel preferencePanel; 39 40 private JCheckBox internalRulesetCheckBox; 41 private JLabel rulesetFolderLabel; 42 private JTextField rulesetFolderTextField; 43 private JButton selectRulesetFolderButton; 44 45 private JComboBox bookmarkComboBox; 46 private JButton editBookmarkButton; 47 private JButton deleteBookmarkButton; 48 49 private JCheckBox separateDirectionsCheckBox; 50 51 public void addGui(PreferenceTabbedPane gui) { 52 53 readPreferences(); 54 55 preferencePanel = gui.createPreferenceTab("graphview", "Graphview", 56 "Settings for the Graphview plugin that visualizes routing graphs."); 57 58 JPanel mainPanel = createMainPanel(); 59 60 preferencePanel.add(mainPanel, GBC.eol().fill(GBC.BOTH)); 61 62 updateVehiclePanel(GraphViewPreferences.getInstance().getCurrentParameterBookmarkName()); 63 64 } 65 66 /** 67 * creates local versions of preference information 68 * that will only be written to real preferences if the OK button is pressed 69 */ 70 private void readPreferences() { 71 72 GraphViewPreferences preferences = GraphViewPreferences.getInstance(); 73 74 rulesetFolder = preferences.getRulesetFolder(); 75 76 parameterBookmarks = 77 new HashMap<String, PreferenceAccessParameters>(preferences.getParameterBookmarks()); 78 79 } 80 81 private JPanel createMainPanel() { 82 83 JPanel mainPanel = new JPanel(); 84 85 GridBagLayout mainLayout = new GridBagLayout(); 86 mainPanel.setLayout(mainLayout); 87 88 GridBagConstraints constraints = new GridBagConstraints(); 89 constraints.fill = GridBagConstraints.HORIZONTAL; 90 constraints.weightx = 1; 91 constraints.gridx = 0; 92 93 { 94 JPanel rulesetPanel = createRulesetPanel(); 95 constraints.gridy = 0; 96 mainLayout.setConstraints(rulesetPanel, constraints); 97 mainPanel.add(rulesetPanel); 98 } { 99 JPanel vehiclePanel = createVehiclePanel(); 100 constraints.gridy = 1; 101 mainLayout.setConstraints(vehiclePanel, constraints); 102 mainPanel.add(vehiclePanel); 103 } { 104 JPanel visualizationPanel = createVisualizationPanel(); 105 constraints.gridy = 2; 106 mainLayout.setConstraints(visualizationPanel, constraints); 107 mainPanel.add(visualizationPanel); 108 } 109 110 mainPanel.add(GBC.glue(0, 0)); 111 112 return mainPanel; 113 114 } 115 116 private JPanel createRulesetPanel() { 117 118 JPanel rulesetPanel = new JPanel(); 119 rulesetPanel.setBorder(BorderFactory.createTitledBorder("ruleset")); 120 rulesetPanel.setLayout(new BoxLayout(rulesetPanel, BoxLayout.Y_AXIS)); 121 122 internalRulesetCheckBox = new JCheckBox("use built-in rulesets"); 123 internalRulesetCheckBox.setSelected(GraphViewPreferences.getInstance().getUseInternalRulesets()); 124 internalRulesetCheckBox.addActionListener(internalRulesetActionListener); 125 rulesetPanel.add(internalRulesetCheckBox); 126 127 rulesetFolderLabel = new JLabel("external ruleset directory:"); 128 rulesetPanel.add(rulesetFolderLabel); 129 130 rulesetFolderTextField = new JTextField(); 131 rulesetFolderTextField.setText(rulesetFolder.getPath()); 132 rulesetFolderTextField.setEditable(false); 133 rulesetPanel.add(rulesetFolderTextField); 134 135 selectRulesetFolderButton = new JButton("select directory"); 136 selectRulesetFolderButton.addActionListener(selectRulesetFolderActionListener); 137 rulesetPanel.add(selectRulesetFolderButton); 138 139 updateRulesetPanel(); 140 141 return rulesetPanel; 142 } 143 144 private JPanel createVehiclePanel() { 145 146 JPanel vehiclePanel = new JPanel(); 147 vehiclePanel.setBorder(BorderFactory.createTitledBorder("vehicle")); 148 vehiclePanel.setLayout(new BoxLayout(vehiclePanel, BoxLayout.Y_AXIS)); 149 150 bookmarkComboBox = new JComboBox(); 151 vehiclePanel.add(bookmarkComboBox); 152 153 JPanel buttonPanel = new JPanel(); 154 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); 155 156 JButton createButton = new JButton("create"); 157 createButton.addActionListener(createVehicleActionListener); 158 buttonPanel.add(createButton); 159 160 editBookmarkButton = new JButton("edit"); 161 editBookmarkButton.addActionListener(editVehicleActionListener); 162 buttonPanel.add(editBookmarkButton); 163 164 deleteBookmarkButton = new JButton("delete"); 165 deleteBookmarkButton.addActionListener(deleteVehicleActionListener); 166 buttonPanel.add(deleteBookmarkButton); 167 168 JButton restoreDefaultsButton = new JButton("restore defaults"); 169 restoreDefaultsButton.addActionListener(restoreVehicleDefaultsActionListener); 170 buttonPanel.add(restoreDefaultsButton); 171 172 vehiclePanel.add(buttonPanel); 173 174 return vehiclePanel; 175 } 176 177 private JPanel createVisualizationPanel() { 178 179 JPanel visualizationPanel = new JPanel(); 180 visualizationPanel.setBorder(BorderFactory.createTitledBorder("visualization")); 181 visualizationPanel.setLayout(new BoxLayout(visualizationPanel, BoxLayout.Y_AXIS)); 182 183 separateDirectionsCheckBox = new JCheckBox("draw directions separately"); 184 separateDirectionsCheckBox.setSelected(GraphViewPreferences.getInstance().getSeparateDirections()); 185 visualizationPanel.add(separateDirectionsCheckBox); 186 187 return visualizationPanel; 188 } 189 190 public boolean ok() { 191 192 GraphViewPreferences preferences = GraphViewPreferences.getInstance(); 193 194 preferences.setUseInternalRulesets(internalRulesetCheckBox.isSelected()); 195 preferences.setRulesetFolder(rulesetFolder); 196 197 preferences.setParameterBookmarks(parameterBookmarks); 198 199 String selectedBookmarkName = (String)bookmarkComboBox.getSelectedItem(); 200 preferences.setCurrentParameterBookmarkName(selectedBookmarkName); 201 202 preferences.setSeparateDirections(separateDirectionsCheckBox.isSelected()); 203 204 preferences.distributeChanges(); 205 206 return false; 207 } 208 209 private final ActionListener internalRulesetActionListener = new ActionListener() { 210 public void actionPerformed(ActionEvent e) { 211 updateRulesetPanel(); 212 } 213 }; 214 215 private final ActionListener selectRulesetFolderActionListener = new ActionListener() { 216 public void actionPerformed(ActionEvent e) { 217 218 File initialFCDirectory = rulesetFolder; 219 if (rulesetFolder.getParentFile() != null) { 220 initialFCDirectory = rulesetFolder.getParentFile(); 221 } 222 223 final JFileChooser fc = new JFileChooser(); 224 fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 225 fc.setCurrentDirectory(initialFCDirectory); 226 227 int returnVal = fc.showOpenDialog(preferencePanel); 228 229 if (returnVal == JFileChooser.APPROVE_OPTION) { 230 rulesetFolder = fc.getSelectedFile(); 231 rulesetFolderTextField.setText(rulesetFolder.getPath()); 232 } 233 234 } 235 }; 236 237 private final ActionListener createVehicleActionListener = new ActionListener() { 238 public void actionPerformed(ActionEvent e) { 239 240 PreferenceAccessParameters defaultBookmarkParameters = 241 GraphViewPreferenceDefaults.createDefaultBookmarkAccessParameters(); 242 243 AccessParameterDialog apd = new AccessParameterDialog( 244 null, 245 false, 246 "new bookmark", 247 parameterBookmarks.keySet(), 248 defaultBookmarkParameters, 249 new BookmarkAction() { 250 public void execute(String name, PreferenceAccessParameters parameters) { 251 parameterBookmarks.put(name, parameters); 252 updateVehiclePanel(name); 253 } 254 }); 255 256 apd.setVisible(true); 257 } 258 }; 259 260 private final ActionListener editVehicleActionListener = new ActionListener() { 261 public void actionPerformed(ActionEvent e) { 262 if (bookmarkComboBox.getSelectedItem() != null) { 263 264 final String selectedBookmarkName = (String)bookmarkComboBox.getSelectedItem(); 265 PreferenceAccessParameters parameters = 266 parameterBookmarks.get(selectedBookmarkName); 267 268 Collection<String> otherBookmarkNames = new LinkedList<String>(); 269 for (String bookmarkName : parameterBookmarks.keySet()) { 270 if (!bookmarkName.equals(selectedBookmarkName)) { 271 otherBookmarkNames.add(bookmarkName); 272 } 273 } 274 275 AccessParameterDialog apd = new AccessParameterDialog( 276 null, 277 true, 278 selectedBookmarkName, 279 otherBookmarkNames, 280 parameters, 281 new BookmarkAction() { 282 public void execute(String name, PreferenceAccessParameters parameters) { 283 parameterBookmarks.remove(selectedBookmarkName); 284 parameterBookmarks.put(name, parameters); 285 updateVehiclePanel(name); 286 } 287 }); 288 289 apd.setVisible(true); 290 } 291 292 } 293 }; 294 295 private final ActionListener deleteVehicleActionListener = new ActionListener() { 296 public void actionPerformed(ActionEvent e) { 297 if (bookmarkComboBox.getSelectedItem() != null) { 298 299 String selectedBookmarkName = (String)bookmarkComboBox.getSelectedItem(); 300 301 int userChoice = JOptionPane.showConfirmDialog( 302 preferencePanel, 303 "Really delete \"" + selectedBookmarkName + "\"?", 304 "Bookmark deletion", 305 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 306 307 if (userChoice == JOptionPane.YES_OPTION) { 308 parameterBookmarks.remove(selectedBookmarkName); 309 updateVehiclePanel(null); 310 } 311 312 } 313 } 314 }; 315 316 private final ActionListener restoreVehicleDefaultsActionListener = new ActionListener() { 317 public void actionPerformed(ActionEvent e) { 318 319 int userChoice = JOptionPane.showConfirmDialog( 320 preferencePanel, 321 "Really restore default bookmarks?\n" 322 + "All manually added or edited bookmarks will be lost!", 323 "Bookmark reset", 324 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 325 326 if (userChoice == JOptionPane.YES_OPTION) { 327 parameterBookmarks.clear(); 328 parameterBookmarks.putAll( 329 GraphViewPreferenceDefaults.createDefaultAccessParameterBookmarks()); 330 updateVehiclePanel(null); 331 } 332 333 } 334 }; 335 336 private void updateRulesetPanel() { 337 338 rulesetFolderLabel.setEnabled(!internalRulesetCheckBox.isSelected()); 339 rulesetFolderTextField.setEnabled(!internalRulesetCheckBox.isSelected()); 340 selectRulesetFolderButton.setEnabled(!internalRulesetCheckBox.isSelected()); 341 342 } 343 344 private void updateVehiclePanel(String selectedBookmarkName) { 345 346 bookmarkComboBox.removeAllItems(); 347 for (String bookmarkName : parameterBookmarks.keySet()) { 348 bookmarkComboBox.addItem(bookmarkName); 349 } 350 351 if (selectedBookmarkName == null) { 352 if (bookmarkComboBox.getItemCount() > 0) { 353 bookmarkComboBox.setSelectedIndex(0); 354 } 355 } else { 356 bookmarkComboBox.setSelectedItem(selectedBookmarkName); 357 } 358 359 editBookmarkButton.setEnabled(parameterBookmarks.size() > 0); 360 deleteBookmarkButton.setEnabled(parameterBookmarks.size() > 0); 361 362 } 363 363 364 364 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/layer/GraphViewLayer.java
r22547 r23189 46 46 public class GraphViewLayer extends Layer implements LayerChangeListener, WayGraphObserver { 47 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 48 private static final int NODE_RADIUS = 5; 49 50 /** 51 * offset from real position if {@link GraphViewPreferences#getSeparateDirections()} is active, 52 * causes the graph nodes for the two directions to be visually distinguishable. 53 * Positive values move "forward" direction to the right. 54 */ 55 private static final double DIRECTIONAL_OFFSET = 20; 56 57 private static final double OFFSET_ANGLE = 0.5 * Math.PI; 58 59 private static final double MIN_QUAD_DISTANCE_FOR_OFFSET = 4; 60 61 private static final boolean CONNECT_ALL_NODE_PAIRS = false; 62 63 /** an arrow head that points along the x-axis to (0,0) */ 64 private static final Shape ARROW_HEAD; 65 66 static { 67 68 Polygon head = new Polygon(); 69 70 head.addPoint( 0, 0); 71 head.addPoint(-15, +4); 72 head.addPoint(-15, -4); 73 74 ARROW_HEAD = head; 75 } 76 77 private WayGraph wayGraph = null; 78 79 private ColorScheme colorScheme = null; 80 private NodePositioner nodePositioner = new NonMovingNodePositioner(); 81 82 public GraphViewLayer() { 83 super("Graph view"); 84 MapView.addLayerChangeListener(this); 85 } 86 87 /** sets the WayGraph that is to be displayed by this layer, may be null */ 88 public void setWayGraph(WayGraph wayGraph) { 89 if (this.wayGraph != null) { 90 this.wayGraph.deleteObserver(this); 91 } 92 this.wayGraph = wayGraph; 93 if (wayGraph != null) { 94 wayGraph.addObserver(this); 95 } 96 } 97 98 /** sets the ColorScheme that is to be used for choosing colors, may be null */ 99 public void setColorScheme(ColorScheme colorScheme) { 100 this.colorScheme = colorScheme; 101 Main.panel.repaint(); 102 } 103 104 /** 105 * sets the NodePositioner that is to be used for determining node placement, 106 * null will cause a {@link NonMovingNodePositioner} to be used. 107 */ 108 public void setNodePositioner(NodePositioner nodePositioner) { 109 this.nodePositioner = nodePositioner; 110 if (nodePositioner == null) { 111 this.nodePositioner = new NonMovingNodePositioner(); 112 } 113 Main.panel.repaint(); 114 } 115 116 @Override 117 public Icon getIcon() { 118 return ImageProvider.get("layer", "graphview"); 119 } 120 121 private void paintGraphNode(final GraphNode node, final Graphics g, final MapView mv) { 122 123 Color color = colorScheme != null ? colorScheme.getNodeColor(node) : Color.LIGHT_GRAY; 124 125 Point p = getNodePoint(node, mv); 126 g.setColor(color); 127 g.fillOval(p.x - NODE_RADIUS, p.y - NODE_RADIUS, 2 * NODE_RADIUS, 2 * NODE_RADIUS); 128 129 } 130 131 private void paintGraphEdge(final GraphEdge e, final Graphics2D g2D, final MapView mv) { 132 133 if (!CONNECT_ALL_NODE_PAIRS && GraphViewPreferences.getInstance().getSeparateDirections()) { 134 135 //don't paint edges between nodes from the same SegmentNode and simply inverted Segment 136 if (e.getStartNode().getSegmentNode() == e.getTargetNode().getSegmentNode() 137 && e.getStartNode().getSegment().getNode2() == e.getTargetNode().getSegment().getNode1() 138 && e.getStartNode().getSegment().getNode1() == e.getTargetNode().getSegment().getNode2()) { 139 return; 140 } 141 142 } 143 144 /* draw line(s) */ 145 146 g2D.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 147 148 List<Segment> edgeSegments = e.getPropertyValue(GraphEdgeSegments.PROPERTY); 149 150 if (edgeSegments.size() > 0) { 151 152 Segment firstSegment = edgeSegments.get(0); 153 Segment lastSegment = edgeSegments.get(edgeSegments.size() - 1); 154 155 //draw segments 156 157 for (Segment segment : edgeSegments) { 158 159 Color color = Color.WHITE; 160 if (colorScheme != null) { 161 color = colorScheme.getSegmentColor(segment); 162 } 163 g2D.setColor(color); 164 165 Point p1 = getNodePoint(segment.getNode1(), mv); 166 Point p2 = getNodePoint(segment.getNode2(), mv); 167 168 if (segment == firstSegment) { 169 p1 = getNodePoint(e.getStartNode(), mv); 170 } 171 if (segment == lastSegment) { 172 p2 = getNodePoint(e.getTargetNode(), mv); 173 } 174 175 g2D.draw(new Line2D.Float(p1.x, p1.y, p2.x, p2.y)); 176 177 } 178 179 } else { 180 181 g2D.setColor(Color.WHITE); 182 183 Point p1 = getNodePoint(e.getStartNode(), mv); 184 Point p2 = getNodePoint(e.getTargetNode(), mv); 185 186 g2D.draw(new Line2D.Float(p1.x, p1.y, p2.x, p2.y)); 187 188 } 189 190 /* draw arrow head (note: color of last segment is still set) */ 191 192 { 193 Point p1 = getNodePoint(e.getStartNode(), mv); 194 Point p2 = getNodePoint(e.getTargetNode(), mv); 195 196 if (edgeSegments.size() > 0) { 197 Segment lastSegment = edgeSegments.get(edgeSegments.size() - 1); 198 p1 = getNodePoint(lastSegment.getNode1(), mv); 199 } 200 201 double angle = angleFromXAxis(p1, p2); // angle between x-axis and [p1,p2] 202 Shape head = ARROW_HEAD; 203 head = AffineTransform.getRotateInstance(angle).createTransformedShape(head); 204 head = AffineTransform.getTranslateInstance(p2.x, p2.y).createTransformedShape(head); 205 206 g2D.fill(head); 207 208 } 209 } 210 211 private Point getNodePoint(GraphNode node, MapView mv) { 212 213 Point nodePoint = getNodePoint(nodePositioner.getPosition(node), mv); 214 215 if (GraphViewPreferences.getInstance().getSeparateDirections() 216 && !GraphUtil.isEndNode(node)) { 217 218 SegmentNode node1 = node.getSegment().getNode1(); 219 SegmentNode node2 = node.getSegment().getNode2(); 220 221 Point node1Point = getNodePoint(node1, mv); 222 Point node2Point = getNodePoint(node2, mv); 223 224 double segmentX = node2Point.getX() - node1Point.getX(); 225 double segmentY = node2Point.getY() - node1Point.getY(); 226 227 if (segmentX*segmentX + segmentY*segmentY >= MIN_QUAD_DISTANCE_FOR_OFFSET) { 228 229 double rotatedX = Math.cos(OFFSET_ANGLE) * segmentX - Math.sin(OFFSET_ANGLE) * segmentY; 230 double rotatedY = Math.sin(OFFSET_ANGLE) * segmentX + Math.cos(OFFSET_ANGLE) * segmentY; 231 232 double segmentLength = Math.sqrt(rotatedX * rotatedX + rotatedY * rotatedY); 233 234 double normalizedX = rotatedX / segmentLength; 235 double normalizedY = rotatedY / segmentLength; 236 237 nodePoint.x += DIRECTIONAL_OFFSET * normalizedX; 238 nodePoint.y += DIRECTIONAL_OFFSET * normalizedY; 239 240 } 241 242 } 243 244 return nodePoint; 245 } 246 private Point getNodePoint(SegmentNode node, MapView mv) { 247 LatLonCoords coords = new LatLonCoords(node.getLat(), node.getLon()); 248 return getNodePoint(coords, mv); 249 } 250 private Point getNodePoint(LatLonCoords coords, MapView mv) { 251 LatLon latLon = new LatLon(coords.getLat(), coords.getLon()); 252 EastNorth eastNorth = Main.proj.latlon2eastNorth(latLon); 253 return mv.getPoint(eastNorth); 254 } 255 256 /** 257 * calculates the angle between the x axis and a vector given by two points 258 * @param p1 first point for vector; != null 259 * @param p2 second point for vector; != null 260 * @return angle in radians, in range [-Pi .. +Pi] 261 */ 262 private double angleFromXAxis(Point p1, Point p2) { 263 assert p1 != null && p2 != null; 264 265 final float vecX = p2.x - p1.x; 266 final float vecY = p2.y - p1.y; 267 268 final float vecLength = (float)Math.sqrt(vecX*vecX + vecY*vecY); 269 270 final float dotProductVecAxis = vecX; 271 272 float angle = (float)Math.acos(dotProductVecAxis / vecLength); 273 274 if (p2.y < p1.y) { 275 angle = -angle; 276 } 277 278 assert -Math.PI*0.5 < angle && angle <= Math.PI*0.5; 279 280 return angle; 281 } 282 283 @Override 284 public void paint(final Graphics2D g, final MapView mv, Bounds bounds) { 285 if (wayGraph != null) { 286 287 for (GraphNode n : wayGraph.getNodes()) { 288 paintGraphNode(n, g, mv); 289 } 290 291 for (GraphEdge e : wayGraph.getEdges()) { 292 paintGraphEdge(e, g, mv); 293 } 294 295 } 296 297 } 298 299 @Override 300 public String getToolTipText() { 301 return "routing graph calculated by the GraphView plugin"; 302 } 303 304 @Override 305 public void mergeFrom(Layer from) { 306 throw new AssertionError("GraphView layer is not mergable"); 307 } 308 309 @Override 310 public boolean isMergable(Layer other) { 311 return false; 312 } 313 314 @Override 315 public void visitBoundingBox(BoundingXYVisitor v) { 316 } 317 318 @Override 319 public Object getInfoComponent() { 320 return getToolTipText(); 321 } 322 323 @Override 324 public Action[] getMenuEntries() { 325 return new Action[] { 326 LayerListDialog.getInstance().createShowHideLayerAction(), 327 LayerListDialog.getInstance().createDeleteLayerAction(), 328 SeparatorLayerAction.INSTANCE, 329 new RenameLayerAction(null, this), 330 SeparatorLayerAction.INSTANCE, 331 new LayerListPopup.InfoAction(this)}; 332 } 333 334 public void update(WayGraph wayGraph) { 335 assert wayGraph == this.wayGraph; 336 Main.panel.repaint(); 337 } 338 339 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 340 //do nothing 341 } 342 public void layerAdded(Layer newLayer) { 343 //do nothing 344 } 345 public void layerRemoved(Layer oldLayer) { 346 if (oldLayer == this) { 347 MapView.removeLayerChangeListener(this); 348 } 349 } 350 350 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/layer/PreferencesColorScheme.java
r16520 r23189 13 13 public class PreferencesColorScheme implements ColorScheme { 14 14 15 15 private final GraphViewPreferences preferences; 16 16 17 18 19 17 public PreferencesColorScheme(GraphViewPreferences preferences) { 18 this.preferences = preferences; 19 } 20 20 21 22 23 21 public Color getNodeColor(GraphNode node) { 22 return preferences.getNodeColor(); 23 } 24 24 25 26 27 25 public Color getSegmentColor(Segment segment) { 26 return preferences.getSegmentColor(); 27 } 28 28 29 29 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/GraphViewPreferenceDefaults.java
r16520 r23189 22 22 public final class GraphViewPreferenceDefaults { 23 23 24 25 24 /** prevents instantiation */ 25 private GraphViewPreferenceDefaults() { } 26 26 27 28 27 /** creates a default "empty" bookmark */ 28 public static PreferenceAccessParameters createDefaultBookmarkAccessParameters() { 29 29 30 31 30 Collection<AccessType> accessTypes = 31 Arrays.asList(UNDEFINED, YES, PERMISSIVE, DESIGNATED); 32 32 33 34 33 Map<VehiclePropertyType<?>, String> propertyStringMap = 34 new HashMap<VehiclePropertyType<?>, String>(); 35 35 36 37 38 39 40 36 try { 37 return new PreferenceAccessParameters("", accessTypes, propertyStringMap); 38 } catch (PropertyValueSyntaxException e) { 39 throw new AssertionError(e); 40 } 41 41 42 42 } 43 43 44 45 44 /** creates the default map of access parameter bookmarks */ 45 public static Map<String, PreferenceAccessParameters> createDefaultAccessParameterBookmarks() { 46 46 47 47 try { 48 48 49 50 49 Map<String, PreferenceAccessParameters> result = 50 new HashMap<String, PreferenceAccessParameters>(); 51 51 52 53 52 Collection<AccessType> accessTypes = 53 Arrays.asList(UNDEFINED, YES, PERMISSIVE, DESIGNATED); 54 54 55 56 57 58 55 /* create motorcar bookmark */ 56 { 57 Map<VehiclePropertyType<?>, String> propertyMap = 58 new HashMap<VehiclePropertyType<?>, String>(); 59 59 60 61 60 PreferenceAccessParameters accessParameters = 61 new PreferenceAccessParameters("motorcar", accessTypes, propertyMap); 62 62 63 64 63 result.put("motorcar", accessParameters); 64 } 65 65 66 67 68 69 70 66 /* create hgv bookmark */ 67 { 68 Map<VehiclePropertyType<?>, String> propertyMap = 69 new HashMap<VehiclePropertyType<?>, String>(); 70 propertyMap.put(VehiclePropertyTypes.WEIGHT, "3.5"); 71 71 72 73 72 PreferenceAccessParameters accessParameters = 73 new PreferenceAccessParameters("hgv", accessTypes, propertyMap); 74 74 75 76 75 result.put("hgv (3.5 t)", accessParameters); 76 } 77 77 78 79 80 81 78 /* create bicycle bookmark */ 79 { 80 Map<VehiclePropertyType<?>, String> propertyMap = 81 new HashMap<VehiclePropertyType<?>, String>(); 82 82 83 84 83 PreferenceAccessParameters accessParameters = 84 new PreferenceAccessParameters("bicycle", accessTypes, propertyMap); 85 85 86 87 86 result.put("bicycle", accessParameters); 87 } 88 88 89 90 91 92 89 /* create pedestrian bookmark */ 90 { 91 Map<VehiclePropertyType<?>, String> propertyMap = 92 new HashMap<VehiclePropertyType<?>, String>(); 93 93 94 95 94 PreferenceAccessParameters accessParameters = 95 new PreferenceAccessParameters("foot", accessTypes, propertyMap); 96 96 97 98 97 result.put("pedestrian", accessParameters); 98 } 99 99 100 100 return result; 101 101 102 103 104 105 102 } catch (PropertyValueSyntaxException e) { 103 throw new AssertionError(e); 104 } 105 } 106 106 107 108 109 107 public static File getDefaultRulesetFolder() { 108 return new File(System.getProperty("user.home")); 109 } 110 110 111 111 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/GraphViewPreferences.java
r16520 r23189 39 39 public class GraphViewPreferences extends Observable { 40 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 41 private static GraphViewPreferences instance; 42 43 /** 44 * returns the single instance of GraphViewPreferences. 45 * @param ignoreSyntaxErrors 46 * @return 47 */ 48 public static GraphViewPreferences getInstance() { 49 if (instance == null) { 50 instance = new GraphViewPreferences(); 51 } 52 return instance; 53 } 54 55 private boolean useInternalRulesets; 56 private File rulesetFolder; 57 private File currentRulesetFile; 58 private InternalRuleset currentInternalRuleset; 59 60 private String currentParameterBookmarkName; 61 private Map<String, PreferenceAccessParameters> parameterBookmarks; 62 63 private ColorScheme currentColorScheme; 64 private Color nodeColor; 65 private Color segmentColor; 66 67 private boolean separateDirections; 68 69 70 public synchronized boolean getUseInternalRulesets() { 71 return useInternalRulesets; 72 } 73 public synchronized void setUseInternalRulesets(boolean useInternalRulesets) { 74 this.useInternalRulesets = useInternalRulesets; 75 } 76 77 public synchronized File getRulesetFolder() { 78 return rulesetFolder; 79 } 80 public synchronized void setRulesetFolder(File rulesetFolder) { 81 this.rulesetFolder = rulesetFolder; 82 } 83 84 public synchronized File getCurrentRulesetFile() { 85 return currentRulesetFile; 86 } 87 public synchronized void setCurrentRulesetFile(File currentRulesetFile) { 88 this.currentRulesetFile = currentRulesetFile; 89 } 90 91 public synchronized InternalRuleset getCurrentInternalRuleset() { 92 return currentInternalRuleset; 93 } 94 public synchronized void setCurrentInternalRuleset(InternalRuleset internalRuleset) { 95 this.currentInternalRuleset = internalRuleset; 96 } 97 98 /** 99 * returns the name (map key) of the currently selected parameter bookmark 100 * or null if none is selected. 101 * If a name is returned, is has to be a key of the map returned by 102 * {@link #getParameterBookmarks()}. 103 */ 104 public synchronized String getCurrentParameterBookmarkName() { 105 assert parameterBookmarks.containsKey(currentParameterBookmarkName); 106 return currentParameterBookmarkName; 107 } 108 109 /** 110 * returns the access parameters of the currently selected parameter bookmark 111 * or null if none is selected. 112 */ 113 public synchronized AccessParameters getCurrentParameterBookmark() { 114 if (currentParameterBookmarkName == null) { 115 return null; 116 } else { 117 assert parameterBookmarks.containsKey(currentParameterBookmarkName); 118 return parameterBookmarks.get(currentParameterBookmarkName); 119 } 120 } 121 122 /** 123 * sets the active parameter bookmark using its name as an identifier 124 * @param currentParameters name of bookmark to set or null (no active bookmark). 125 * Non-null values must be keys of the map returned by 126 * {@link #getParameterBookmarks()}. 127 */ 128 public synchronized void setCurrentParameterBookmarkName(String parameterBookmarkName) { 129 assert parameterBookmarks.containsKey(parameterBookmarkName); 130 this.currentParameterBookmarkName = parameterBookmarkName; 131 } 132 133 public synchronized Map<String, PreferenceAccessParameters> getParameterBookmarks() { 134 return Collections.unmodifiableMap(parameterBookmarks); 135 } 136 public synchronized void setParameterBookmarks( 137 Map<String, PreferenceAccessParameters> parameterBookmarks) { 138 assert parameterBookmarks != null; 139 140 this.parameterBookmarks = 141 new HashMap<String, PreferenceAccessParameters>(parameterBookmarks); 142 } 143 144 public synchronized ColorScheme getCurrentColorScheme() { 145 return currentColorScheme; 146 } 147 public synchronized void setCurrentColorScheme(ColorScheme currentColorScheme) { 148 this.currentColorScheme = currentColorScheme; 149 } 150 151 public synchronized Color getNodeColor() { 152 return nodeColor; 153 } 154 public synchronized void setNodeColor(Color nodeColor) { 155 this.nodeColor = nodeColor; 156 } 157 158 public synchronized Color getSegmentColor() { 159 return segmentColor; 160 } 161 public synchronized void setSegmentColor(Color segmentColor) { 162 this.segmentColor = segmentColor; 163 } 164 165 public synchronized boolean getSeparateDirections() { 166 return separateDirections; 167 } 168 public synchronized void setSeparateDirections(boolean separateDirections) { 169 this.separateDirections = separateDirections; 170 } 171 172 /** 173 * writes changes to JOSM's preferences and notifies observers. 174 * Must be called explicitly after setters (to prevent distributing incomplete changes). 175 */ 176 public void distributeChanges() { 177 writePreferences(); 178 setChanged(); 179 notifyObservers(); 180 } 181 182 private GraphViewPreferences() { 183 184 /* set defaults first (in case preferences are incomplete) */ 185 186 fillDefaults(); 187 188 /* read preferences and overwrite defaults */ 189 190 readPreferences(); 191 192 /* write preferences 193 * (this will restore missing/defect preferences, 194 * but will simply rewrite valid preferences) */ 195 196 writePreferences(); 197 198 } 199 200 private void fillDefaults() { 201 202 parameterBookmarks = GraphViewPreferenceDefaults.createDefaultAccessParameterBookmarks(); 203 204 if (parameterBookmarks.size() > 0) { 205 currentParameterBookmarkName = parameterBookmarks.keySet().iterator().next(); 206 } else { 207 currentParameterBookmarkName = null; 208 } 209 210 useInternalRulesets = true; 211 rulesetFolder = GraphViewPreferenceDefaults.getDefaultRulesetFolder(); 212 currentRulesetFile = null; 213 currentInternalRuleset = null; 214 215 nodeColor = Color.WHITE; 216 segmentColor = Color.WHITE; 217 currentColorScheme = new PreferencesColorScheme(this); 218 219 separateDirections = false; 220 221 } 222 223 private void writePreferences() { 224 225 Main.pref.put("graphview.parameterBookmarks", 226 createAccessParameterBookmarksString(parameterBookmarks)); 227 228 if (currentParameterBookmarkName != null) { 229 Main.pref.put("graphview.activeBookmark", currentParameterBookmarkName); 230 } 231 232 Main.pref.put("graphview.useInternalRulesets", useInternalRulesets); 233 234 Main.pref.put("graphview.rulesetFolder", rulesetFolder.getPath()); 235 236 if (currentRulesetFile != null) { 237 Main.pref.put("graphview.rulesetFile", currentRulesetFile.getPath()); 238 } 239 if (currentInternalRuleset != null) { 240 Main.pref.put("graphview.rulesetResource", currentInternalRuleset.toString()); 241 } 242 243 Main.pref.put("graphview.defaultNodeColor", createColorString(nodeColor)); 244 Main.pref.put("graphview.defaultSegmentColor", createColorString(segmentColor)); 245 246 Main.pref.put("graphview.separateDirections", separateDirections); 247 248 } 249 250 private void readPreferences() { 251 252 if (Main.pref.hasKey("graphview.parameterBookmarks")) { 253 String bookmarksString = Main.pref.get("graphview.parameterBookmarks"); 254 parameterBookmarks = parseAccessParameterBookmarksString(bookmarksString); 255 } 256 257 if (Main.pref.hasKey("graphview.activeBookmark")) { 258 currentParameterBookmarkName = Main.pref.get("graphview.activeBookmark"); 259 } 260 if (!parameterBookmarks.containsKey(currentParameterBookmarkName)) { 261 currentParameterBookmarkName = null; 262 } 263 264 265 useInternalRulesets = Main.pref.getBoolean("graphview.useInternalRulesets", true); 266 267 if (Main.pref.hasKey("graphview.rulesetFolder")) { 268 String dirString = Main.pref.get("graphview.rulesetFolder"); 269 rulesetFolder = new File(dirString); 270 } 271 if (Main.pref.hasKey("graphview.rulesetFile")) { 272 String fileString = Main.pref.get("graphview.rulesetFile"); 273 currentRulesetFile = new File(fileString); 274 } 275 276 if (Main.pref.hasKey("graphview.rulesetResource")) { 277 String rulesetString = Main.pref.get("graphview.rulesetResource"); 278 //get the enum value for the string 279 //(InternalRuleset.valueOf cannot be used because it cannot handle invalid strings well) 280 for (InternalRuleset ruleset : InternalRuleset.values()) { 281 if (ruleset.toString().equals(rulesetString)) { 282 currentInternalRuleset = ruleset; 283 break; 284 } 285 } 286 } 287 288 if (Main.pref.hasKey("graphview.defaultNodeColor")) { 289 Color color = parseColorString(Main.pref.get("graphview.defaultNodeColor")); 290 if (color != null) { 291 nodeColor = color; 292 } 293 } 294 if (Main.pref.hasKey("graphview.defaultSegmentColor")) { 295 Color color = parseColorString(Main.pref.get("graphview.defaultSegmentColor")); 296 if (color != null) { 297 segmentColor = color; 298 } 299 } 300 301 separateDirections = Main.pref.getBoolean("graphview.separateDirections", false); 302 303 } 304 305 private static final Pattern ACCESS_PARAM_PATTERN = Pattern.compile("^([^;]*);([^;]*);types=\\{([^\\}]*)\\};properties=\\{([^\\}]*)\\}$"); 306 307 private static final Pattern PROPERTY_MAP_ENTRY_PATTERN = Pattern.compile("^([^=]*)=(.*)$"); 308 309 private static final Map<VehiclePropertyType<?>, String> VEHICLE_PROPERTY_TYPE_NAME_MAP = 310 new HashMap<VehiclePropertyType<?>, String>(); 311 312 313 static { 314 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(AXLELOAD, "AXLELOAD"); 315 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(HEIGHT, "HEIGHT"); 316 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(LENGTH, "LENGTH"); 317 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(MAX_INCLINE_DOWN, "MAX_INCLINE_DOWN"); 318 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(MAX_INCLINE_UP, "MAX_INCLINE_UP"); 319 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(MAX_TRACKTYPE, "MAX_TRACKTYPE"); 320 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(SPEED, "SPEED"); 321 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(SURFACE_BLACKLIST, "SURFACE_BLACKLIST"); 322 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(WEIGHT, "WEIGHT"); 323 VEHICLE_PROPERTY_TYPE_NAME_MAP.put(WIDTH, "WIDTH"); 324 } 325 326 private static String createAccessParameterBookmarksString( 327 Map<String, PreferenceAccessParameters> parameterBookmarks) { 328 329 StringBuilder stringBuilder = new StringBuilder(); 330 331 boolean firstEntry = true; 332 333 for (String bookmarkName : parameterBookmarks.keySet()) { 334 335 if (!firstEntry) { 336 stringBuilder.append("|"); 337 } else { 338 firstEntry = false; 339 } 340 341 stringBuilder.append(createAccessParameterBookmarkString( 342 bookmarkName, 343 parameterBookmarks.get(bookmarkName))); 344 345 } 346 347 return stringBuilder.toString(); 348 } 349 350 private static String createAccessParameterBookmarkString( 351 String bookmarkName, PreferenceAccessParameters parameters) { 352 353 StringBuilder stringBuilder = new StringBuilder(); 354 355 stringBuilder.append(bookmarkName).append(";"); 356 357 stringBuilder.append(parameters.getAccessClass()); 358 359 stringBuilder.append(";types={"); 360 for (AccessType accessType : AccessType.values()) { 361 if (parameters.getAccessTypeUsable(accessType)) { 362 stringBuilder.append(accessType).append(","); 363 } 364 } 365 366 if(stringBuilder.charAt(stringBuilder.length()-1) == ',') { 367 stringBuilder.deleteCharAt(stringBuilder.length()-1); 368 } 369 stringBuilder.append("}"); 370 371 stringBuilder.append(";properties={"); 372 373 for (VehiclePropertyType<?> vehiclePropertyType : VEHICLE_PROPERTY_TYPE_NAME_MAP.keySet()) { 374 String propertyString = parameters.getVehiclePropertyString(vehiclePropertyType); 375 if (propertyString != null) { 376 stringBuilder.append(VEHICLE_PROPERTY_TYPE_NAME_MAP.get(vehiclePropertyType)); 377 stringBuilder.append("="); 378 stringBuilder.append(propertyString); 379 stringBuilder.append(","); 380 } 381 } 382 383 if(stringBuilder.charAt(stringBuilder.length()-1) == ',') { 384 stringBuilder.deleteCharAt(stringBuilder.length()-1); 385 } 386 stringBuilder.append("}"); 387 388 assert ACCESS_PARAM_PATTERN.matcher(stringBuilder.toString()).matches(); 389 390 return stringBuilder.toString(); 391 } 392 393 private static Map<String, PreferenceAccessParameters> parseAccessParameterBookmarksString( 394 String string) { 395 396 Map<String, PreferenceAccessParameters> resultMap = 397 new HashMap<String, PreferenceAccessParameters>(); 398 399 String[] bookmarkStrings = string.split("\\|"); 400 401 for (String bookmarkString : bookmarkStrings) { 402 parseAccessParameterBookmarkString(bookmarkString, resultMap); 403 } 404 405 return resultMap; 406 } 407 408 private static void parseAccessParameterBookmarkString(String bookmarkString, 409 Map<String, PreferenceAccessParameters> resultMap) { 410 411 Matcher matcher = ACCESS_PARAM_PATTERN.matcher(bookmarkString); 412 413 if (matcher.matches()) { 414 415 String bookmarkName = matcher.group(1); 416 417 String accessClass = matcher.group(2); 418 419 String[] accessTypeStrings = matcher.group(3).split(","); 420 Collection<AccessType> accessTypes = new LinkedList<AccessType>(); 421 for (String accessTypeString : accessTypeStrings) { 422 AccessType accessType = AccessType.valueOf(accessTypeString); 423 if (accessType != null) { 424 accessTypes.add(accessType); 425 } 426 } 427 428 429 String[] vehiclePropertyStrings = matcher.group(4).split(","); 430 Map<VehiclePropertyType<?>, String> vehiclePropertyMap = 431 new HashMap<VehiclePropertyType<?>, String>(); 432 433 for (String vehiclePropertyString : vehiclePropertyStrings) { 434 435 Matcher entryMatcher = PROPERTY_MAP_ENTRY_PATTERN.matcher(vehiclePropertyString); 436 if (entryMatcher.matches()) { 437 438 String propertyTypeString = entryMatcher.group(1); 439 String propertyValueString = entryMatcher.group(2); 440 441 for (VehiclePropertyType<?> propertyType : 442 VEHICLE_PROPERTY_TYPE_NAME_MAP.keySet()) { 443 444 if (propertyTypeString.equals( 445 VEHICLE_PROPERTY_TYPE_NAME_MAP.get(propertyType))) { 446 447 vehiclePropertyMap.put(propertyType, propertyValueString); 448 449 } 450 451 } 452 453 } 454 455 } 456 457 try { 458 459 PreferenceAccessParameters accessParameters = 460 new PreferenceAccessParameters(accessClass, accessTypes, vehiclePropertyMap); 461 462 resultMap.put(bookmarkName, accessParameters); 463 464 } catch (PropertyValueSyntaxException e) { 465 //don't add bookmark 466 } 467 468 } 469 } 470 471 private static final Pattern COLOR_PATTERN = 472 Pattern.compile("^(\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})$"); 473 private String createColorString(Color color) { 474 return color.getRed() + ", " + color.getGreen() + ", " + color.getBlue(); 475 } 476 477 private Color parseColorString(String string) { 478 Matcher matcher = COLOR_PATTERN.matcher(string); 479 if (!matcher.matches()) { 480 return null; 481 } else { 482 int r = Integer.parseInt(matcher.group(1)); 483 int g = Integer.parseInt(matcher.group(2)); 484 int b = Integer.parseInt(matcher.group(3)); 485 return new Color(r, g, b); 486 } 487 } 488 488 489 489 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/InternalRuleset.java
r16520 r23189 3 3 public enum InternalRuleset { 4 4 5 6 5 DEFAULT("files/accessRuleset.xml"), 6 GERMANY("files/accessRuleset_de.xml"); 7 7 8 9 10 11 12 13 14 8 private String resourceName; 9 private InternalRuleset(String resourceName) { 10 this.resourceName = resourceName; 11 } 12 public String getResourceName() { 13 return resourceName; 14 } 15 15 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/PreferenceAccessParameters.java
r16520 r23189 17 17 public class PreferenceAccessParameters implements AccessParameters { 18 18 19 20 21 22 19 private final String accessClass; 20 private final Map<AccessType, Boolean> accessTypeUsableMap; 21 private final Map<VehiclePropertyType<?>, String> vehiclePropertyStrings; 22 private final Map<VehiclePropertyType<?>, Object> vehiclePropertyValues; 23 23 24 25 26 24 public String getAccessClass() { 25 return accessClass; 26 } 27 27 28 29 30 31 28 public boolean getAccessTypeUsable(AccessType accessType) { 29 assert accessType != null; 30 return accessTypeUsableMap.get(accessType); 31 } 32 32 33 34 35 33 public Collection<VehiclePropertyType<?>> getAvailableVehicleProperties() { 34 return vehiclePropertyValues.keySet(); 35 } 36 36 37 38 39 40 41 42 43 44 45 46 47 37 /** 38 * returns the value for a vehicle property. 39 * 40 * @param <D> type of property value 41 * @param vehicleProperty property to get value for; != null 42 * @return value for vehicleProperty, null if no value is available. 43 * Guaranteed to be valid according to vehicleProperty's 44 * {@link VehiclePropertyType#isValidValue(Object)} method. 45 */ 46 public <D> D getVehiclePropertyValue(VehiclePropertyType<D> vehicleProperty) { 47 assert vehicleProperty != null; 48 48 49 50 51 52 49 @SuppressWarnings("unchecked") 50 D value = (D)vehiclePropertyValues.get(vehicleProperty); 51 return value; 52 } 53 53 54 55 56 57 58 59 60 61 54 /** 55 * returns the unparsed String for a vehicle property. 56 * 57 * @param vehicleProperty property to get String for; != null 58 * @return unparsed String, null if no value is available. 59 */ 60 public String getVehiclePropertyString(VehiclePropertyType<?> vehicleProperty) { 61 assert vehicleProperty != null; 62 62 63 64 63 return vehiclePropertyStrings.get(vehicleProperty); 64 } 65 65 66 67 68 69 70 71 72 73 74 75 76 77 66 /** 67 * @param vehiclePropertyStrings map from vehicle properties to string representations 68 * that will be parsed using {@link VehiclePropertyStringParser} 69 * to get the property values; != null 70 * 71 * @throws VehiclePropertyStringParser.PropertyValueSyntaxException 72 * if a String from vehiclePropertyStrings contains a syntax error 73 */ 74 public PreferenceAccessParameters(String accessClass, 75 Collection<AccessType> usableAccessTypes, 76 Map<VehiclePropertyType<?>, String> vehiclePropertyStrings) 77 throws VehiclePropertyStringParser.PropertyValueSyntaxException { 78 78 79 79 this.accessClass = accessClass; 80 80 81 82 83 84 81 accessTypeUsableMap = new EnumMap<AccessType, Boolean>(AccessType.class); 82 for (AccessType accessType : AccessType.values()) { 83 accessTypeUsableMap.put(accessType, usableAccessTypes.contains(accessType)); 84 } 85 85 86 86 /* check and use vehicle properties */ 87 87 88 89 88 this.vehiclePropertyStrings = Collections.unmodifiableMap( 89 new HashMap<VehiclePropertyType<?>, String>(vehiclePropertyStrings)); 90 90 91 92 93 94 95 96 97 91 this.vehiclePropertyValues = new HashMap<VehiclePropertyType<?>, Object>(); 92 for (VehiclePropertyType<?> vehiclePropertyType : vehiclePropertyStrings.keySet()) { 93 String propertyValueString = vehiclePropertyStrings.get(vehiclePropertyType); 94 Object propertyValue = VehiclePropertyStringParser.parsePropertyValue( 95 vehiclePropertyType, propertyValueString); 96 this.vehiclePropertyValues.put(vehiclePropertyType, propertyValue); 97 } 98 98 99 99 } 100 100 101 101 } -
applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/VehiclePropertyStringParser.java
r20243 r23189 16 16 public final class VehiclePropertyStringParser { 17 17 18 19 18 /** prevents instantiation */ 19 private VehiclePropertyStringParser() { } 20 20 21 22 23 24 25 26 27 28 29 30 21 /** 22 * Exception class for syntax errors in property value Strings, 23 * the message contains the reason using one of this utility class' public String constants. 24 */ 25 public static class PropertyValueSyntaxException extends Exception { 26 private static final long serialVersionUID = 1L; 27 public PropertyValueSyntaxException(String message) { 28 super(message); 29 } 30 } 31 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 32 public static final String ERROR_WEIGHT = 33 "Weights must be given as positive decimal numbers with unit \"t\" or without unit."; 34 public static final String ERROR_LENGTH = 35 "Lengths must be given as positive decimal numbers with unit \"m\", \"km\", \"mi\"" + 36 " or without unit.\nAlternatively, the format FEET' INCHES\" can be used."; 37 public static final String ERROR_SPEED = 38 "Speeds should be given as numbers without unit or " 39 + "as numbers followed by \"mph\"."; 40 public static final String ERROR_INCLINE = 41 "Inclines must be given as positive decimal numbers with followed by \"%\"."; 42 public static final String ERROR_TRACKTYPE = 43 "Tracktype grades must be given as integers between 0 and 5."; 44 public static final String ERROR_SURFACE = 45 "Surface values must not contain any of the following characters: ',' '{' '}' '=' '|"; 46 46 47 48 47 private static final List<Character> FORBIDDEN_SURFACE_CHARS = 48 Arrays.asList(',', '{', '}', '=', '|'); 49 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 50 /** 51 * returns the value represented by the propertyValueString 52 * 53 * @throws PropertyValueSyntaxException if the string has syntax errors that prevent parsing 54 * @throws InvalidParameterException if an unknown property type was passed 55 * 56 * @param propertyType type of the property; != null 57 * @param propertyValueString string to parse; != null 58 * @return property value; != null. 59 * Guaranteed to be valid according to propertyType's 60 * {@link VehiclePropertyType#isValidValue(Object)} method. 61 */ 62 public static final <V> V parsePropertyValue( 63 VehiclePropertyType<V> propertyType, String propertyValueString) 64 throws PropertyValueSyntaxException { 65 65 66 66 assert propertyType != null && propertyValueString != null; 67 67 68 69 68 if (propertyType == VehiclePropertyTypes.AXLELOAD 69 || propertyType == VehiclePropertyTypes.WEIGHT) { 70 70 71 72 73 74 75 76 77 78 71 Float value = ValueStringParser.parseWeight(propertyValueString); 72 if (value != null && propertyType.isValidValue(value)) { 73 @SuppressWarnings("unchecked") //V must be float because of propertyType condition 74 V result = (V)value; 75 return result; 76 } else { 77 throw new PropertyValueSyntaxException(ERROR_WEIGHT); 78 } 79 79 80 81 82 80 } else if (propertyType == VehiclePropertyTypes.HEIGHT 81 || propertyType == VehiclePropertyTypes.LENGTH 82 || propertyType == VehiclePropertyTypes.WIDTH) { 83 83 84 85 86 87 88 89 90 91 84 Float value = ValueStringParser.parseMeasure(propertyValueString); 85 if (value != null && propertyType.isValidValue(value)) { 86 @SuppressWarnings("unchecked") //V must be float because of propertyType condition 87 V result = (V)value; 88 return result; 89 } else { 90 throw new PropertyValueSyntaxException(ERROR_LENGTH); 91 } 92 92 93 93 } else if (propertyType == VehiclePropertyTypes.SPEED) { 94 94 95 96 97 98 99 100 101 102 95 Float value = ValueStringParser.parseSpeed(propertyValueString); 96 if (value != null && propertyType.isValidValue(value)) { 97 @SuppressWarnings("unchecked") //V must be float because of propertyType condition 98 V result = (V)value; 99 return result; 100 } else { 101 throw new PropertyValueSyntaxException(ERROR_SPEED); 102 } 103 103 104 105 104 } else if (propertyType == VehiclePropertyTypes.MAX_INCLINE_DOWN 105 || propertyType == VehiclePropertyTypes.MAX_INCLINE_UP) { 106 106 107 108 109 110 111 112 113 114 107 Float value = ValueStringParser.parseIncline(propertyValueString); 108 if (value != null && propertyType.isValidValue(value)) { 109 @SuppressWarnings("unchecked") //V must be float because of propertyType condition 110 V result = (V)value; 111 return result; 112 } else { 113 throw new PropertyValueSyntaxException(ERROR_INCLINE); 114 } 115 115 116 116 } else if (propertyType == VehiclePropertyTypes.MAX_TRACKTYPE) { 117 117 118 119 120 121 122 123 124 125 118 try { 119 int value = Integer.parseInt(propertyValueString); 120 if (0 <= value && value <= 5) { 121 @SuppressWarnings("unchecked") //V must be int because of propertyType condition 122 V result = (V)(Integer)value; 123 return result; 124 } 125 } catch (NumberFormatException e) {} 126 126 127 127 throw new PropertyValueSyntaxException(ERROR_TRACKTYPE); 128 128 129 129 } else if (propertyType == VehiclePropertyTypes.SURFACE_BLACKLIST) { 130 130 131 132 133 134 135 136 137 138 139 140 131 String[] surfaces = propertyValueString.split(";\\s*"); 132 Collection<String> surfaceBlacklist = new ArrayList<String>(surfaces.length); 133 for (String surface : surfaces) { 134 for (char nameChar : surface.toCharArray()) { 135 if (FORBIDDEN_SURFACE_CHARS.contains(nameChar)) { 136 throw new PropertyValueSyntaxException(ERROR_SURFACE); 137 } 138 } 139 surfaceBlacklist.add(surface); 140 } 141 141 142 143 144 142 @SuppressWarnings("unchecked") //V must be Collection because of propertyType condition 143 V result = (V)surfaceBlacklist; 144 return result; 145 145 146 147 148 146 } else { 147 throw new InvalidParameterException("unknown property type: " + propertyType); 148 } 149 149 150 150 } 151 151 152 152 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/FullGraphCreationTest.java
r19216 r23189 32 32 public class FullGraphCreationTest { 33 33 34 35 36 37 38 34 private static final AccessParameters ACCESS_PARAMS; 35 static { 36 Map<VehiclePropertyType<?>, String> vehiclePropertyValues = 37 new HashMap<VehiclePropertyType<?>, String>(); 38 vehiclePropertyValues.put(VehiclePropertyTypes.WIDTH, "3.0"); 39 39 40 41 42 43 44 45 46 47 48 40 try { 41 ACCESS_PARAMS = new PreferenceAccessParameters( 42 "test_vehicle", 43 Arrays.asList(AccessType.UNDEFINED), 44 vehiclePropertyValues); 45 } catch (PropertyValueSyntaxException e) { 46 throw new Error(e); 47 } 48 } 49 49 50 51 52 53 54 55 56 57 58 59 60 50 private static final AccessRuleset TEST_RULESET = new AccessRuleset() { 51 public java.util.List<String> getAccessHierarchyAncestors(String transportMode) { 52 return Arrays.asList(transportMode); 53 } 54 public java.util.Collection<Tag> getBaseTags() { 55 return Arrays.asList(new Tag("highway", "test")); 56 } 57 public java.util.List<Implication> getImplications() { 58 return new LinkedList<Implication>(); 59 } 60 }; 61 61 62 63 62 @Test 63 public void testTJunction() { 64 64 65 65 TestDataSource ds = new TestDataSource(); 66 66 67 68 69 70 67 TestNode nodeN = new TestNode(2, 1); 68 TestNode nodeW = new TestNode(1, 0); 69 TestNode nodeS = new TestNode(0, 1); 70 TestNode nodeC = new TestNode(1, 1); 71 71 72 72 ds.nodes.addAll(Arrays.asList(nodeN, nodeW, nodeS, nodeC)); 73 73 74 75 76 77 78 79 80 81 82 74 TestWay wayNC = new TestWay(); 75 wayNC.tags.put("highway", "test"); 76 wayNC.nodes.addAll(Arrays.asList(nodeN, nodeC)); 77 TestWay wayCS = new TestWay(); 78 wayCS.tags.put("highway", "test"); 79 wayCS.nodes.addAll(Arrays.asList(nodeC, nodeS)); 80 TestWay wayCW = new TestWay(); 81 wayCW.tags.put("highway", "test"); 82 wayCW.nodes.addAll(Arrays.asList(nodeC, nodeW)); 83 83 84 85 86 84 ds.ways.add(wayNC); 85 ds.ways.add(wayCS); 86 ds.ways.add(wayCW); 87 87 88 89 90 88 /* variant 1: no restrictions */ 89 { 90 TransitionStructure ts1 = createTestTransitionStructure(ds); 91 91 92 93 94 92 assertSame(4, size(ts1.getNodes())); 93 assertSame(6, size(ts1.getSegments())); 94 assertSame(0, size(ts1.getRestrictions())); 95 95 96 96 WayGraph graph1 = new TSBasedWayGraph(ts1); 97 97 98 99 100 101 102 103 104 98 assertSame(12, graph1.getNodes().size()); 99 assertSame(24, graph1.getEdges().size()); 100 } 101 /* variant 2: no left turn from S to W */ 102 { 103 ds.relations.add(createTurnRestrictionRelation(wayCS, nodeC, wayCW, "no_left_turn")); 104 TransitionStructure ts2 = createTestTransitionStructure(ds); 105 105 106 107 108 106 assertSame(4, size(ts2.getNodes())); 107 assertSame(6, size(ts2.getSegments())); 108 assertSame(1, size(ts2.getRestrictions())); 109 109 110 110 WayGraph graph2 = new TSBasedWayGraph(ts2); 111 111 112 113 114 112 assertSame(12, graph2.getNodes().size()); 113 assertSame(23, graph2.getEdges().size()); 114 } 115 115 116 116 } 117 117 118 119 118 @Test 119 public void testBarrier() { 120 120 121 121 TestDataSource ds = new TestDataSource(); 122 122 123 124 125 126 123 TestNode node1 = new TestNode(0, 1); 124 TestNode nodeB = new TestNode(0, 2); 125 nodeB.tags.put("width", "1"); 126 TestNode node2 = new TestNode(0, 3); 127 127 128 128 ds.nodes.addAll(Arrays.asList(node1, nodeB, node2)); 129 129 130 131 132 133 134 130 TestWay way = new TestWay(); 131 way.tags.put("highway", "test"); 132 way.tags.put("oneway", "yes"); 133 way.nodes.addAll(Arrays.asList(node1, nodeB, node2)); 134 ds.ways.add(way); 135 135 136 136 /* variant 1: no restrictions */ 137 137 138 138 TransitionStructure ts = createTestTransitionStructure(ds); 139 139 140 141 142 140 assertSame(3, size(ts.getNodes())); 141 assertSame(2, size(ts.getSegments())); 142 assertSame(1, size(ts.getRestrictions())); 143 143 144 144 WayGraph graph = new TSBasedWayGraph(ts); 145 145 146 147 146 assertSame(4, graph.getNodes().size()); 147 assertSame(2, graph.getEdges().size()); 148 148 149 149 } 150 150 151 152 153 154 155 156 157 158 159 160 151 private TestRelation createTurnRestrictionRelation( 152 TestWay from, TestNode via, TestWay to, String restriction) { 153 TestRelation resultRelation = new TestRelation(); 154 resultRelation.tags.put("type", "restriction"); 155 resultRelation.tags.put("restriction", restriction); 156 resultRelation.members.add(new TestRelationMember("from", from)); 157 resultRelation.members.add(new TestRelationMember("via", via)); 158 resultRelation.members.add(new TestRelationMember("to", to)); 159 return resultRelation; 160 } 161 161 162 162 private TransitionStructure createTestTransitionStructure(TestDataSource dataSource) { 163 163 164 165 164 LinkedList<RoadPropertyType<?>> properties = new LinkedList<RoadPropertyType<?>>(); 165 properties.add(new RoadWidth()); 166 166 167 168 169 167 return new GenericTransitionStructure<TestNode, TestWay, TestRelation, TestRelationMember>( 168 ACCESS_PARAMS, TEST_RULESET, dataSource, properties); 169 } 170 170 171 172 173 174 175 176 177 178 179 171 private static int size(Iterable<?> iterable) { 172 Iterator<?> iterator = iterable.iterator(); 173 int size = 0; 174 while (iterator.hasNext()) { 175 iterator.next(); 176 size ++; 177 } 178 return size; 179 } 180 180 181 181 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/TestDataSource.java
r19216 r23189 14 14 public class TestDataSource implements DataSource<TestDataSource.TestNode, TestDataSource.TestWay, TestDataSource.TestRelation, TestDataSource.TestRelationMember> { 15 15 16 17 18 16 public static class TestPrimitive { 17 public final Map<String, String> tags = new HashMap<String, String>(); 18 }; 19 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 20 public static class TestNode extends TestPrimitive { 21 public final double lat; 22 public final double lon; 23 public TestNode() { 24 this(0, 0); 25 } 26 public TestNode(double lat, double lon) { 27 this.lat = lat; 28 this.lon = lon; 29 } 30 @Override 31 public String toString() { 32 return "(" + lat + ", " + lon + "); " + tags; 33 } 34 } 35 35 36 37 38 39 40 41 42 36 public static class TestWay extends TestPrimitive { 37 public final List<TestNode> nodes = new LinkedList<TestNode>(); 38 @Override 39 public String toString() { 40 return nodes + "; " + tags; 41 } 42 } 43 43 44 45 46 47 48 49 50 44 public static class TestRelation extends TestPrimitive { 45 public final Collection<TestRelationMember> members = new LinkedList<TestRelationMember>(); 46 @Override 47 public String toString() { 48 return members + "; " + tags; 49 } 50 } 51 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 52 public static class TestRelationMember { 53 public final String role; 54 public final TestPrimitive member; 55 public TestRelationMember(String role, TestPrimitive member) { 56 this.role = role; 57 this.member = member; 58 } 59 public TestPrimitive getMember() { 60 return member; 61 } 62 public String getRole() { 63 return role; 64 } 65 @Override 66 public String toString() { 67 return role + "=" + member; 68 } 69 } 70 70 71 71 72 73 74 72 public final Collection<TestNode> nodes = new LinkedList<TestNode>(); 73 public final Collection<TestWay> ways = new LinkedList<TestWay>(); 74 public final Collection<TestRelation> relations = new LinkedList<TestRelation>(); 75 75 76 76 77 78 79 80 81 82 77 public double getLat(TestNode node) { 78 return node.lat; 79 } 80 public double getLon(TestNode node) { 81 return node.lon; 82 } 83 83 84 85 86 84 public Iterable<TestRelationMember> getMembers(TestRelation relation) { 85 return relation.members; 86 } 87 87 88 89 90 88 public Iterable<TestNode> getNodes() { 89 return nodes; 90 } 91 91 92 93 94 92 public Iterable<TestNode> getNodes(TestWay way) { 93 return way.nodes; 94 } 95 95 96 97 98 96 public Iterable<TestWay> getWays() { 97 return ways; 98 } 99 99 100 101 102 100 public Iterable<TestRelation> getRelations() { 101 return relations; 102 } 103 103 104 105 106 104 public TagGroup getTagsN(TestNode node) { 105 return new MapBasedTagGroup(node.tags); 106 } 107 107 108 109 110 108 public TagGroup getTagsW(TestWay way) { 109 return new MapBasedTagGroup(way.tags); 110 } 111 111 112 public TagGroup getTagsR(TestRelation relation) { 113 return new MapBasedTagGroup(relation.tags); 114 } 115 116 public Object getMember(TestRelationMember member) { 117 return member.getMember(); 118 } 119 120 public String getRole(TestRelationMember member) { 121 return member.getRole(); 122 } 123 124 public boolean isNMember(TestRelationMember member) { 125 return member.getMember() instanceof TestNode; 126 } 127 128 public boolean isWMember(TestRelationMember member) { 129 return member.getMember() instanceof TestWay; 130 } 131 132 public boolean isRMember(TestRelationMember member) { 133 return member.getMember() instanceof TestRelation; 134 } 112 public TagGroup getTagsR(TestRelation relation) { 113 return new MapBasedTagGroup(relation.tags); 114 } 135 115 136 void addObserver(DataSourceObserver observer) {137 // not needed for test 138 116 public Object getMember(TestRelationMember member) { 117 return member.getMember(); 118 } 139 119 140 public void deleteObserver(DataSourceObserver observer) { 141 // not needed for test 142 } 120 public String getRole(TestRelationMember member) { 121 return member.getRole(); 122 } 123 124 public boolean isNMember(TestRelationMember member) { 125 return member.getMember() instanceof TestNode; 126 } 127 128 public boolean isWMember(TestRelationMember member) { 129 return member.getMember() instanceof TestWay; 130 } 131 132 public boolean isRMember(TestRelationMember member) { 133 return member.getMember() instanceof TestRelation; 134 } 135 136 public void addObserver(DataSourceObserver observer) { 137 // not needed for test 138 } 139 140 public void deleteObserver(DataSourceObserver observer) { 141 // not needed for test 142 } 143 143 144 144 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/access/AccessRulesetReaderTest.java
r16520 r23189 22 22 public class AccessRulesetReaderTest { 23 23 24 25 24 @Test 25 public void testReadAccessRuleset_valid_classes() throws IOException { 26 26 27 28 29 27 InputStream is = new FileInputStream("plugins/graphview/test/files/accessRuleset_valid.xml"); 28 AccessRuleset ruleset = AccessRulesetReader.readAccessRuleset(is); 29 assertNotNull(ruleset); 30 30 31 31 32 32 assertEquals("vehicle", ruleset.getAccessHierarchyAncestors("vehicle").get(0)); 33 33 34 35 34 assertEquals("motor_vehicle", ruleset.getAccessHierarchyAncestors("motor_vehicle").get(0)); 35 assertEquals("vehicle", ruleset.getAccessHierarchyAncestors("motor_vehicle").get(1)); 36 36 37 38 39 37 assertEquals("bus", ruleset.getAccessHierarchyAncestors("bus").get(0)); 38 assertEquals("motor_vehicle", ruleset.getAccessHierarchyAncestors("bus").get(1)); 39 assertEquals("vehicle", ruleset.getAccessHierarchyAncestors("bus").get(2)); 40 40 41 42 41 assertEquals("bicycle", ruleset.getAccessHierarchyAncestors("bicycle").get(0)); 42 assertEquals("vehicle", ruleset.getAccessHierarchyAncestors("bicycle").get(1)); 43 43 44 44 assertFalse(ruleset.getAccessHierarchyAncestors("bus").contains("bicycle")); 45 45 46 46 assertSame(ruleset.getAccessHierarchyAncestors("boat").size(), 0); 47 47 48 48 } 49 49 50 51 50 @Test 51 public void testReadAccessRuleset_valid_basetags() throws IOException { 52 52 53 54 55 53 InputStream is = new FileInputStream("plugins/graphview/test/files/accessRuleset_valid.xml"); 54 AccessRuleset ruleset = AccessRulesetReader.readAccessRuleset(is); 55 assertNotNull(ruleset); 56 56 57 57 assertSame(2, ruleset.getBaseTags().size()); 58 58 59 60 61 62 59 assertTrue(ruleset.getBaseTags().contains(new Tag("highway", "residential"))); 60 assertTrue(ruleset.getBaseTags().contains(new Tag("highway", "cycleway"))); 61 assertFalse(ruleset.getBaseTags().contains(new Tag("building", "residential"))); 62 assertFalse(ruleset.getBaseTags().contains(new Tag("highway", "stop"))); 63 63 64 64 } 65 65 66 67 66 @Test 67 public void testReadAccessRuleset_valid_implications() throws IOException { 68 68 69 70 71 69 InputStream is = new FileInputStream("plugins/graphview/test/files/accessRuleset_valid.xml"); 70 AccessRuleset ruleset = AccessRulesetReader.readAccessRuleset(is); 71 assertNotNull(ruleset); 72 72 73 73 List<Implication> implications = ruleset.getImplications(); 74 74 75 75 assertSame(3, implications.size()); 76 76 77 78 79 80 81 77 TagGroup[] tagGroups = new TagGroup[4]; 78 tagGroups[0] = createTagGroup(new Tag("highway", "cycleway")); 79 tagGroups[1] = createTagGroup(new Tag("highway", "steps")); 80 tagGroups[2] = createTagGroup(new Tag("highway", "steps"), new Tag("escalator", "yes")); 81 tagGroups[3] = createTagGroup(new Tag("disused", "yes"), new Tag("construction", "no")); 82 82 83 84 85 86 87 83 for (Implication implication : implications) { 84 for (int i = 0; i < tagGroups.length; i++) { 85 tagGroups[i] = implication.apply(tagGroups[i]); 86 } 87 } 88 88 89 90 89 assertSame(2, tagGroups[0].size()); 90 assertTrue(tagGroups[0].contains(new Tag("bicycle", "designated"))); 91 91 92 93 92 assertSame(2, tagGroups[1].size()); 93 assertTrue(tagGroups[1].contains(new Tag("normal_steps", "yes"))); 94 94 95 96 95 assertSame(2, tagGroups[2].size()); 96 assertFalse(tagGroups[2].contains(new Tag("normal_steps", "yes"))); 97 97 98 99 100 98 assertSame(3, tagGroups[3].size()); 99 assertTrue(tagGroups[3].contains(new Tag("usable", "no"))); 100 } 101 101 102 103 104 105 106 107 108 102 private static TagGroup createTagGroup(Tag... tags) { 103 Map<String, String> tagMap = new HashMap<String, String>(); 104 for (Tag tag : tags) { 105 tagMap.put(tag.key, tag.value); 106 } 107 return new MapBasedTagGroup(tagMap); 108 } 109 109 110 110 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/property/RoadInclineTest.java
r16520 r23189 6 6 public class RoadInclineTest extends RoadPropertyTest { 7 7 8 9 8 private static void testIncline(Float expectedInclineForward, Float expectedInclineBackward, 9 String inclineString) { 10 10 11 12 13 14 11 testEvaluateW(new RoadIncline(), 12 expectedInclineForward, expectedInclineBackward, 13 new Tag("incline", inclineString)); 14 } 15 15 16 17 18 19 20 21 22 16 @Test 17 public void testEvaluate() { 18 testIncline(5f, -5f, "5 %"); 19 testIncline(9.5f, -9.5f, "9.5 %"); 20 testIncline(-2.5f, 2.5f, "-2.5%"); 21 testIncline(null, null, "steep"); 22 } 23 23 24 24 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/property/RoadMaxspeedTest.java
r21609 r23189 6 6 public class RoadMaxspeedTest extends RoadPropertyTest { 7 7 8 9 10 8 private static void testMaxspeed(float expectedMaxspeed, String maxspeedString) { 9 testEvaluateBoth(new RoadMaxspeed(), expectedMaxspeed, new Tag("maxspeed", maxspeedString)); 10 } 11 11 12 13 14 15 16 12 @Test 13 public void testEvaluate_numeric() { 14 testMaxspeed(30, "30"); 15 testMaxspeed(48.3f, "48.3"); 16 } 17 17 18 19 20 21 22 23 18 @Test 19 public void testEvaluate_kmh() { 20 testMaxspeed(50, "50 km/h"); 21 testMaxspeed(120, "120km/h"); 22 testMaxspeed(30, "30 km/h"); 23 } 24 24 25 26 27 28 29 30 25 @Test 26 public void testEvaluate_mph() { 27 testMaxspeed(72.42048f, "45 mph"); 28 testMaxspeed(64.373764f, "40mph"); 29 testMaxspeed(24.14016f, "15 mph"); 30 } 31 31 32 32 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/property/RoadPropertyTest.java
r16520 r23189 8 8 abstract public class RoadPropertyTest { 9 9 10 10 protected static <P> void testEvaluateW(RoadPropertyType<P> property, P expectedForward, P expectedBackward, Tag... wayTags) { 11 11 12 13 14 15 16 17 12 TestDataSource ds = new TestDataSource(); 13 TestDataSource.TestWay testWay = new TestDataSource.TestWay(); 14 for (Tag tag : wayTags) { 15 testWay.tags.put(tag.key, tag.value); 16 } 17 ds.ways.add(testWay); 18 18 19 20 19 assertEquals(expectedForward, property.evaluateW(testWay, true, null, ds)); 20 assertEquals(expectedBackward, property.evaluateW(testWay, false, null, ds)); 21 21 22 22 } 23 23 24 24 protected static <P> void testEvaluateN(RoadPropertyType<P> property, P expected, Tag... nodeTags) { 25 25 26 27 28 29 30 31 26 TestDataSource ds = new TestDataSource(); 27 TestDataSource.TestNode testNode = new TestDataSource.TestNode(); 28 for (Tag tag : nodeTags) { 29 testNode.tags.put(tag.key, tag.value); 30 } 31 ds.nodes.add(testNode); 32 32 33 33 RoadMaxspeed m = new RoadMaxspeed(); 34 34 35 35 assertEquals(expected, m.evaluateN(testNode, null, ds)); 36 36 37 37 } 38 38 39 40 41 42 39 protected static <P> void testEvaluateBoth(RoadPropertyType<P> property, P expected, Tag... nodeTags) { 40 testEvaluateW(property, expected, expected, nodeTags); 41 testEvaluateN(property, expected, nodeTags); 42 } 43 43 44 44 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/util/TagConditionLogicTest.java
r16520 r23189 15 15 public class TagConditionLogicTest { 16 16 17 18 17 TagGroup groupA; 18 TagGroup groupB; 19 19 20 21 22 23 24 25 26 20 @Before 21 public void setUp() { 22 Map<String, String> mapA = new HashMap<String, String>(); 23 mapA.put("key1", "value1"); 24 mapA.put("key2", "value2"); 25 mapA.put("key3", "value1"); 26 groupA = new MapBasedTagGroup(mapA); 27 27 28 29 30 31 32 28 Map<String, String> mapB = new HashMap<String, String>(); 29 mapB.put("key1", "value1"); 30 mapB.put("key4", "value4"); 31 groupB = new MapBasedTagGroup(mapB); 32 } 33 33 34 35 36 37 38 39 34 @Test 35 public void testTag() { 36 TagCondition condition = TagConditionLogic.tag(new Tag("key3", "value1")); 37 assertTrue(condition.matches(groupA)); 38 assertFalse(condition.matches(groupB)); 39 } 40 40 41 42 43 44 45 46 41 @Test 42 public void testKey() { 43 TagCondition condition = TagConditionLogic.key("key3"); 44 assertTrue(condition.matches(groupA)); 45 assertFalse(condition.matches(groupB)); 46 } 47 47 48 49 50 51 52 48 @Test 49 public void testAnd() { 50 TagCondition condition1 = TagConditionLogic.tag(new Tag("key2", "value2")); 51 TagCondition conditionAnd1a = TagConditionLogic.and(condition1); 52 TagCondition conditionAnd1b = TagConditionLogic.and(Arrays.asList(condition1)); 53 53 54 55 56 57 54 assertTrue(conditionAnd1a.matches(groupA)); 55 assertTrue(conditionAnd1b.matches(groupA)); 56 assertFalse(conditionAnd1a.matches(groupB)); 57 assertFalse(conditionAnd1b.matches(groupB)); 58 58 59 60 61 59 TagCondition condition2 = TagConditionLogic.tag(new Tag("key1", "value1")); 60 TagCondition conditionAnd2a = TagConditionLogic.and(condition1, condition2); 61 TagCondition conditionAnd2b = TagConditionLogic.and(Arrays.asList(condition1, condition2)); 62 62 63 64 65 66 63 assertTrue(conditionAnd2a.matches(groupA)); 64 assertTrue(conditionAnd2b.matches(groupA)); 65 assertFalse(conditionAnd2a.matches(groupB)); 66 assertFalse(conditionAnd2b.matches(groupB)); 67 67 68 69 70 68 TagCondition condition3 = TagConditionLogic.tag(new Tag("key4", "value4")); 69 TagCondition conditionAnd3a = TagConditionLogic.and(condition1, condition2, condition3); 70 TagCondition conditionAnd3b = TagConditionLogic.and(Arrays.asList(condition1, condition2, condition3)); 71 71 72 73 74 75 76 72 assertFalse(conditionAnd3a.matches(groupA)); 73 assertFalse(conditionAnd3b.matches(groupA)); 74 assertFalse(conditionAnd3a.matches(groupB)); 75 assertFalse(conditionAnd3b.matches(groupB)); 76 } 77 77 78 79 80 81 82 78 @Test 79 public void testOr() { 80 TagCondition condition1 = TagConditionLogic.tag(new Tag("key42", "value42")); 81 TagCondition conditionOr1a = TagConditionLogic.or(condition1); 82 TagCondition conditionOr1b = TagConditionLogic.or(Arrays.asList(condition1)); 83 83 84 85 86 87 84 assertFalse(conditionOr1a.matches(groupA)); 85 assertFalse(conditionOr1b.matches(groupA)); 86 assertFalse(conditionOr1a.matches(groupB)); 87 assertFalse(conditionOr1b.matches(groupB)); 88 88 89 90 91 89 TagCondition condition2 = TagConditionLogic.tag(new Tag("key3", "value1")); 90 TagCondition conditionOr2a = TagConditionLogic.or(condition1, condition2); 91 TagCondition conditionOr2b = TagConditionLogic.or(Arrays.asList(condition1, condition2)); 92 92 93 94 95 96 93 assertTrue(conditionOr2a.matches(groupA)); 94 assertTrue(conditionOr2b.matches(groupA)); 95 assertFalse(conditionOr2a.matches(groupB)); 96 assertFalse(conditionOr2b.matches(groupB)); 97 97 98 99 100 98 TagCondition condition3 = TagConditionLogic.tag(new Tag("key1", "value1")); 99 TagCondition conditionOr3a = TagConditionLogic.or(condition1, condition2, condition3); 100 TagCondition conditionOr3b = TagConditionLogic.or(Arrays.asList(condition1, condition2, condition3)); 101 101 102 103 104 105 106 102 assertTrue(conditionOr3a.matches(groupA)); 103 assertTrue(conditionOr3b.matches(groupA)); 104 assertTrue(conditionOr3a.matches(groupB)); 105 assertTrue(conditionOr3b.matches(groupB)); 106 } 107 107 108 109 110 111 112 113 108 @Test 109 public void testNot() { 110 TagCondition condition = TagConditionLogic.not(TagConditionLogic.key("key3")); 111 assertFalse(condition.matches(groupA)); 112 assertTrue(condition.matches(groupB)); 113 } 114 114 115 115 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/util/ValueStringParserTest.java
r20244 r23189 10 10 public class ValueStringParserTest { 11 11 12 12 /* speed */ 13 13 14 15 16 17 14 @Test 15 public void testParseSpeedDefault() { 16 assertClose(50, parseSpeed("50")); 17 } 18 18 19 20 21 22 23 19 @Test 20 public void testParseSpeedKmh() { 21 assertClose(30, parseSpeed("30 km/h")); 22 assertClose(100, parseSpeed("100km/h")); 23 } 24 24 25 26 27 28 29 25 @Test 26 public void testParseSpeedMph() { 27 assertClose(40.234f, parseSpeed("25mph")); 28 assertClose(40.234f, parseSpeed("25 mph")); 29 } 30 30 31 32 33 34 31 @Test 32 public void testParseSpeedInvalid() { 33 assertNull(parseSpeed("lightspeed")); 34 } 35 35 36 36 /* measure */ 37 37 38 39 40 41 38 @Test 39 public void testParseMeasureDefault() { 40 assertClose(3.5f, parseMeasure("3.5")); 41 } 42 42 43 44 45 46 47 43 @Test 44 public void testParseMeasureM() { 45 assertClose(2, parseMeasure("2m")); 46 assertClose(5.5f, parseMeasure("5.5 m")); 47 } 48 48 49 50 51 52 53 49 @Test 50 public void testParseMeasureKm() { 51 assertClose(1000, parseMeasure("1 km")); 52 assertClose(7200, parseMeasure("7.2km")); 53 } 54 54 55 56 57 58 55 @Test 56 public void testParseMeasureMi() { 57 assertClose(1609.344f, parseMeasure("1 mi")); 58 } 59 59 60 61 62 63 64 60 @Test 61 public void testParseMeasureFeetInches() { 62 assertClose(3.6576f, parseMeasure("12'0\"")); 63 assertClose(1.9812f, parseMeasure("6' 6\"")); 64 } 65 65 66 67 68 69 70 66 @Test 67 public void testParseMeasureInvalid() { 68 assertNull(parseMeasure("very long")); 69 assertNull(parseMeasure("6' 16\"")); 70 } 71 71 72 72 /* weight */ 73 73 74 75 76 77 74 @Test 75 public void testParseWeightDefault() { 76 assertClose(3.6f, parseWeight("3.6")); 77 } 78 78 79 80 81 82 83 79 @Test 80 public void testParseWeightT() { 81 assertClose(30, parseWeight("30t")); 82 assertClose(3.5f, parseWeight("3.5 t")); 83 } 84 84 85 86 87 88 85 @Test 86 public void testParseWeightInvalid() { 87 assertNull(parseWeight("heavy")); 88 } 89 89 90 91 92 93 94 90 private static final void assertClose(float expected, float actual) { 91 if (Math.abs(expected - actual) > 0.001) { 92 throw new AssertionError("expected " + expected + ", was " + actual); 93 } 94 } 95 95 96 96 } -
applications/editors/josm/plugins/graphview/test/org/openstreetmap/josm/plugins/graphview/core/visualisation/FloatPropertyColorSchemeTest.java
r16520 r23189 13 13 public class FloatPropertyColorSchemeTest { 14 14 15 15 private FloatPropertyColorScheme subject; 16 16 17 18 17 @Before 18 public void setUp() { 19 19 20 21 22 23 20 Map<Float, Color> colorMap = new HashMap<Float, Color>(); 21 colorMap.put( 5f, new Color( 42, 42, 42)); 22 colorMap.put(10f, new Color(100, 100, 100)); 23 colorMap.put(20f, new Color(200, 200, 200)); 24 24 25 26 25 subject = new FloatPropertyColorScheme(RoadMaxweight.class, colorMap, Color.RED); 26 } 27 27 28 29 30 31 32 28 @Test 29 public void testGetColorForValue_below() { 30 assertEquals(new Color(42, 42, 42), subject.getColorForValue(1f)); 31 assertEquals(new Color(42, 42, 42), subject.getColorForValue(5f)); 32 } 33 33 34 35 36 37 34 @Test 35 public void testGetColorForValue_above() { 36 assertEquals(new Color(200, 200, 200), subject.getColorForValue(25f)); 37 } 38 38 39 40 41 42 39 @Test 40 public void testGetColorForValue_value() { 41 assertEquals(new Color(100, 100, 100), subject.getColorForValue(10f)); 42 } 43 43 44 45 46 47 44 @Test 45 public void testGetColorForValue_interpolate() { 46 assertEquals(new Color(150, 150, 150), subject.getColorForValue(15f)); 47 } 48 48 49 49 } -
applications/editors/josm/plugins/multipoly-convert/src/converttomultipoly/MultipolyAction.java
r20416 r23189 27 27 /** 28 28 * Convert an area into an advance multipolygon. 29 * 29 * 30 30 * New relation with type=multipolygon is created for each ways. 31 * 31 * 32 32 * All the tags (except the source tag) will be moved into the relation. 33 33 */ … … 35 35 public class MultipolyAction extends JosmAction { 36 36 37 38 39 40 41 42 43 37 public MultipolyAction() { 38 super(tr("Convert to multipolygon"), "multipoly_convert", 39 tr("Convert to multipolygon."), Shortcut.registerShortcut( 40 "tools:multipolyconv", tr("Tool: {0}", 41 tr("Convert to multipolygon")), KeyEvent.VK_M, 42 Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true); 43 } 44 44 45 46 47 * 48 49 50 51 45 /** 46 * The action button has been clicked 47 * 48 * @param e 49 * Action Event 50 */ 51 public void actionPerformed(ActionEvent e) { 52 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 53 // Get all ways in some type=multipolygon relation 54 HashSet<OsmPrimitive> relationsInMulti = new HashSet<OsmPrimitive>(); 55 for (Relation r : Main.main.getCurrentDataSet().getRelations()) { 56 if (!r.isUsable()) 57 continue; 58 if (r.get("type") != "multipolygon") 59 continue; 60 for (RelationMember rm : r.getMembers()) { 61 OsmPrimitive m = rm.getMember(); 62 if (m instanceof Way) { 63 relationsInMulti.add(m); 64 } 65 } 66 } 67 67 68 // List of selected ways 69 ArrayList<Way> selectedWays = new ArrayList<Way>(); 70 68 // List of selected ways 69 ArrayList<Way> selectedWays = new ArrayList<Way>(); 71 70 72 // For every selected way73 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) {74 if (osm instanceof Way) {75 Way way = (Way) osm;76 // Check if way is already in another multipolygon77 if (relationsInMulti.contains(osm)) {78 JOptionPane79 .showMessageDialog(80 Main.parent,81 tr("One of the selected ways is already part of another multipolygon."));82 return;83 }84 71 85 selectedWays.add(way); 86 } 87 } 72 // For every selected way 73 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { 74 if (osm instanceof Way) { 75 Way way = (Way) osm; 76 // Check if way is already in another multipolygon 77 if (relationsInMulti.contains(osm)) { 78 JOptionPane 79 .showMessageDialog( 80 Main.parent, 81 tr("One of the selected ways is already part of another multipolygon.")); 82 return; 83 } 88 84 89 if (Main.map == null) { 90 JOptionPane.showMessageDialog(Main.parent, tr("No data loaded.")); 91 return; 92 } 85 selectedWays.add(way); 86 } 87 } 93 88 94 Collection<Command> cmds = new LinkedList<Command>(); 95 // Add ways to it 96 for (int i = 0; i < selectedWays.size(); i++) { 97 Way way = selectedWays.get(i);89 if (Main.map == null) { 90 JOptionPane.showMessageDialog(Main.parent, tr("No data loaded.")); 91 return; 92 } 98 93 99 // Create new relation 100 Relation rel = new Relation(); 101 rel.put("type", "multipolygon"); 94 Collection<Command> cmds = new LinkedList<Command>(); 95 // Add ways to it 96 for (int i = 0; i < selectedWays.size(); i++) { 97 Way way = selectedWays.get(i); 102 98 103 RelationMember rm = new RelationMember("outer", way); 104 rel.addMember(rm); 105 106 for (Iterator<String> keyi = way.getKeys().keySet().iterator() ; keyi.hasNext() ; ) { 107 String key = keyi.next(); 108 rel.put(key, way.get(key)); 109 System.out.println(key); 110 if (key.compareTo("source") != 0) { 111 way.remove(key); 112 } 113 } 114 // Add relation 115 cmds.add(new AddCommand(rel)); 116 } 117 // Commit 118 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), cmds)); 119 Main.map.repaint(); 120 } 99 // Create new relation 100 Relation rel = new Relation(); 101 rel.put("type", "multipolygon"); 121 102 122 /** Enable this action only if something is selected */ 123 @Override 124 protected void updateEnabledState() { 125 if (getCurrentDataSet() == null) { 126 setEnabled(false); 127 } else { 128 updateEnabledState(getCurrentDataSet().getSelected()); 129 } 130 } 103 RelationMember rm = new RelationMember("outer", way); 104 rel.addMember(rm); 131 105 132 /** Enable this action only if something is selected */ 133 @Override 134 protected void updateEnabledState( 135 Collection<? extends OsmPrimitive> selection) { 136 setEnabled(selection != null && !selection.isEmpty()); 137 } 106 for (Iterator<String> keyi = way.getKeys().keySet().iterator() ; keyi.hasNext() ; ) { 107 String key = keyi.next(); 108 rel.put(key, way.get(key)); 109 System.out.println(key); 110 if (key.compareTo("source") != 0) { 111 way.remove(key); 112 } 113 } 114 // Add relation 115 cmds.add(new AddCommand(rel)); 116 } 117 // Commit 118 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), cmds)); 119 Main.map.repaint(); 120 } 121 122 /** Enable this action only if something is selected */ 123 @Override 124 protected void updateEnabledState() { 125 if (getCurrentDataSet() == null) { 126 setEnabled(false); 127 } else { 128 updateEnabledState(getCurrentDataSet().getSelected()); 129 } 130 } 131 132 /** Enable this action only if something is selected */ 133 @Override 134 protected void updateEnabledState( 135 Collection<? extends OsmPrimitive> selection) { 136 setEnabled(selection != null && !selection.isEmpty()); 137 } 138 138 } -
applications/editors/josm/plugins/multipoly-convert/src/converttomultipoly/MultipolyPlugin.java
r20416 r23189 15 15 public class MultipolyPlugin extends Plugin { 16 16 17 17 protected String name; 18 18 19 19 // public MultipolyPlugin(PluginInformation info) { 20 20 public MultipolyPlugin(PluginInformation info) { 21 22 23 24 25 26 27 28 29 30 21 super(info); 22 name = tr("Convert to multipolygon"); 23 JMenu toolsMenu = null; 24 for (int i = 0; i < Main.main.menu.getMenuCount() && toolsMenu == null; i++) { 25 JMenu menu = Main.main.menu.getMenu(i); 26 String name = menu.getText(); 27 if (name != null && name.equals(tr("Tools"))) { 28 toolsMenu = menu; 29 } 30 } 31 31 32 33 34 35 36 37 38 39 40 32 if (toolsMenu == null) { 33 toolsMenu = new JMenu(name); 34 toolsMenu.add(new JMenuItem(new MultipolyAction())); 35 Main.main.menu.add(toolsMenu, 2); 36 } else { 37 toolsMenu.addSeparator(); 38 toolsMenu.add(new JMenuItem(new MultipolyAction())); 39 } 40 } 41 41 } -
applications/editors/josm/plugins/multipoly/src/multipoly/MultipolyAction.java
r19456 r23189 30 30 /** 31 31 * Create multipolygon from selected ways automatically. 32 * 32 * 33 33 * New relation with type=multipolygon is created 34 * 34 * 35 35 * If one or more of ways is already in relation with type=multipolygon or the 36 36 * way is not closed, then error is reported and no relation is created 37 * 37 * 38 38 * The "inner" and "outer" roles are guessed automatically. First, bbox is 39 39 * calculated for each way. then the largest area is assumed to be outside and … … 45 45 public class MultipolyAction extends JosmAction { 46 46 47 48 49 50 51 52 53 47 public MultipolyAction() { 48 super(tr("Create multipolygon"), "multipoly_create", 49 tr("Create multipolygon."), Shortcut.registerShortcut( 50 "tools:multipoly", tr("Tool: {0}", 51 tr("Create multipolygon")), KeyEvent.VK_M, 52 Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true); 53 } 54 54 55 56 57 * 58 59 60 61 55 /** 56 * The action button has been clicked 57 * 58 * @param e 59 * Action Event 60 */ 61 public void actionPerformed(ActionEvent e) { 62 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 63 // Get all ways in some type=multipolygon relation 64 HashSet<OsmPrimitive> relationsInMulti = new HashSet<OsmPrimitive>(); 65 for (Relation r : Main.main.getCurrentDataSet().getRelations()) { 66 if (!r.isUsable()) 67 continue; 68 if (r.get("type") != "multipolygon") 69 continue; 70 for (RelationMember rm : r.getMembers()) { 71 OsmPrimitive m = rm.getMember(); 72 if (m instanceof Way) { 73 relationsInMulti.add(m); 74 } 75 } 76 } 77 77 78 79 80 81 82 83 78 // List of selected ways 79 List<Way> selectedWays = new ArrayList<Way>(); 80 // Area of largest way (in square degrees) 81 double maxarea = 0; 82 // Which way is the largest one (outer) 83 Way maxWay = null; 84 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 85 // For every selected way 86 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { 87 if (osm instanceof Way) { 88 Way way = (Way) osm; 89 // Check if way is already in another multipolygon 90 if (relationsInMulti.contains(osm)) { 91 JOptionPane 92 .showMessageDialog( 93 Main.parent, 94 tr("One of the selected ways is already part of another multipolygon.")); 95 return; 96 } 97 EastNorth first = null, last = null; 98 // Boundingbox of way 99 double minx = 9999, miny = 9999, maxx = -9999, maxy = -9999; 100 for (Pair<Node, Node> seg : way.getNodePairs(false)) { 101 if (first == null) 102 first = seg.a.getEastNorth(); 103 last = seg.b.getEastNorth(); 104 double x = seg.a.getEastNorth().east(); 105 double y = seg.a.getEastNorth().north(); 106 if (x < minx) 107 minx = x; 108 if (y < miny) 109 miny = y; 110 if (x > maxx) 111 maxx = x; 112 if (y > maxy) 113 maxy = y; 114 } 115 // Check if first and last node are the same 116 if (!first.equals(last)) { 117 JOptionPane 118 .showMessageDialog( 119 Main.parent, 120 tr("Multipolygon must consist only of closed ways.")); 121 return; 122 } 123 // Determine area 124 double area = (maxx - minx) * (maxy - miny); 125 selectedWays.add(way); 126 if (area > maxarea) { 127 maxarea = area; 128 maxWay = way; 129 } 130 } 131 } 132 132 133 134 135 136 133 if (Main.map == null) { 134 JOptionPane.showMessageDialog(Main.parent, tr("No data loaded.")); 135 return; 136 } 137 137 138 139 140 141 142 138 if (selectedWays.size() < 2) { 139 JOptionPane.showMessageDialog(Main.parent, 140 tr("You must select at least two ways.")); 141 return; 142 } 143 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 144 Collection<Command> cmds = new LinkedList<Command>(); 145 // Create new relation 146 Relation rel = new Relation(); 147 rel.put("type", "multipolygon"); 148 // Add ways to it 149 for (int i = 0; i < selectedWays.size(); i++) { 150 Way s = selectedWays.get(i); 151 String xrole = "inner"; 152 if (s == maxWay) 153 xrole = "outer"; 154 RelationMember rm = new RelationMember(xrole, s); 155 rel.addMember(rm); 156 } 157 // Add relation 158 cmds.add(new AddCommand(rel)); 159 // Commit 160 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), 161 cmds)); 162 Main.map.repaint(); 163 } 164 164 165 166 167 168 169 170 171 172 173 165 /** Enable this action only if something is selected */ 166 @Override 167 protected void updateEnabledState() { 168 if (getCurrentDataSet() == null) { 169 setEnabled(false); 170 } else { 171 updateEnabledState(getCurrentDataSet().getSelected()); 172 } 173 } 174 174 175 176 177 178 179 180 175 /** Enable this action only if something is selected */ 176 @Override 177 protected void updateEnabledState( 178 Collection<? extends OsmPrimitive> selection) { 179 setEnabled(selection != null && !selection.isEmpty()); 180 } 181 181 } -
applications/editors/josm/plugins/multipoly/src/multipoly/MultipolyPlugin.java
r19456 r23189 15 15 public class MultipolyPlugin extends Plugin { 16 16 17 17 protected String name; 18 18 19 20 21 22 23 24 25 26 27 28 29 19 public MultipolyPlugin(PluginInformation info) { 20 super(info); 21 name = tr("Create multipolygon"); 22 JMenu toolsMenu = null; 23 for (int i = 0; i < Main.main.menu.getMenuCount() && toolsMenu == null; i++) { 24 JMenu menu = Main.main.menu.getMenu(i); 25 String name = menu.getText(); 26 if (name != null && name.equals(tr("Tools"))) { 27 toolsMenu = menu; 28 } 29 } 30 30 31 32 33 34 35 36 37 38 39 31 if (toolsMenu == null) { 32 toolsMenu = new JMenu(name); 33 toolsMenu.add(new JMenuItem(new MultipolyAction())); 34 Main.main.menu.add(toolsMenu, 2); 35 } else { 36 toolsMenu.addSeparator(); 37 toolsMenu.add(new JMenuItem(new MultipolyAction())); 38 } 39 } 40 40 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/PermissionPref.java
r22733 r23189 7 7 * 8 8 * Use @see PermissionPrefWithDefault instead of this class. 9 * 9 * 10 10 * @author Bodo Meissner 11 11 */ 12 12 @Deprecated 13 13 public class PermissionPref { 14 15 16 17 18 19 20 21 22 23 14 /** name of the preference setting to permit the remote operation */ 15 String pref; 16 /** message to be displayed if operation is not permitted */ 17 String message; 18 19 public PermissionPref(String pref, String message) 20 { 21 this.pref = pref; 22 this.message = message; 23 } 24 24 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/PermissionPrefWithDefault.java
r22733 r23189 2 2 3 3 /** 4 * This class should replace PermissionPref because it allows explicit 4 * This class should replace PermissionPref because it allows explicit 5 5 * specification of the permission's default value. 6 * 6 * 7 7 * @author Bodo Meissner 8 8 */ … … 10 10 public class PermissionPrefWithDefault extends PermissionPref { 11 11 12 12 boolean defaultVal = true; 13 13 14 15 16 17 14 public PermissionPrefWithDefault(String pref, boolean defaultVal, String message) { 15 super(pref, message); 16 this.defaultVal = defaultVal; 17 } 18 18 19 20 21 19 public PermissionPrefWithDefault(PermissionPref prefWithoutDefault) { 20 super(prefWithoutDefault.pref, prefWithoutDefault.message); 21 } 22 22 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RemoteControlPlugin.java
r22733 r23189 8 8 9 9 /** 10 * Base plugin for remote control operations. 10 * Base plugin for remote control operations. 11 11 * This plugin contains operations that use JOSM core only. 12 * 13 * Other plugins can register additional operations by calling 12 * 13 * Other plugins can register additional operations by calling 14 14 * @see addRequestHandler(). 15 15 * To allow API changes this plugin contains a @see getVersion() method. 16 * 16 * 17 17 * IMPORTANT! increment the minor version on compatible API extensions 18 18 * and increment the major version and set minor to 0 on incompatible changes. … … 20 20 public class RemoteControlPlugin extends Plugin 21 21 { 22 23 24 25 26 27 28 29 30 31 32 33 34 35 22 /** API version 23 * IMPORTANT! update the version number on API changes. 24 */ 25 static final int apiMajorVersion = 1; 26 static final int apiMinorVersion = 0; 27 28 /** 29 * RemoteControl HTTP protocol version. Change minor number for compatible 30 * interface extensions. Change major number in case of incompatible 31 * changes. 32 */ 33 static final int protocolMajorVersion = 1; 34 static final int protocolMinorVersion = 2; 35 36 36 /** The HTTP server this plugin launches */ 37 37 static HttpServer server; 38 38 39 39 /** 40 * Returns an array of int values with major and minor API version 40 * Returns an array of int values with major and minor API version 41 41 * and major and minor HTTP protocol version. 42 * 42 * 43 43 * The function returns an int[4] instead of an object with fields 44 44 * to avoid ClassNotFound errors with old versions of remotecontrol. 45 * 46 * @return array of integer version numbers: 45 * 46 * @return array of integer version numbers: 47 47 * apiMajorVersion, apiMinorVersion, protocolMajorVersion, protocolMajorVersion 48 48 */ 49 49 public int[] getVersion() 50 50 { 51 52 51 int versions[] = {apiMajorVersion, apiMinorVersion, protocolMajorVersion, protocolMajorVersion}; 52 return versions; 53 53 } 54 54 55 55 /** 56 56 * Creates the plugin, and starts the HTTP server … … 58 58 public RemoteControlPlugin(PluginInformation info) 59 59 { 60 61 62 63 64 60 super(info); 61 /* 62 System.out.println("constructor " + this.getClass().getName() + " (" + info.name + 63 " v " + info.version + " stage " + info.stage + ")"); 64 */ 65 65 restartServer(); 66 66 } … … 103 103 RequestProcessor.addRequestHandlerClass(command, handlerClass); 104 104 } 105 105 106 106 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestHandler.java
r22733 r23189 11 11 12 12 /** 13 * This is the parent of all classes that handle a specific command 13 * This is the parent of all classes that handle a specific command 14 14 * in remote control plug-in. 15 * 15 * 16 16 * @author Bodo Meissner 17 17 */ 18 18 public abstract class RequestHandler 19 19 { 20 21 22 23 24 25 26 20 public static final String globalConfirmationKey = "remotecontrol.always-confirm"; 21 public static final boolean globalConfirmationDefault = false; 22 23 /** The GET request arguments */ 24 protected HashMap<String,String> args; 25 26 /** The request URL without "GET". */ 27 27 protected String request; 28 28 … … 34 34 /** will be filled with the command assigned to the subclass */ 35 35 protected String myCommand; 36 36 37 37 /** 38 38 * Check permission and parameters and handle request. 39 * 39 * 40 40 * @throws RequestHandlerForbiddenException 41 41 * @throws RequestHandlerBadRequestException … … 44 44 final void handle() throws RequestHandlerForbiddenException, RequestHandlerBadRequestException, RequestHandlerErrorException 45 45 { 46 47 48 49 } 50 46 checkPermission(); 47 checkMandatoryParams(); 48 handleRequest(); 49 } 50 51 51 /** 52 52 * Handle a specific command sent as remote control. 53 * 54 * This method of the subclass will do the real work. 55 * 53 * 54 * This method of the subclass will do the real work. 55 * 56 56 * @throws RequestHandlerErrorException 57 * @throws RequestHandlerBadRequestException 57 * @throws RequestHandlerBadRequestException 58 58 */ 59 59 protected abstract void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException; … … 62 62 * Get a specific message to ask the user for permission for the operation 63 63 * requested via remote control. 64 * 64 * 65 65 * This message will be displayed to the user if the preference 66 66 * remotecontrol.always-confirm is true. 67 * 67 * 68 68 * @return the message 69 69 */ … … 74 74 * preference to individually allow the requested operation and an error 75 75 * message to be displayed when a disabled operation is requested. 76 * 77 * Default is not to check any special preference. Override this in a 76 * 77 * Default is not to check any special preference. Override this in a 78 78 * subclass to define permission preference and error message. 79 * 79 * 80 80 * @return the preference name and error message or null 81 81 */ 82 83 82 @SuppressWarnings("deprecation") 83 public PermissionPref getPermissionPref() 84 84 { 85 85 /* Example: … … 93 93 protected String[] getMandatoryParams() 94 94 { 95 96 } 97 98 /** 99 * Check permissions in preferences and display error message 95 return null; 96 } 97 98 /** 99 * Check permissions in preferences and display error message 100 100 * or ask for permission. 101 * 101 * 102 102 * @throws RequestHandlerForbiddenException 103 103 */ 104 104 @SuppressWarnings("deprecation") 105 106 { 107 /* 105 final public void checkPermission() throws RequestHandlerForbiddenException 106 { 107 /* 108 108 * If the subclass defines a specific preference and if this is set 109 109 * to false, abort with an error message. 110 * 110 * 111 111 * Note: we use the deprecated class here for compatibility with 112 112 * older versions of WMSPlugin. … … 118 118 if(permissionPref instanceof PermissionPrefWithDefault) 119 119 { 120 121 } 122 else 120 permissionPrefWithDefault = (PermissionPrefWithDefault) permissionPref; 121 } 122 else 123 123 { 124 124 permissionPrefWithDefault = new PermissionPrefWithDefault(permissionPref); 125 125 } 126 126 if (!Main.pref.getBoolean(permissionPrefWithDefault.pref, 127 127 permissionPrefWithDefault.defaultVal)) { 128 128 System.out.println(permissionPrefWithDefault.message); 129 129 throw new RequestHandlerForbiddenException(); … … 147 147 /** 148 148 * Set request URL and parse args. 149 * 149 * 150 150 * @param url The request URL. 151 151 */ 152 153 154 155 156 157 158 159 160 * 161 162 163 164 165 166 167 168 169 170 171 172 152 public void setUrl(String url) { 153 this.request = url; 154 parseArgs(); 155 } 156 157 /** 158 * Parse the request parameters as key=value pairs. 159 * The result will be stored in this.args. 160 * 161 * Can be overridden by subclass. 162 */ 163 protected void parseArgs() { 164 StringTokenizer st = new StringTokenizer(this.request, "&?"); 165 HashMap<String, String> args = new HashMap<String, String>(); 166 // ignore first token which is the command 167 if(st.hasMoreTokens()) st.nextToken(); 168 while (st.hasMoreTokens()) { 169 String param = st.nextToken(); 170 int eq = param.indexOf("="); 171 if (eq > -1) 172 args.put(param.substring(0, eq), 173 173 param.substring(eq + 1)); 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 * 200 201 202 203 204 205 206 174 } 175 this.args = args; 176 } 177 178 void checkMandatoryParams() throws RequestHandlerBadRequestException 179 { 180 String[] mandatory = getMandatoryParams(); 181 if(mandatory == null) return; 182 183 boolean error = false; 184 for(int i = 0; i < mandatory.length; ++i) 185 { 186 String key = mandatory[i]; 187 String value = args.get(key); 188 if((value == null) || (value.length() == 0)) 189 { 190 error = true; 191 System.out.println("'" + myCommand + "' remote control request must have '" + key + "' parameter"); 192 } 193 } 194 if(error) throw new RequestHandlerBadRequestException(); 195 } 196 197 /** 198 * Save command associated with this handler. 199 * 200 * @param command The command. 201 */ 202 public void setCommand(String command) 203 { 204 if(command.charAt(0) == '/') command = command.substring(1); 205 myCommand = command; 206 } 207 207 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestHandlerForbiddenException.java
r22675 r23189 2 2 3 3 public class RequestHandlerForbiddenException extends RequestHandlerException { 4 4 private static final long serialVersionUID = 2263904699747115423L; 5 5 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestProcessor.java
r22734 r23189 23 23 */ 24 24 public class RequestProcessor extends Thread { 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 * 48 49 50 51 52 53 54 55 56 57 58 * 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 * 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 * 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 * 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 * 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 * 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 25 /** 26 * RemoteControl protocol version. Change minor number for compatible 27 * interface extensions. Change major number in case of incompatible 28 * changes. 29 */ 30 public static final String PROTOCOLVERSION = "{\"protocolversion\": {\"major\": " + 31 RemoteControlPlugin.protocolMajorVersion + ", \"minor\": " + 32 RemoteControlPlugin.protocolMinorVersion + 33 "}, \"application\": \"JOSM RemoteControl\"}"; 34 35 /** The socket this processor listens on */ 36 private Socket request; 37 38 /** 39 * Collection of request handlers. 40 * Will be initialized with default handlers here. Other plug-ins 41 * can extend this list by using @see addRequestHandler 42 */ 43 private static HashMap<String, Class<? extends RequestHandler>> handlers = new HashMap<String, Class<? extends RequestHandler>>(); 44 45 /** 46 * Constructor 47 * 48 * @param request A socket to read the request. 49 */ 50 public RequestProcessor(Socket request) { 51 super("RemoteControl request processor"); 52 this.setDaemon(true); 53 this.request = request; 54 } 55 56 /** 57 * Spawns a new thread for the request 58 * 59 * @param request 60 * The WMS request 61 */ 62 public static void processRequest(Socket request) { 63 RequestProcessor processor = new RequestProcessor(request); 64 processor.start(); 65 } 66 67 /** 68 * Add external request handler. Can be used by other plug-ins that 69 * want to use remote control. 70 * @param command The command to handle. 71 * @param handler The additional request handler. 72 */ 73 static void addRequestHandlerClass(String command, 74 Class<? extends RequestHandler> handler) { 75 addRequestHandlerClass(command, handler, false); 76 } 77 78 /** 79 * Add external request handler. Message can be suppressed. 80 * (for internal use) 81 * @param command The command to handle. 82 * @param handler The additional request handler. 83 * @param silent Don't show message if true. 84 */ 85 private static void addRequestHandlerClass(String command, 86 Class<? extends RequestHandler> handler, boolean silent) { 87 if(command.charAt(0) == '/') 88 { 89 command = command.substring(1); 90 } 91 String commandWithSlash = "/" + command; 92 if (handlers.get(commandWithSlash) != null) { 93 System.out.println("RemoteControl: ignoring duplicate command " + command 94 + " with handler " + handler.getName()); 95 } else { 96 if(!silent) System.out.println("RemoteControl: adding command \"" + 97 command + "\" (handled by " + handler.getSimpleName() + ")"); 98 handlers.put(commandWithSlash, handler); 99 } 100 } 101 102 /** Add default request handlers */ 103 static { 104 addRequestHandlerClass(LoadAndZoomHandler.command, 105 LoadAndZoomHandler.class, true); 106 addRequestHandlerClass(LoadAndZoomHandler.command2, 107 LoadAndZoomHandler.class, true); 108 addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true); 109 addRequestHandlerClass(ImportHandler.command, ImportHandler.class, true); 110 addRequestHandlerClass(VersionHandler.command, VersionHandler.class, true); 111 } 112 113 /** 114 * The work is done here. 115 */ 116 public void run() { 117 Writer out = null; 118 try { 119 OutputStream raw = new BufferedOutputStream( 120 request.getOutputStream()); 121 out = new OutputStreamWriter(raw); 122 Reader in = new InputStreamReader(new BufferedInputStream( 123 request.getInputStream()), "ASCII"); 124 125 StringBuffer requestLine = new StringBuffer(); 126 while (requestLine.length() < 1024) { 127 int c = in.read(); 128 if (c == '\r' || c == '\n') 129 break; 130 requestLine.append((char) c); 131 } 132 133 System.out.println("RemoteControl received: " + requestLine); 134 String get = requestLine.toString(); 135 StringTokenizer st = new StringTokenizer(get); 136 if (!st.hasMoreTokens()) { 137 sendError(out); 138 return; 139 } 140 String method = st.nextToken(); 141 if (!st.hasMoreTokens()) { 142 sendError(out); 143 return; 144 } 145 String url = st.nextToken(); 146 147 if (!method.equals("GET")) { 148 sendNotImplemented(out); 149 return; 150 } 151 152 String command = null; 153 int questionPos = url.indexOf('?'); 154 if(questionPos < 0) 155 { 156 command = url; 157 } 158 else 159 { 160 command = url.substring(0, questionPos); 161 } 162 163 // find a handler for this command 164 Class<? extends RequestHandler> handlerClass = handlers 165 .get(command); 166 if (handlerClass == null) { 167 // no handler found 168 sendBadRequest(out); 169 } else { 170 // create handler object 171 RequestHandler handler = handlerClass.newInstance(); 172 try { 173 handler.setCommand(command); 174 handler.setUrl(url); 175 handler.checkPermission(); 176 handler.handle(); 177 sendHeader(out, "200 OK", handler.contentType, false); 178 out.write("Content-length: " + handler.content.length() 179 + "\r\n"); 180 out.write("\r\n"); 181 out.write(handler.content); 182 out.flush(); 183 } catch (RequestHandlerErrorException ex) { 184 sendError(out); 185 } catch (RequestHandlerBadRequestException ex) { 186 sendBadRequest(out); 187 } catch (RequestHandlerForbiddenException ex) { 188 sendForbidden(out); 189 } 190 } 191 192 } catch (IOException ioe) { 193 } catch (Exception e) { 194 e.printStackTrace(); 195 try { 196 sendError(out); 197 } catch (IOException e1) { 198 } 199 } finally { 200 try { 201 request.close(); 202 } catch (IOException e) { 203 } 204 } 205 } 206 207 /** 208 * Sends a 500 error: server error 209 * 210 * @param out 211 * The writer where the error is written 212 * @throws IOException 213 * If the error can not be written 214 */ 215 private void sendError(Writer out) throws IOException { 216 sendHeader(out, "500 Internal Server Error", "text/html", true); 217 out.write("<HTML>\r\n"); 218 out.write("<HEAD><TITLE>Internal Error</TITLE>\r\n"); 219 out.write("</HEAD>\r\n"); 220 out.write("<BODY>"); 221 out.write("<H1>HTTP Error 500: Internal Server Error</h2>\r\n"); 222 out.write("</BODY></HTML>\r\n"); 223 out.flush(); 224 } 225 226 /** 227 * Sends a 501 error: not implemented 228 * 229 * @param out 230 * The writer where the error is written 231 * @throws IOException 232 * If the error can not be written 233 */ 234 private void sendNotImplemented(Writer out) throws IOException { 235 sendHeader(out, "501 Not Implemented", "text/html", true); 236 out.write("<HTML>\r\n"); 237 out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n"); 238 out.write("</HEAD>\r\n"); 239 out.write("<BODY>"); 240 out.write("<H1>HTTP Error 501: Not Implemented</h2>\r\n"); 241 out.write("</BODY></HTML>\r\n"); 242 out.flush(); 243 } 244 245 /** 246 * Sends a 403 error: forbidden 247 * 248 * @param out 249 * The writer where the error is written 250 * @throws IOException 251 * If the error can not be written 252 */ 253 private void sendForbidden(Writer out) throws IOException { 254 sendHeader(out, "403 Forbidden", "text/html", true); 255 out.write("<HTML>\r\n"); 256 out.write("<HEAD><TITLE>Forbidden</TITLE>\r\n"); 257 out.write("</HEAD>\r\n"); 258 out.write("<BODY>"); 259 out.write("<H1>HTTP Error 403: Forbidden</h2>\r\n"); 260 out.write("</BODY></HTML>\r\n"); 261 out.flush(); 262 } 263 264 /** 265 * Sends a 403 error: forbidden 266 * 267 * @param out 268 * The writer where the error is written 269 * @throws IOException 270 * If the error can not be written 271 */ 272 private void sendBadRequest(Writer out) throws IOException { 273 sendHeader(out, "400 Bad Request", "text/html", true); 274 out.write("<HTML>\r\n"); 275 out.write("<HEAD><TITLE>Bad Request</TITLE>\r\n"); 276 out.write("</HEAD>\r\n"); 277 out.write("<BODY>"); 278 out.write("<H1>HTTP Error 400: Bad Request</h2>\r\n"); 279 out.write("</BODY></HTML>\r\n"); 280 out.flush(); 281 } 282 283 /** 284 * Send common HTTP headers to the client. 285 * 286 * @param out 287 * The Writer 288 * @param status 289 * The status string ("200 OK", "500", etc) 290 * @param contentType 291 * The content type of the data sent 292 * @param endHeaders 293 * If true, adds a new line, ending the headers. 294 * @throws IOException 295 * When error 296 */ 297 private void sendHeader(Writer out, String status, String contentType, 298 boolean endHeaders) throws IOException { 299 out.write("HTTP/1.1 " + status + "\r\n"); 300 Date now = new Date(); 301 out.write("Date: " + now + "\r\n"); 302 out.write("Server: JOSM RemoteControl\r\n"); 303 out.write("Content-type: " + contentType + "\r\n"); 304 out.write("Access-Control-Allow-Origin: *\r\n"); 305 if (endHeaders) 306 out.write("\r\n"); 307 } 308 308 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/AddNodeHandler.java
r22733 r23189 17 17 public class AddNodeHandler extends RequestHandler { 18 18 19 20 21 19 public static final String command = "add_node"; 20 public static final String permissionKey = "remotecontrol.permission.create-objects"; 21 public static final boolean permissionDefault = false; 22 22 23 24 23 @Override 24 protected void handleRequest() { 25 25 addNode(args); 26 26 } 27 27 28 @Override 29 protected String[] getMandatoryParams() 30 { 31 return new String[] { "lat", "lon" }; 32 } 33 34 @Override 35 public String getPermissionMessage() { 36 return tr("Remote Control has been asked to create a new node."); 37 } 28 @Override 29 protected String[] getMandatoryParams() 30 { 31 return new String[] { "lat", "lon" }; 32 } 38 33 39 @Override 40 public PermissionPrefWithDefault getPermissionPref() 41 { 42 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 43 "RemoteControl: creating objects forbidden by preferences"); 44 } 45 34 @Override 35 public String getPermissionMessage() { 36 return tr("Remote Control has been asked to create a new node."); 37 } 38 39 @Override 40 public PermissionPrefWithDefault getPermissionPref() 41 { 42 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 43 "RemoteControl: creating objects forbidden by preferences"); 44 } 45 46 46 /** 47 47 * Adds a node, implements the GET /add_node?lon=...&lat=... request. -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/ImportHandler.java
r22733 r23189 16 16 public class ImportHandler extends RequestHandler { 17 17 18 19 20 18 public static final String command = "import"; 19 public static final String permissionKey = "remotecontrol.permission.import"; 20 public static final boolean permissionDefault = true; 21 21 22 23 22 @Override 23 protected void handleRequest() throws RequestHandlerErrorException { 24 24 try { 25 25 DownloadTask osmTask = new DownloadOsmTask(); … … 30 30 throw new RequestHandlerErrorException(); 31 31 } 32 32 } 33 33 34 35 36 37 38 39 40 41 42 34 @Override 35 protected String[] getMandatoryParams() 36 { 37 return new String[] { "url" }; 38 } 39 40 @Override 41 public String getPermissionMessage() { 42 return tr("Remote Control has been asked to import data from the following URL:") + 43 43 "<br>" + request; 44 44 } 45 45 46 47 48 49 50 51 46 @Override 47 public PermissionPrefWithDefault getPermissionPref() 48 { 49 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 50 "RemoteControl: import forbidden by preferences"); 51 } 52 52 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/LoadAndZoomHandler.java
r22733 r23189 29 29 public class LoadAndZoomHandler extends RequestHandler 30 30 { 31 32 33 34 35 36 37 38 39 40 31 public static final String command = "load_and_zoom"; 32 public static final String command2 = "zoom"; 33 34 public static final String loadDataPermissionKey = "remotecontrol.permission.load-data"; 35 public static final boolean loadDataPermissionDefault = true; 36 public static final String changeSelectionPermissionKey = "remotecontrol.permission.change-selection"; 37 public static final boolean changeSelectionPermissionDefault = true; 38 public static final String changeViewportPermissionKey = "remotecontrol.permission.change-viewport"; 39 public static final boolean changeViewportPermissionDefault = true; 40 41 41 @Override 42 42 public String getPermissionMessage() 43 43 { 44 44 return tr("Remote Control has been asked to load data from the API.") + 45 45 "<br>" + tr("Request details: {0}", request); 46 46 } 47 47 48 @Override 49 protected String[] getMandatoryParams() 50 { 51 return new String[] { "bottom", "top", "left", "right" }; 52 } 53 54 @Override 55 protected void handleRequest() throws RequestHandlerErrorException 56 { 57 DownloadTask osmTask = new DownloadOsmTask(); 58 double minlat = 0; 59 double maxlat = 0; 60 double minlon = 0; 61 double maxlon = 0; 62 try { 63 minlat = Double.parseDouble(args.get("bottom")); 64 maxlat = Double.parseDouble(args.get("top")); 65 minlon = Double.parseDouble(args.get("left")); 66 maxlon = Double.parseDouble(args.get("right")); 48 @Override 49 protected String[] getMandatoryParams() 50 { 51 return new String[] { "bottom", "top", "left", "right" }; 52 } 67 53 68 if(command.equals(myCommand)) 69 { 70 if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault)) 71 { 72 System.out.println("RemoteControl: download forbidden by preferences"); 73 } 74 else 75 { 76 77 // find out whether some data has already been downloaded 78 Area present = null; 79 Area toDownload = null; 80 DataSet ds = Main.main.getCurrentDataSet(); 81 if (ds != null) 82 present = ds.getDataSourceArea(); 83 if (present != null && !present.isEmpty()) { 84 toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat)); 85 toDownload.subtract(present); 86 if (!toDownload.isEmpty()) 87 { 88 // the result might not be a rectangle (L shaped etc) 89 Rectangle2D downloadBounds = toDownload.getBounds2D(); 90 minlat = downloadBounds.getMinY(); 91 minlon = downloadBounds.getMinX(); 92 maxlat = downloadBounds.getMaxY(); 93 maxlon = downloadBounds.getMaxX(); 94 } 95 } 96 if((toDownload != null) && toDownload.isEmpty()) 97 { 98 System.out.println("RemoteControl: no download necessary"); 99 } 100 else 101 { 102 Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */); 103 Main.worker.submit(new PostDownloadHandler(osmTask, future)); 104 } 105 } 106 } 107 } catch (Exception ex) { 108 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:"); 109 ex.printStackTrace(); 110 throw new RequestHandlerErrorException(); 111 } 112 if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) { 113 // select objects after downloading, zoom to selection. 114 final String selection = args.get("select"); 115 Main.worker.execute(new Runnable() { 116 public void run() { 117 HashSet<Long> ways = new HashSet<Long>(); 118 HashSet<Long> nodes = new HashSet<Long>(); 119 HashSet<Long> relations = new HashSet<Long>(); 120 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>(); 121 for (String item : selection.split(",")) { 122 if (item.startsWith("way")) { 123 ways.add(Long.parseLong(item.substring(3))); 124 } else if (item.startsWith("node")) { 125 nodes.add(Long.parseLong(item.substring(4))); 126 } else if (item.startsWith("relation")) { 127 relations.add(Long.parseLong(item.substring(8))); 128 } else if (item.startsWith("rel")) { 129 relations.add(Long.parseLong(item.substring(3))); 130 } else { 131 System.out.println("RemoteControl: invalid selection '"+item+"' ignored"); 132 } 133 } 134 DataSet ds = Main.main.getCurrentDataSet(); 135 if(ds == null) // e.g. download failed 136 return; 137 for (Way w : ds.getWays()) if (ways.contains(w.getId())) newSel.add(w); 138 for (Node n : ds.getNodes()) if (nodes.contains(n.getId())) newSel.add(n); 139 for (Relation r : ds.getRelations()) if (relations.contains(r.getId())) newSel.add(r); 140 ds.setSelected(newSel); 141 if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) 142 new AutoScaleAction("selection").actionPerformed(null); 143 } 144 }); 145 } else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) { 146 // after downloading, zoom to downloaded area. 147 zoom(minlat, maxlat, minlon, maxlon); 148 } 149 } 54 @Override 55 protected void handleRequest() throws RequestHandlerErrorException 56 { 57 DownloadTask osmTask = new DownloadOsmTask(); 58 double minlat = 0; 59 double maxlat = 0; 60 double minlon = 0; 61 double maxlon = 0; 62 try { 63 minlat = Double.parseDouble(args.get("bottom")); 64 maxlat = Double.parseDouble(args.get("top")); 65 minlon = Double.parseDouble(args.get("left")); 66 maxlon = Double.parseDouble(args.get("right")); 150 67 151 protected void zoom(double minlat, double maxlat, double minlon, double maxlon) { 152 final Bounds bounds = new Bounds(new LatLon(minlat, minlon), 153 new LatLon(maxlat, maxlon)); 68 if(command.equals(myCommand)) 69 { 70 if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault)) 71 { 72 System.out.println("RemoteControl: download forbidden by preferences"); 73 } 74 else 75 { 154 76 155 // make sure this isn't called unless there *is* a MapView 156 // 157 if (Main.map != null && Main.map.mapView != null) { 158 Main.worker.execute(new Runnable() { 159 public void run() { 160 BoundingXYVisitor bbox = new BoundingXYVisitor(); 161 bbox.visit(bounds); 162 Main.map.mapView.recalculateCenterScale(bbox); 163 } 164 }); 165 } 166 } 77 // find out whether some data has already been downloaded 78 Area present = null; 79 Area toDownload = null; 80 DataSet ds = Main.main.getCurrentDataSet(); 81 if (ds != null) 82 present = ds.getDataSourceArea(); 83 if (present != null && !present.isEmpty()) { 84 toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat)); 85 toDownload.subtract(present); 86 if (!toDownload.isEmpty()) 87 { 88 // the result might not be a rectangle (L shaped etc) 89 Rectangle2D downloadBounds = toDownload.getBounds2D(); 90 minlat = downloadBounds.getMinY(); 91 minlon = downloadBounds.getMinX(); 92 maxlat = downloadBounds.getMaxY(); 93 maxlon = downloadBounds.getMaxX(); 94 } 95 } 96 if((toDownload != null) && toDownload.isEmpty()) 97 { 98 System.out.println("RemoteControl: no download necessary"); 99 } 100 else 101 { 102 Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */); 103 Main.worker.submit(new PostDownloadHandler(osmTask, future)); 104 } 105 } 106 } 107 } catch (Exception ex) { 108 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:"); 109 ex.printStackTrace(); 110 throw new RequestHandlerErrorException(); 111 } 112 if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) { 113 // select objects after downloading, zoom to selection. 114 final String selection = args.get("select"); 115 Main.worker.execute(new Runnable() { 116 public void run() { 117 HashSet<Long> ways = new HashSet<Long>(); 118 HashSet<Long> nodes = new HashSet<Long>(); 119 HashSet<Long> relations = new HashSet<Long>(); 120 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>(); 121 for (String item : selection.split(",")) { 122 if (item.startsWith("way")) { 123 ways.add(Long.parseLong(item.substring(3))); 124 } else if (item.startsWith("node")) { 125 nodes.add(Long.parseLong(item.substring(4))); 126 } else if (item.startsWith("relation")) { 127 relations.add(Long.parseLong(item.substring(8))); 128 } else if (item.startsWith("rel")) { 129 relations.add(Long.parseLong(item.substring(3))); 130 } else { 131 System.out.println("RemoteControl: invalid selection '"+item+"' ignored"); 132 } 133 } 134 DataSet ds = Main.main.getCurrentDataSet(); 135 if(ds == null) // e.g. download failed 136 return; 137 for (Way w : ds.getWays()) if (ways.contains(w.getId())) newSel.add(w); 138 for (Node n : ds.getNodes()) if (nodes.contains(n.getId())) newSel.add(n); 139 for (Relation r : ds.getRelations()) if (relations.contains(r.getId())) newSel.add(r); 140 ds.setSelected(newSel); 141 if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) 142 new AutoScaleAction("selection").actionPerformed(null); 143 } 144 }); 145 } else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) { 146 // after downloading, zoom to downloaded area. 147 zoom(minlat, maxlat, minlon, maxlon); 148 } 149 } 150 151 protected void zoom(double minlat, double maxlat, double minlon, double maxlon) { 152 final Bounds bounds = new Bounds(new LatLon(minlat, minlon), 153 new LatLon(maxlat, maxlon)); 154 155 // make sure this isn't called unless there *is* a MapView 156 // 157 if (Main.map != null && Main.map.mapView != null) { 158 Main.worker.execute(new Runnable() { 159 public void run() { 160 BoundingXYVisitor bbox = new BoundingXYVisitor(); 161 bbox.visit(bounds); 162 Main.map.mapView.recalculateCenterScale(bbox); 163 } 164 }); 165 } 166 } 167 167 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/VersionHandler.java
r22733 r23189 14 14 public class VersionHandler extends RequestHandler { 15 15 16 17 18 16 public static final String command = "version"; 17 public static final String permissionKey = "remotecontrol.permission.read-protocolversion"; 18 public static final boolean permissionDefault = true; 19 19 20 21 22 23 24 25 26 27 28 20 @Override 21 protected void handleRequest() throws RequestHandlerErrorException, 22 RequestHandlerBadRequestException { 23 content = RequestProcessor.PROTOCOLVERSION; 24 contentType = "application/json"; 25 if (args.containsKey("jsonp")) { 26 content = args.get("jsonp")+ " && " + args.get("jsonp") + "(" + content + ")"; 27 } 28 } 29 29 30 31 32 33 30 @Override 31 public String getPermissionMessage() { 32 return tr("Remote Control has been asked to report its protocol version. This enables web sites to detect a running JOSM."); 33 } 34 34 35 36 37 38 39 40 35 @Override 36 public PermissionPrefWithDefault getPermissionPref() 37 { 38 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 39 "RemoteControl: /version forbidden by preferences"); 40 } 41 41 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/ConvertedWay.java
r17380 r23189 11 11 12 12 public class ConvertedWay { 13 14 public class WayEnd {15 private Node end;16 17 public WayEnd(Node end) {18 this.end = end;19 }20 21 @Override22 public boolean equals(Object o) {23 if (o instanceof WayEnd) {24 WayEnd otherEnd = (WayEnd)o;25 return end.equals(otherEnd.end) && routes.equals(otherEnd.getRoutes());26 } else {27 return false;28 }29 }30 31 @Override32 public int hashCode() {33 return end.hashCode() + routes.hashCode();34 }35 36 public BitSet getRoutes() {37 return routes;38 }39 40 public ConvertedWay getWay() {41 return ConvertedWay.this;42 }43 }44 45 private List<Node> nodes = new ArrayList<Node>();46 private BitSet routes;47 48 public ConvertedWay(BitSet routes, Way way) {49 this.routes = routes;50 nodes.addAll(way.getNodes());51 }52 53 public WayEnd getStart() {54 return new WayEnd(nodes.get(0));55 }56 57 public WayEnd getStop() {58 return new WayEnd(nodes.get(nodes.size() - 1));59 }60 61 /**62 * Connects way to this way. Other ways internal representation is destroyed!!!63 * @param way64 */65 public void connect(ConvertedWay way) {66 for (int i=0; i<2; i++) {67 if (way.nodes.get(0).equals(nodes.get(nodes.size() - 1))) {68 way.nodes.remove(0);69 nodes.addAll(way.nodes);70 return;71 }72 73 if (way.nodes.get(way.nodes.size() - 1).equals(nodes.get(0))) {74 nodes.remove(0);75 way.nodes.addAll(nodes);76 nodes = way.nodes;77 return;78 }79 Collections.reverse(nodes);80 }81 }82 13 83 public List<Node> getNodes() { 84 return nodes; 85 } 14 public class WayEnd { 15 private Node end; 86 16 87 public BitSet getRoutes() { 88 return routes; 89 } 17 public WayEnd(Node end) { 18 this.end = end; 19 } 20 21 @Override 22 public boolean equals(Object o) { 23 if (o instanceof WayEnd) { 24 WayEnd otherEnd = (WayEnd)o; 25 return end.equals(otherEnd.end) && routes.equals(otherEnd.getRoutes()); 26 } else { 27 return false; 28 } 29 } 30 31 @Override 32 public int hashCode() { 33 return end.hashCode() + routes.hashCode(); 34 } 35 36 public BitSet getRoutes() { 37 return routes; 38 } 39 40 public ConvertedWay getWay() { 41 return ConvertedWay.this; 42 } 43 } 44 45 private List<Node> nodes = new ArrayList<Node>(); 46 private BitSet routes; 47 48 public ConvertedWay(BitSet routes, Way way) { 49 this.routes = routes; 50 nodes.addAll(way.getNodes()); 51 } 52 53 public WayEnd getStart() { 54 return new WayEnd(nodes.get(0)); 55 } 56 57 public WayEnd getStop() { 58 return new WayEnd(nodes.get(nodes.size() - 1)); 59 } 60 61 /** 62 * Connects way to this way. Other ways internal representation is destroyed!!! 63 * @param way 64 */ 65 public void connect(ConvertedWay way) { 66 for (int i=0; i<2; i++) { 67 if (way.nodes.get(0).equals(nodes.get(nodes.size() - 1))) { 68 way.nodes.remove(0); 69 nodes.addAll(way.nodes); 70 return; 71 } 72 73 if (way.nodes.get(way.nodes.size() - 1).equals(nodes.get(0))) { 74 nodes.remove(0); 75 way.nodes.addAll(nodes); 76 nodes = way.nodes; 77 return; 78 } 79 Collections.reverse(nodes); 80 } 81 } 82 83 public List<Node> getNodes() { 84 return nodes; 85 } 86 87 public BitSet getRoutes() { 88 return routes; 89 } 90 90 91 91 -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/PathBuilder.java
r19532 r23189 14 14 public class PathBuilder { 15 15 16 17 16 private Map<Way, BitSet> wayRoutes = new HashMap<Way, BitSet>(); 17 private Collection<ConvertedWay> convertedWays; 18 18 19 19 public void addWay(Way way, RouteDefinition route) { 20 20 21 22 23 24 25 26 27 28 21 if (way.getNodesCount() >= 2) { 22 BitSet routes = wayRoutes.get(way); 23 if (routes == null) { 24 routes = new BitSet(); 25 wayRoutes.put(way, routes); 26 } 27 routes.set(route.getIndex()); 28 } 29 29 30 30 } 31 31 32 33 34 32 public Collection<ConvertedWay> getConvertedWays() { 33 if (convertedWays == null) { 34 Map<WayEnd, ConvertedWay> ways = new HashMap<WayEnd, ConvertedWay>(); 35 35 36 37 36 for (Entry<Way, BitSet> wayEntry:wayRoutes.entrySet()) { 37 ConvertedWay way = new ConvertedWay(wayEntry.getValue(), wayEntry.getKey()); 38 38 39 40 39 ConvertedWay wayBefore = ways.get(way.getStart()); 40 ConvertedWay wayAfter = ways.get(way.getStop()); 41 41 42 43 44 45 42 if (wayBefore != null) { 43 removeWay(ways, wayBefore); 44 way.connect(wayBefore); 45 } 46 46 47 48 49 50 47 if (wayAfter != null) { 48 removeWay(ways, wayAfter); 49 way.connect(wayAfter); 50 } 51 51 52 53 54 52 ways.put(way.getStart(), way); 53 ways.put(way.getStop(), way); 54 } 55 55 56 57 58 59 60 61 56 Set<ConvertedWay> uniqueWays = new HashSet<ConvertedWay>(); 57 uniqueWays.addAll(ways.values()); 58 convertedWays = uniqueWays; 59 } 60 return convertedWays; 61 } 62 62 63 64 65 66 63 private void removeWay(Map<WayEnd, ConvertedWay> map, ConvertedWay wayInMap) { 64 map.remove(wayInMap.getStart()); 65 map.remove(wayInMap.getStop()); 66 } 67 67 68 69 70 71 68 public void clear() { 69 convertedWays = null; 70 wayRoutes.clear(); 71 } 72 72 73 73 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RelationEditMode.java
r22046 r23189 21 21 22 22 public class RelationEditMode extends MapMode { 23 23 private static final long serialVersionUID = -7767329767438266289L; 24 24 25 25 private Way highlightedWay; 26 26 27 28 29 30 31 27 public RelationEditMode(MapFrame mapFrame) { 28 super(tr("Edit relation"), "node/autonode", tr("Edit relations"), 29 Shortcut.registerShortcut("mapmode:editRelation", tr("Mode: {0}", tr("Edit relation")), KeyEvent.VK_H, Shortcut.GROUP_EDIT), 30 mapFrame, Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 31 } 32 32 33 34 35 36 37 38 33 @Override 34 public void enterMode() { 35 super.enterMode(); 36 Main.map.mapView.addMouseListener(this); 37 Main.map.mapView.addMouseMotionListener(this); 38 } 39 39 40 41 42 43 44 45 40 @Override 41 public void exitMode() { 42 super.exitMode(); 43 Main.map.mapView.removeMouseListener(this); 44 Main.map.mapView.removeMouseMotionListener(this); 45 } 46 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 47 @Override 48 public void mouseMoved(MouseEvent e) { 49 Way nearestWay = Main.map.mapView.getNearestWay(e.getPoint(), OsmPrimitive.isUsablePredicate); 50 if (nearestWay != highlightedWay) { 51 if (highlightedWay != null) { 52 highlightedWay.setHighlighted(false); 53 } 54 if (nearestWay != null) { 55 nearestWay.setHighlighted(true); 56 } 57 highlightedWay = nearestWay; 58 Main.map.mapView.repaint(); 59 } 60 } 61 61 62 63 64 65 62 @Override 63 public void mouseClicked(MouseEvent e) { 64 if (Main.main.getCurrentDataSet() == null) 65 return; 66 66 67 68 67 Way way = Main.map.mapView.getNearestWay(e.getPoint(), OsmPrimitive.isUsablePredicate); 68 Collection<Relation> selectedRelations = Main.main.getCurrentDataSet().getSelectedRelations(); 69 69 70 70 if (way != null) { 71 71 72 73 74 72 if (selectedRelations.isEmpty()) { 73 JOptionPane.showMessageDialog(Main.parent, tr("No relation is selected")); 74 } 75 75 76 77 78 79 80 81 82 83 84 76 for (OsmPrimitive rel:selectedRelations) { 77 Relation r = (Relation)rel; 78 RelationMember foundMember = null; 79 for (RelationMember member:r.getMembers()) { 80 if (member.getMember() == way) { 81 foundMember = member; 82 break; 83 } 84 } 85 85 86 87 88 89 90 91 92 93 94 95 86 if (foundMember != null) { 87 Main.main.undoRedo.add(new RemoveRelationMemberCommand(r, new RelationMember("", way))); 88 } else { 89 Relation newRelation = new Relation(r); 90 newRelation.addMember(new RelationMember("", way)); 91 Main.main.undoRedo.add(new ChangeCommand(r, newRelation)); 92 } 93 } 94 } 95 } 96 96 97 97 -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RouteDefinition.java
r19338 r23189 10 10 public class RouteDefinition { 11 11 12 13 14 15 12 private final Color color; 13 private final String matchString; 14 private Match match; 15 private final int index; 16 16 17 18 19 20 21 22 23 24 25 26 27 17 public RouteDefinition(int index, Color color, String expression) { 18 this.color = color; 19 this.matchString = expression; 20 this.index = index; 21 try { 22 match = SearchCompiler.compile(expression, false, false); 23 } catch (ParseError e) { 24 match = new SearchCompiler.Never(); 25 e.printStackTrace(); 26 } 27 } 28 28 29 30 31 29 public boolean matches(OsmPrimitive primitive) { 30 return match.match(primitive); 31 } 32 32 33 34 35 33 public Color getColor() { 34 return color; 35 } 36 36 37 38 39 37 public int getIndex() { 38 return index; 39 } 40 40 41 42 43 44 41 @Override 42 public String toString() { 43 return color.toString() + " " + matchString; 44 } 45 45 46 46 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RouteLayer.java
r22549 r23189 33 33 public class RouteLayer extends Layer implements DataSetListenerAdapter.Listener { 34 34 35 36 37 38 35 private final PathPainter pathPainter; 36 private final PathBuilder pathBuilder = new PathBuilder(); 37 private final List<RouteDefinition> routes = new ArrayList<RouteDefinition>(); 38 private volatile boolean datasetChanged = true; 39 39 40 41 40 public RouteLayer(RoutesXMLLayer xmlLayer) { 41 super(xmlLayer.getName()); 42 42 43 44 45 46 47 48 49 50 51 52 53 43 int index = 0; 44 for (RoutesXMLRoute route:xmlLayer.getRoute()) { 45 if (route.isEnabled()) { 46 Color color = ColorHelper.html2color(route.getColor()); 47 if (color == null) { 48 color = Color.RED; 49 System.err.printf("Routes plugin - unable to convert color (%s)\n", route.getColor()); 50 } 51 routes.add(new RouteDefinition(index++, color, route.getPattern())); 52 } 53 } 54 54 55 56 57 58 59 55 if ("wide".equals(Main.pref.get("routes.painter"))) { 56 pathPainter = new WideLinePainter(this); 57 } else { 58 pathPainter = new NarrowLinePainter(this); 59 } 60 60 61 62 61 DatasetEventManager.getInstance().addDatasetListener(new DataSetListenerAdapter(this), FireMode.IMMEDIATELY); 62 } 63 63 64 65 66 67 64 @Override 65 public Icon getIcon() { 66 return ImageProvider.get("layer", "osmdata_small"); 67 } 68 68 69 70 71 72 69 @Override 70 public Object getInfoComponent() { 71 return null; 72 } 73 73 74 75 76 77 74 @Override 75 public Action[] getMenuEntries() { 76 return new Action[0]; 77 } 78 78 79 80 81 82 79 @Override 80 public String getToolTipText() { 81 return "Hiking routes"; 82 } 83 83 84 85 86 87 84 @Override 85 public boolean isMergable(Layer other) { 86 return false; 87 } 88 88 89 90 91 92 89 @Override 90 public void mergeFrom(Layer from) { 91 // Merging is not supported 92 } 93 93 94 95 96 97 98 99 100 101 94 private void addRelation(Relation relation, RouteDefinition route) { 95 for (RelationMember member:relation.getMembers()) { 96 if (member.getMember() instanceof Way) { 97 Way way = (Way)member.getMember(); 98 pathBuilder.addWay(way, route); 99 } 100 } 101 } 102 102 103 104 103 @Override 104 public void paint(Graphics2D g, MapView mv, Bounds bounds) { 105 105 106 106 DataSet dataset = Main.main.getCurrentDataSet(); 107 107 108 109 110 108 if (dataset == null) { 109 return; 110 } 111 111 112 113 114 112 if (datasetChanged) { 113 datasetChanged = false; 114 pathBuilder.clear(); 115 115 116 117 118 119 120 121 122 116 for (Relation relation:dataset.getRelations()) { 117 for (RouteDefinition route:routes) { 118 if (route.matches(relation)) { 119 addRelation(relation, route); 120 } 121 } 122 } 123 123 124 125 126 127 128 129 130 131 124 for (Way way:dataset.getWays()) { 125 for (RouteDefinition route:routes) { 126 if (route.matches(way)) { 127 pathBuilder.addWay(way, route); 128 } 129 } 130 } 131 } 132 132 133 134 135 136 137 138 139 133 Stroke stroke = g.getStroke(); 134 Color color = g.getColor(); 135 for (ConvertedWay way:pathBuilder.getConvertedWays()) { 136 pathPainter.drawWay(way, mv, g); 137 } 138 g.setStroke(stroke); 139 g.setColor(color); 140 140 141 141 } 142 142 143 144 143 @Override 144 public void visitBoundingBox(BoundingXYVisitor v) { 145 145 146 146 } 147 147 148 149 150 148 public List<RouteDefinition> getRoutes() { 149 return routes; 150 } 151 151 152 153 154 152 public void processDatasetEvent(AbstractDatasetChangedEvent event) { 153 datasetChanged = true; 154 } 155 155 156 156 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RoutesPlugin.java
r19473 r23189 26 26 27 27 public class RoutesPlugin extends Plugin implements LayerChangeListener { 28 28 29 29 private final List<RouteLayer> routeLayers = new ArrayList<RouteLayer>(); 30 30 private boolean isShown; 31 31 32 32 public RoutesPlugin(PluginInformation info) { 33 34 35 33 super(info); 34 MapView.addLayerChangeListener(this); 35 36 36 File routesFile = new File(getPluginDir() + File.separator + "routes.xml"); 37 37 if (!routesFile.exists()) { 38 38 System.out.println("File with route definitions doesn't exist, using default"); 39 39 40 40 try { 41 41 routesFile.getParentFile().mkdir(); 42 42 OutputStream outputStream = new FileOutputStream(routesFile); 43 43 InputStream inputStream = Routes.class.getResourceAsStream("routes.xml"); 44 45 byte[] b = new byte[512]; 46 int read; 47 while ((read = inputStream.read(b)) != -1) { 44 45 byte[] b = new byte[512]; 46 int read; 47 while ((read = inputStream.read(b)) != -1) { 48 48 outputStream.write(b, 0, read); 49 49 } 50 51 outputStream.close(); 50 51 outputStream.close(); 52 52 inputStream.close(); 53 53 54 54 } catch (IOException e) { 55 55 e.printStackTrace(); 56 56 } 57 57 } 58 58 59 59 try { 60 60 JAXBContext context = JAXBContext.newInstance( … … 64 64 new FileInputStream(getPluginDir() + File.separator + "routes.xml")); 65 65 for (RoutesXMLLayer layer:routes.getLayer()) { 66 67 68 66 if (layer.isEnabled()) { 67 routeLayers.add(new RouteLayer(layer)); 68 } 69 69 } 70 70 } catch (Exception e) { 71 71 e.printStackTrace(); 72 } 72 } 73 73 74 74 //new RelationEditMode(Main.map); … … 77 77 78 78 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 79 // TODO Auto-generated method stub 79 // TODO Auto-generated method stub 80 80 } 81 81 82 82 private void checkLayers() { 83 83 if (Main.map != null && Main.map.mapView != null) { … … 91 91 Main.main.addLayer(routeLayer); 92 92 } 93 } 93 } 94 94 }); 95 95 } 96 96 return; 97 } 97 } 98 98 } 99 99 if (isShown) { … … 104 104 Main.main.removeLayer(routeLayer); 105 105 } 106 } 106 } 107 107 }); 108 108 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/AbstractLinePainter.java
r22590 r23189 17 17 public abstract class AbstractLinePainter implements PathPainter { 18 18 19 20 21 22 23 24 25 26 27 28 29 30 31 19 // Following two method copied from http://blog.persistent.info/2004/03/java-lineline-intersections.html 20 protected boolean getLineLineIntersection(Line2D.Double l1, 21 Line2D.Double l2, 22 Point intersection) 23 { 24 double x1 = l1.getX1(), y1 = l1.getY1(), 25 x2 = l1.getX2(), y2 = l1.getY2(), 26 x3 = l2.getX1(), y3 = l2.getY1(), 27 x4 = l2.getX2(), y4 = l2.getY2(); 28 double dx1 = x2 - x1; 29 double dx2 = x4 - x3; 30 double dy1 = y2 - y1; 31 double dy2 = y4 - y3; 32 32 33 33 double ua = (dx2 * (y1 - y3) - dy2 * (x1 - x3)) / (dy2 * dx1 - dx2 * dy1); 34 34 35 36 37 38 39 40 41 42 35 if (Math.abs(dy2 * dx1 - dx2 * dy1) < 0.0001) { 36 intersection.x = (int)l1.x2; 37 intersection.y = (int)l1.y2; 38 return false; 39 } else { 40 intersection.x = (int)(x1 + ua * (x2 - x1)); 41 intersection.y = (int)(y1 + ua * (y2 - y1)); 42 } 43 43 44 45 44 return true; 45 } 46 46 47 48 49 50 47 protected double det(double a, double b, double c, double d) 48 { 49 return a * d - b * c; 50 } 51 51 52 53 54 52 protected Point shiftPoint(Point2D p1, Point2D p2, double shift) { 53 double dx = p2.getX() - p1.getX(); 54 double dy = p2.getY() - p1.getY(); 55 55 56 57 58 56 // Perpendicular vector 57 double ndx = -dy; 58 double ndy = dx; 59 59 60 61 62 63 60 // Normalize 61 double length = Math.sqrt(ndx * ndx + ndy * ndy); 62 ndx = ndx / length; 63 ndy = ndy / length; 64 64 65 66 65 return new Point((int)(p1.getX() + shift * ndx), (int)(p1.getY() + shift * ndy)); 66 } 67 67 68 69 70 68 protected Line2D.Double shiftLine(Point2D p1, Point2D p2, double shift) { 69 double dx = p2.getX() - p1.getX(); 70 double dy = p2.getY() - p1.getY(); 71 71 72 73 72 Point2D point1 = shiftPoint(p1, p2, shift); 73 Point2D point2 = new Point2D.Double(point1.getX() + dx, point1.getY() + dy); 74 74 75 76 77 75 return new Line2D.Double( 76 point1, point2); 77 } 78 78 79 79 protected GeneralPath getPath(Graphics2D g, MapView mapView, List<Node> nodes, double shift) { 80 80 81 81 GeneralPath path = new GeneralPath(); 82 82 83 84 85 83 if (nodes.size() < 2) { 84 return path; 85 } 86 86 87 88 89 90 87 Point p1 = null; 88 Point p2 = null; 89 Point p3 = null; 90 Point lastPoint = null; 91 91 92 93 92 for (Node n: nodes) { 93 Point p = mapView.getPoint(n); 94 94 95 96 97 98 99 100 101 95 if (!p.equals(p3)) { 96 p1 = p2; 97 p2 = p3; 98 p3 = p; 99 } else { 100 continue; 101 } 102 102 103 104 105 106 107 108 109 103 p = null; 104 if (p2 != null) { 105 if (p1 == null) { 106 p = shiftPoint(p2, p3, shift); 107 } else { 108 Line2D.Double line1 = shiftLine(p1, p2, shift); 109 Line2D.Double line2 = shiftLine(p2, p3, shift); 110 110 111 112 113 114 111 /*path.moveTo((float)line1.x1, (float)line1.y1); 112 path.lineTo((float)line1.x2, (float)line1.y2); 113 path.moveTo((float)line2.x1, (float)line2.y1); 114 path.lineTo((float)line2.x2, (float)line2.y2);*/ 115 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 116 p = new Point(); 117 if (!getLineLineIntersection(line1, line2, p)) { 118 p = null; 119 } else { 120 int dx = p.x - p2.x; 121 int dy = p.y - p2.y; 122 int distance = (int)Math.sqrt(dx * dx + dy * dy); 123 if (distance > 10) { 124 p.x = p2.x + dx / (distance / 10); 125 p.y = p2.y + dy / (distance / 10); 126 } 127 } 128 } 129 } 130 130 131 132 133 134 135 136 137 131 if (p != null && lastPoint != null) { 132 drawSegment(g, mapView, path, lastPoint, p); 133 } 134 if (p != null) { 135 lastPoint = p; 136 } 137 } 138 138 139 140 141 142 139 if (p2 != null && p3 != null && lastPoint != null) { 140 p3 = shiftPoint(p3, p2, -shift); 141 drawSegment(g, mapView, path, lastPoint, p3); 142 } 143 143 144 145 144 return path; 145 } 146 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 147 private void drawSegment(Graphics2D g, NavigatableComponent nc, GeneralPath path, Point p1, Point p2) { 148 boolean drawIt = false; 149 if (Main.isOpenjdk) { 150 /** 151 * Work around openjdk bug. It leads to drawing artefacts when zooming in a lot. (#4289, #4424) 152 * (It looks like int overflow when clipping.) We do custom clipping. 153 */ 154 Rectangle bounds = g.getClipBounds(); 155 bounds.grow(100, 100); // avoid arrow heads at the border 156 LineClip clip = new LineClip(); 157 drawIt = clip.cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height); 158 if (drawIt) { 159 p1 = clip.getP1(); 160 p2 = clip.getP2(); 161 } 162 } else { 163 drawIt = isSegmentVisible(nc, p1, p2); 164 } 165 if (drawIt) { 166 /* draw segment line */ 167 path.moveTo(p1.x, p1.y); 168 path.lineTo(p2.x, p2.y); 169 } 170 } 171 171 172 173 174 175 176 177 178 172 private boolean isSegmentVisible(NavigatableComponent nc, Point p1, Point p2) { 173 if ((p1.x < 0) && (p2.x < 0)) return false; 174 if ((p1.y < 0) && (p2.y < 0)) return false; 175 if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false; 176 if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false; 177 return true; 178 } 179 179 180 180 -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/NarrowLinePainter.java
r21174 r23189 14 14 public class NarrowLinePainter extends AbstractLinePainter { 15 15 16 17 16 private static final float LINE_WIDTH = 5; 17 private final RouteLayer layer; 18 18 19 20 21 19 public NarrowLinePainter(RouteLayer layer) { 20 this.layer = layer; 21 } 22 22 23 24 25 23 public void drawWay(ConvertedWay way, MapView mapView, Graphics2D g) { 24 List<Node> nodes = way.getNodes(); 25 BitSet routes = way.getRoutes(); 26 26 27 28 29 27 if (nodes.size() < 2) { 28 return; 29 } 30 30 31 32 33 34 35 31 //double totalWidth = LINE_WIDTH + (colors.size() - 1) * 4; 32 //double width = totalWidth / colors.size(); 33 //double shift = -totalWidth / 2 + width / 2; 34 double width = LINE_WIDTH; 35 double shift = - (LINE_WIDTH * routes.cardinality()) / 2 + width / 2; 36 36 37 37 for (int k=0; k<routes.length(); k++) { 38 38 39 40 41 39 if (!routes.get(k)) { 40 continue; 41 } 42 42 43 43 RouteDefinition route = layer.getRoutes().get(k); 44 44 45 46 45 g.setColor(route.getColor()); 46 g.setStroke(new BasicStroke((float) width)); 47 47 48 48 g.draw(getPath(g, mapView, nodes, shift)); 49 49 50 51 52 50 shift += width + 2; 51 } 52 } 53 53 54 54 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/PathPainter.java
r16428 r23189 7 7 8 8 public interface PathPainter { 9 10 9 10 public void drawWay(ConvertedWay way, MapView mapView, Graphics2D g); 11 11 12 12 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/WideLinePainter.java
r21174 r23189 15 15 public class WideLinePainter extends AbstractLinePainter { 16 16 17 18 17 private static final float LINE_WIDTH = 10; 18 private final RouteLayer layer; 19 19 20 21 22 20 public WideLinePainter(RouteLayer layer) { 21 this.layer = layer; 22 } 23 23 24 25 26 24 public void drawWay(ConvertedWay way, MapView mapView, Graphics2D g) { 25 List<Node> nodes = way.getNodes(); 26 BitSet routes = way.getRoutes(); 27 27 28 29 30 28 if (nodes.size() < 2) { 29 return; 30 } 31 31 32 33 34 32 double totalWidth = LINE_WIDTH + (routes.size() - 1) * 4; 33 double width = totalWidth / routes.cardinality(); 34 double shift = -totalWidth / 2 + width / 2; 35 35 36 36 for (int k=0; k<routes.length(); k++) { 37 37 38 39 40 38 if (!routes.get(k)) { 39 continue; 40 } 41 41 42 42 RouteDefinition route = layer.getRoutes().get(k); 43 43 44 45 46 44 Color color = route.getColor(); 45 g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 100)); 46 g.setStroke(new BasicStroke((float) width)); 47 47 48 48 g.draw(getPath(g, mapView, nodes, shift)); 49 49 50 51 52 50 shift += width; 51 } 52 } 53 53 54 54 } -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/xml/ObjectFactory.java
r16593 r23189 1 1 // 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 6 6 // 7 7 … … 13 13 14 14 /** 15 * This object contains factory methods for each 16 * Java content interface and Java element interface 17 * generated in the org.openstreetmap.josm.plugins.routes.xml package. 18 * <p>An ObjectFactory allows you to programatically 19 * construct new instances of the Java representation 20 * for XML content. The Java representation of XML 21 * content can consist of schema derived interfaces 22 * and classes representing the binding of schema 23 * type definitions, element declarations and model 24 * groups. Factory methods for each of these are 15 * This object contains factory methods for each 16 * Java content interface and Java element interface 17 * generated in the org.openstreetmap.josm.plugins.routes.xml package. 18 * <p>An ObjectFactory allows you to programatically 19 * construct new instances of the Java representation 20 * for XML content. The Java representation of XML 21 * content can consist of schema derived interfaces 22 * and classes representing the binding of schema 23 * type definitions, element declarations and model 24 * groups. Factory methods for each of these are 25 25 * provided in this class. 26 * 26 * 27 27 */ 28 28 @XmlRegistry … … 32 32 /** 33 33 * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openstreetmap.josm.plugins.routes.xml 34 * 34 * 35 35 */ 36 36 public ObjectFactory() { … … 39 39 /** 40 40 * Create an instance of {@link RoutesXMLRoute } 41 * 41 * 42 42 */ 43 43 public RoutesXMLRoute createRoutesXMLRoute() { … … 47 47 /** 48 48 * Create an instance of {@link RoutesXMLLayer } 49 * 49 * 50 50 */ 51 51 public RoutesXMLLayer createRoutesXMLLayer() { … … 55 55 /** 56 56 * Create an instance of {@link Routes } 57 * 57 * 58 58 */ 59 59 public Routes createRoutes() { -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/xml/Routes.java
r16593 r23189 1 1 // 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 6 6 // 7 7 … … 19 19 /** 20 20 * <p>Java class for anonymous complex type. 21 * 21 * 22 22 * <p>The following schema fragment specifies the expected content contained within this class. 23 * 23 * 24 24 * <pre> 25 25 * <complexType> … … 33 33 * </complexType> 34 34 * </pre> 35 * 36 * 35 * 36 * 37 37 */ 38 38 @XmlAccessorType(XmlAccessType.FIELD) … … 47 47 /** 48 48 * Gets the value of the layer property. 49 * 49 * 50 50 * <p> 51 51 * This accessor method returns a reference to the live list, … … 53 53 * returned list will be present inside the JAXB object. 54 54 * This is why there is not a <CODE>set</CODE> method for the layer property. 55 * 55 * 56 56 * <p> 57 57 * For example, to add a new item, do as follows: … … 59 59 * getLayer().add(newItem); 60 60 * </pre> 61 * 62 * 61 * 62 * 63 63 * <p> 64 64 * Objects of the following type(s) are allowed in the list 65 65 * {@link RoutesXMLLayer } 66 * 67 * 66 * 67 * 68 68 */ 69 69 public List<RoutesXMLLayer> getLayer() { -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/xml/RoutesXMLLayer.java
r16593 r23189 1 1 // 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 6 6 // 7 7 … … 19 19 /** 20 20 * <p>Java class for layer complex type. 21 * 21 * 22 22 * <p>The following schema fragment specifies the expected content contained within this class. 23 * 23 * 24 24 * <pre> 25 25 * <complexType name="layer"> … … 35 35 * </complexType> 36 36 * </pre> 37 * 38 * 37 * 38 * 39 39 */ 40 40 @XmlAccessorType(XmlAccessType.FIELD) … … 52 52 /** 53 53 * Gets the value of the route property. 54 * 54 * 55 55 * <p> 56 56 * This accessor method returns a reference to the live list, … … 58 58 * returned list will be present inside the JAXB object. 59 59 * This is why there is not a <CODE>set</CODE> method for the route property. 60 * 60 * 61 61 * <p> 62 62 * For example, to add a new item, do as follows: … … 64 64 * getRoute().add(newItem); 65 65 * </pre> 66 * 67 * 66 * 67 * 68 68 * <p> 69 69 * Objects of the following type(s) are allowed in the list 70 70 * {@link RoutesXMLRoute } 71 * 72 * 71 * 72 * 73 73 */ 74 74 public List<RoutesXMLRoute> getRoute() { … … 81 81 /** 82 82 * Gets the value of the name property. 83 * 83 * 84 84 * @return 85 85 * possible object is 86 86 * {@link String } 87 * 87 * 88 88 */ 89 89 public String getName() { … … 93 93 /** 94 94 * Sets the value of the name property. 95 * 95 * 96 96 * @param value 97 97 * allowed object is 98 98 * {@link String } 99 * 99 * 100 100 */ 101 101 public void setName(String value) { … … 105 105 /** 106 106 * Gets the value of the enabled property. 107 * 107 * 108 108 * @return 109 109 * possible object is 110 110 * {@link Boolean } 111 * 111 * 112 112 */ 113 113 public boolean isEnabled() { … … 121 121 /** 122 122 * Sets the value of the enabled property. 123 * 123 * 124 124 * @param value 125 125 * allowed object is 126 126 * {@link Boolean } 127 * 127 * 128 128 */ 129 129 public void setEnabled(Boolean value) { -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/xml/RoutesXMLRoute.java
r16593 r23189 1 1 // 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 6 6 // 7 7 … … 18 18 /** 19 19 * <p>Java class for route complex type. 20 * 20 * 21 21 * <p>The following schema fragment specifies the expected content contained within this class. 22 * 22 * 23 23 * <pre> 24 24 * <complexType name="route"> … … 34 34 * </complexType> 35 35 * </pre> 36 * 37 * 36 * 37 * 38 38 */ 39 39 @XmlAccessorType(XmlAccessType.FIELD) … … 52 52 /** 53 53 * Gets the value of the pattern property. 54 * 54 * 55 55 * @return 56 56 * possible object is 57 57 * {@link String } 58 * 58 * 59 59 */ 60 60 public String getPattern() { … … 64 64 /** 65 65 * Sets the value of the pattern property. 66 * 66 * 67 67 * @param value 68 68 * allowed object is 69 69 * {@link String } 70 * 70 * 71 71 */ 72 72 public void setPattern(String value) { … … 76 76 /** 77 77 * Gets the value of the color property. 78 * 78 * 79 79 * @return 80 80 * possible object is 81 81 * {@link String } 82 * 82 * 83 83 */ 84 84 public String getColor() { … … 88 88 /** 89 89 * Sets the value of the color property. 90 * 90 * 91 91 * @param value 92 92 * allowed object is 93 93 * {@link String } 94 * 94 * 95 95 */ 96 96 public void setColor(String value) { … … 100 100 /** 101 101 * Gets the value of the enabled property. 102 * 102 * 103 103 * @return 104 104 * possible object is 105 105 * {@link Boolean } 106 * 106 * 107 107 */ 108 108 public boolean isEnabled() { … … 116 116 /** 117 117 * Sets the value of the enabled property. 118 * 118 * 119 119 * @param value 120 120 * allowed object is 121 121 * {@link Boolean } 122 * 122 * 123 123 */ 124 124 public void setEnabled(Boolean value) { -
applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/xml/package-info.java
r16593 r23189 1 1 // 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 2 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 3 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 4 // Any modifications to this file will be lost upon recompilation of the source schema. 5 // Generated on: 2009.07.19 at 03:50:48 odp. CEST 6 6 // 7 7 -
applications/editors/josm/plugins/routing/src/com/innovant/josm/jrt/core/EdgeIterator.java
r15707 r23189 4 4 5 5 public boolean hasNext(); 6 6 7 7 public RoutingEdge next(); 8 8 -
applications/editors/josm/plugins/routing/src/com/innovant/josm/jrt/core/RoutingEdge.java
r15707 r23189 8 8 9 9 public LatLon toLatLon(); 10 10 11 11 public Object fromV(); 12 12 … … 14 14 15 15 public double getLength(); 16 16 17 17 public void setLength(double length); 18 18 19 19 public double getSpeed(); 20 20 21 21 public void setSpeed(double speed); 22 22 23 23 public boolean isOneway(); 24 24 25 25 public void setOneway(boolean isOneway); 26 26 -
applications/editors/josm/plugins/routing/src/com/innovant/josm/jrt/core/RoutingGraphDelegator.java
r15707 r23189 1 1 /** 2 * 2 * 3 3 */ 4 4 package com.innovant.josm.jrt.core; … … 23 23 */ 24 24 static Logger logger = Logger.getLogger(RoutingGraphDelegator.class); 25 25 26 26 /** 27 27 * 28 28 */ 29 29 private RouteType routeType; 30 30 31 31 public RoutingGraphDelegator(Graph<Node, OsmEdge> arg0) { 32 32 super(arg0); 33 33 } 34 34 35 35 36 36 public RouteType getRouteType() { … … 44 44 45 45 /** 46 * 46 * 47 47 */ 48 48 private static final long serialVersionUID = 1L; … … 51 51 public double getEdgeWeight(OsmEdge edge) { 52 52 double weight=Double.MAX_VALUE; 53 53 54 54 if (routeType==RouteType.SHORTEST) weight=edge.getLength(); 55 55 if (routeType==RouteType.FASTEST) weight=edge.getLength() / edge.getSpeed(); -
applications/editors/josm/plugins/routing/src/com/innovant/josm/jrt/osm/OsmEdge.java
r16290 r23189 94 94 return length; 95 95 } 96 96 97 97 public void setLength(double length) { 98 98 this.length = length; -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/LaunchAction.java
r20079 r23189 21 21 public class LaunchAction extends JosmAction implements SelectionChangedListener { 22 22 23 24 25 26 27 28 29 30 31 32 33 34 23 public LaunchAction() { 24 super( 25 tr("Edit tags"), 26 null, //TODO: set "tag-editor" and add /images/tag-editor.png to distrib 27 tr("Launches the tag editor dialog"), 28 Shortcut.registerShortcut( 29 "edit:launchtageditor", 30 tr("Launches the tag editor dialog"), 31 KeyEvent.VK_T, 32 Shortcut.GROUP_EDIT), 33 true 34 ); 35 35 36 37 38 36 DataSet.selListeners.add(this); 37 setEnabled(false); 38 } 39 39 40 41 42 43 44 45 46 47 48 49 40 /** 41 * launch the editor 42 */ 43 protected void launchEditor() { 44 if (!isEnabled()) 45 return; 46 TagEditorDialog dialog = TagEditorDialog.getInstance(); 47 dialog.startEditSession(); 48 dialog.setVisible(true); 49 } 50 50 51 52 53 51 public void actionPerformed(ActionEvent e) { 52 launchEditor(); 53 } 54 54 55 56 57 55 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) { 56 setEnabled(newSelection != null && newSelection.size() >0); 57 } 58 58 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/TagEditorDialog.java
r21024 r23189 50 50 @SuppressWarnings("serial") 51 51 public class TagEditorDialog extends JDialog { 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 52 static private final Logger logger = Logger.getLogger(TagEditorDialog.class.getName()); 53 54 /** the unique instance */ 55 static private TagEditorDialog instance = null; 56 57 /** 58 * Access to the singleton instance 59 * 60 * @return the singleton instance of the dialog 61 */ 62 static public TagEditorDialog getInstance() { 63 if (instance == null) { 64 instance = new TagEditorDialog(); 65 } 66 return instance; 67 } 68 69 /** default preferred size */ 70 static public final Dimension PREFERRED_SIZE = new Dimension(700, 500); 71 72 /** the properties table */ 73 private TagEditor tagEditor = null; 74 75 /** the auto completion list viewer */ 76 private AutoCompletionListViewer aclViewer = null; 77 78 /** the cache of auto completion values used by the tag editor */ 79 private AutoCompletionManager autocomplete = null; 80 81 private OKAction okAction = null; 82 private CancelAction cancelAction = null; 83 84 /** 85 * @return the tag editor model 86 */ 87 public TagEditorModel getModel() { 88 return tagEditor.getModel(); 89 } 90 91 protected JPanel buildButtonRow() { 92 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); 93 94 // the ok button 95 // 96 pnl.add(new JButton(okAction = new OKAction())); 97 getModel().addPropertyChangeListener(okAction); 98 99 // the cancel button 100 // 101 pnl.add(new JButton(cancelAction = new CancelAction())); 102 return pnl; 103 } 104 105 protected JPanel buildTagGridPanel() { 106 // create tag editor and inject an instance of the tag 107 // editor model 108 // 109 tagEditor = new TagEditor(); 110 111 // create the auto completion list viewer and connect it 112 // to the tag editor 113 // 114 AutoCompletionList autoCompletionList = new AutoCompletionList(); 115 aclViewer = new AutoCompletionListViewer(autoCompletionList); 116 tagEditor.setAutoCompletionList(autoCompletionList); 117 aclViewer.addAutoCompletionListListener(tagEditor); 118 tagEditor.addComponentNotStoppingCellEditing(aclViewer); 119 120 JPanel pnlTagGrid = new JPanel(); 121 pnlTagGrid.setLayout(new BorderLayout()); 122 123 124 pnlTagGrid.add(tagEditor, BorderLayout.CENTER); 125 pnlTagGrid.add(aclViewer, BorderLayout.EAST); 126 pnlTagGrid.setBorder(BorderFactory.createEmptyBorder(5, 0,0,0)); 127 128 JSplitPane splitPane = new JSplitPane( 129 JSplitPane.HORIZONTAL_SPLIT, 130 tagEditor, 131 aclViewer 132 ); 133 splitPane.setOneTouchExpandable(false); 134 splitPane.setDividerLocation(600); 135 pnlTagGrid.add(splitPane, BorderLayout.CENTER); 136 return pnlTagGrid; 137 } 138 139 /** 140 * build the GUI 141 */ 142 protected void build() { 143 getContentPane().setLayout(new BorderLayout()); 144 145 // basic UI prpoperties 146 // 147 setModal(true); 148 setSize(PREFERRED_SIZE); 149 setTitle(tr("JOSM Tag Editor Plugin")); 150 151 JPanel pnlTagGrid = buildTagGridPanel(); 152 153 // create the preset selector 154 // 155 TabularPresetSelector presetSelector = new TabularPresetSelector(); 156 presetSelector.addPresetSelectorListener( 157 new IPresetSelectorListener() { 158 public void itemSelected(Item item) { 159 tagEditor.stopEditing(); 160 tagEditor.getModel().applyPreset(item); 161 tagEditor.requestFocusInTopLeftCell(); 162 } 163 } 164 ); 165 166 JPanel pnlPresetSelector = new JPanel(); 167 pnlPresetSelector.setLayout(new BorderLayout()); 168 pnlPresetSelector.add(presetSelector,BorderLayout.CENTER); 169 pnlPresetSelector.setBorder(BorderFactory.createEmptyBorder(0,0,5,0 )); 170 171 // create the tag selector 172 // 173 TabularTagSelector tagSelector = new TabularTagSelector(); 174 tagSelector.addTagSelectorListener( 175 new ITagSelectorListener() { 176 public void itemSelected(KeyValuePair pair) { 177 tagEditor.stopEditing(); 178 tagEditor.getModel().applyKeyValuePair(pair); 179 tagEditor.requestFocusInTopLeftCell(); 180 } 181 } 182 ); 183 JPanel pnlTagSelector = new JPanel(); 184 pnlTagSelector.setLayout(new BorderLayout()); 185 pnlTagSelector.add(tagSelector,BorderLayout.CENTER); 186 pnlTagSelector.setBorder(BorderFactory.createEmptyBorder(0,0,5,0 )); 187 188 // create the tabbed pane 189 // 190 JTabbedPane tabbedPane = new JTabbedPane(); 191 tabbedPane.add(pnlPresetSelector, tr("Presets")); 192 tabbedPane.add(pnlTagSelector, tr("Tags")); 193 194 195 // create split pane 196 // 197 JSplitPane splitPane = new JSplitPane( 198 JSplitPane.VERTICAL_SPLIT, 199 tabbedPane, 200 pnlTagGrid 201 ); 202 splitPane.setOneTouchExpandable(true); 203 splitPane.setDividerLocation(200); 204 205 Dimension minimumSize = new Dimension(100, 50); 206 presetSelector.setMinimumSize(minimumSize); 207 pnlTagGrid.setMinimumSize(minimumSize); 208 209 getContentPane().add(splitPane,BorderLayout.CENTER); 210 211 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH); 212 213 214 addWindowListener( 215 new WindowAdapter() { 216 @Override public void windowActivated(WindowEvent e) { 217 SwingUtilities.invokeLater(new Runnable(){ 218 public void run() 219 { 220 getModel().ensureOneTag(); 221 tagEditor.clearSelection(); 222 tagEditor.requestFocusInTopLeftCell(); 223 } 224 }); 225 } 226 } 227 ); 228 229 // makes sure that 'Ctrl-Enter' in the properties table 230 // and in the aclViewer is handled by okAction 231 // 232 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put((KeyStroke)cancelAction.getValue(Action.ACCELERATOR_KEY), okAction.getValue(AbstractAction.NAME)); 233 getRootPane().getActionMap().put(cancelAction.getValue(Action.NAME), cancelAction); 234 235 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put((KeyStroke)okAction.getValue(Action.ACCELERATOR_KEY), okAction.getValue(AbstractAction.NAME)); 236 getRootPane().getActionMap().put(okAction.getValue(Action.NAME), okAction); 237 238 239 // make sure the OK action is also enabled in sub components. I registered 240 // the action in the input and action maps of the dialogs root pane and I expected 241 // it to get triggered regardless of what subcomponent had focus, but it didn't. 242 // 243 aclViewer.installKeyAction(okAction); 244 aclViewer.installKeyAction(cancelAction); 245 presetSelector.installKeyAction(okAction); 246 presetSelector.installKeyAction(cancelAction); 247 } 248 249 /** 250 * constructor 251 */ 252 protected TagEditorDialog() { 253 build(); 254 } 255 255 256 256 @Override … … 270 270 } 271 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 272 /** 273 * start an editing session. This method should be called before the dialog 274 * is shown on the screen, i.e. before {@link Dialog#setVisible(boolean)} is 275 * called. 276 */ 277 public void startEditSession() { 278 tagEditor.getModel().clearAppliedPresets(); 279 tagEditor.getModel().initFromJOSMSelection(); 280 autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager(); 281 tagEditor.setAutoCompletionManager(autocomplete); 282 getModel().ensureOneTag(); 283 } 284 285 class CancelAction extends AbstractAction { 286 public CancelAction() { 287 putValue(NAME, tr("Cancel")); 288 putValue(SMALL_ICON, ImageProvider.get("cancel")); 289 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0)); 290 putValue(SHORT_DESCRIPTION, tr("Abort tag editing and close dialog")); 291 } 292 293 public void actionPerformed(ActionEvent arg0) { 294 setVisible(false); 295 } 296 } 297 298 class OKAction extends AbstractAction implements PropertyChangeListener { 299 300 public OKAction() { 301 putValue(NAME, tr("OK")); 302 putValue(SMALL_ICON, ImageProvider.get("ok")); 303 putValue(SHORT_DESCRIPTION, tr("Apply edited tags and close dialog")); 304 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl ENTER")); 305 } 306 307 public void actionPerformed(ActionEvent e) { 308 run(); 309 } 310 311 public void run() { 312 tagEditor.stopEditing(); 313 setVisible(false); 314 tagEditor.getModel().updateJOSMSelection(); 315 DataSet ds = Main.main.getCurrentDataSet(); 316 ds.fireSelectionChanged(); 317 Main.parent.repaint(); // repaint all - drawing could have been changed 318 } 319 320 public void propertyChange(PropertyChangeEvent evt) { 321 if (! evt.getPropertyName().equals(TagEditorModel.PROP_DIRTY)) 322 return; 323 if (! evt.getNewValue().getClass().equals(Boolean.class)) 324 return; 325 boolean dirty = (Boolean)evt.getNewValue(); 326 setEnabled(dirty); 327 } 328 } 329 329 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/TagEditorPlugin.java
r20079 r23189 7 7 8 8 public class TagEditorPlugin extends Plugin { 9 10 11 12 13 14 15 16 17 18 9 LaunchAction action; 10 11 /** 12 * constructor 13 */ 14 public TagEditorPlugin(PluginInformation info) { 15 super(info); 16 action = new LaunchAction(); 17 MainMenu.add(Main.main.menu.editMenu, action); 18 } 19 19 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionContext.java
r20058 r23189 5 5 public class AutoCompletionContext { 6 6 7 8 9 10 7 private boolean selectionIncludesNodes = false; 8 private boolean selectionIncludesWays = false; 9 private boolean selectionIncludesRelations = false; 10 private boolean selectionEmpty = false; 11 11 12 13 12 public AutoCompletionContext(){ 13 } 14 14 15 16 17 18 19 20 15 public void initFromJOSMSelection() { 16 selectionIncludesNodes = ! Main.main.getCurrentDataSet().getSelectedNodes().isEmpty(); 17 selectionIncludesWays = !Main.main.getCurrentDataSet().getSelectedWays().isEmpty(); 18 selectionIncludesRelations = !Main.main.getCurrentDataSet().getSelectedRelations().isEmpty(); 19 selectionEmpty = (Main.main.getCurrentDataSet().getSelected().size() == 0); 20 } 21 21 22 23 24 22 public boolean isSelectionEmpty() { 23 return selectionEmpty; 24 } 25 25 26 27 28 26 public boolean isSelectionIncludesNodes() { 27 return selectionIncludesNodes; 28 } 29 29 30 31 32 30 public void setSelectionIncludesNodes(boolean selectionIncludesNodes) { 31 this.selectionIncludesNodes = selectionIncludesNodes; 32 } 33 33 34 35 36 34 public boolean isSelectionIncludesWays() { 35 return selectionIncludesWays; 36 } 37 37 38 39 40 38 public void setSelectionIncludesWays(boolean selectionIncludesWays) { 39 this.selectionIncludesWays = selectionIncludesWays; 40 } 41 41 42 43 44 42 public boolean isSelectionIncludesRelations() { 43 return selectionIncludesRelations; 44 } 45 45 46 47 48 46 public void setSelectionIncludesRelations(boolean selectionIncludesRelations) { 47 this.selectionIncludesRelations = selectionIncludesRelations; 48 } 49 49 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListRenderer.java
r20058 r23189 21 21 public class AutoCompletionListRenderer extends JLabel implements TableCellRenderer { 22 22 23 24 23 static public final String RES_OSM_ICON = "/resources/osm.gif"; 24 static public final String RES_SELECTION_ICON = "/resources/selection.gif"; 25 25 26 27 28 29 26 /** the icon used to decorate items of priority 27 * {@link AutoCompletionItemPritority#IS_IN_STANDARD} 28 */ 29 private Icon iconStandard; 30 30 31 32 33 34 31 /** the icon used to decorate items of priority 32 * {@link AutoCompletionItemPritority#IS_IN_SELECTION} 33 */ 34 private Icon iconSelection; 35 35 36 37 38 39 40 41 42 36 /** 37 * constructor 38 */ 39 public AutoCompletionListRenderer() { 40 setOpaque(true); 41 loadIcons(); 42 } 43 43 44 45 46 47 48 49 50 51 52 53 54 44 /** 45 * loads the icons 46 */ 47 protected void loadIcons() { 48 URL imgURL = getClass().getResource(RES_OSM_ICON); 49 if (imgURL != null) { 50 iconStandard = new ImageIcon(imgURL); 51 } else { 52 System.err.println("Could not load icon: " + RES_OSM_ICON); 53 iconStandard = null; 54 } 55 55 56 57 58 59 60 61 62 63 56 imgURL = getClass().getResource(RES_SELECTION_ICON); 57 if (imgURL != null) { 58 iconSelection = new ImageIcon(imgURL); 59 } else { 60 System.err.println("Could not load icon: " + RES_SELECTION_ICON); 61 iconSelection = null; 62 } 63 } 64 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 65 /** 66 * prepares the renderer for rendering a specific icon 67 * 68 * @param item the item to be rendered 69 */ 70 protected void prepareRendererIcon(AutoCompletionListItem item) { 71 if (item.getPriority().equals(AutoCompletionItemPritority.IS_IN_STANDARD)) { 72 if (iconStandard != null) { 73 setIcon(iconStandard); 74 } 75 } else if (item.getPriority().equals(AutoCompletionItemPritority.IS_IN_SELECTION)) { 76 if (iconSelection != null) { 77 setIcon(iconSelection); 78 } 79 } 80 } 81 81 82 83 84 85 86 87 88 89 90 91 92 82 /** 83 * resets the renderer 84 */ 85 protected void resetRenderer() { 86 setIcon(null); 87 setText(""); 88 setFont(UIManager.getFont("Table.font")); 89 setOpaque(true); 90 setBackground(UIManager.getColor("Table.background")); 91 setForeground(UIManager.getColor("Table.foreground")); 92 } 93 93 94 95 96 97 98 99 100 94 /** 95 * prepares background and text colors for a selected item 96 */ 97 protected void renderSelected() { 98 setBackground(UIManager.getColor("Table.selectionBackground")); 99 setForeground(UIManager.getColor("Table.selectionForeground")); 100 } 101 101 102 103 102 public Component getTableCellRendererComponent(JTable table, Object value, 103 boolean isSelected, boolean hasFocus, int row, int column) { 104 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 105 resetRenderer(); 106 // set icon and text 107 // 108 if (value instanceof AutoCompletionListItem) { 109 AutoCompletionListItem item = (AutoCompletionListItem)value; 110 prepareRendererIcon(item); 111 setText(item.getValue()); 112 setToolTipText(item.getValue()); 113 } else if (value != null) { 114 setText(value.toString()); 115 setToolTipText(value.toString()); 116 } else { 117 setText(tr("unknown")); 118 setFont(getFont().deriveFont(Font.ITALIC)); 119 } 120 120 121 122 123 124 125 126 127 121 // prepare background and foreground for a selected item 122 // 123 if (isSelected) { 124 renderSelected(); 125 } 126 return this; 127 } 128 128 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListViewer.java
r20058 r23189 22 22 23 23 public class AutoCompletionListViewer extends JPanel { 24 25 24 25 static private Logger logger = Logger.getLogger(AutoCompletionListViewer.class.getName()); 26 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 } 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 27 /** the table showing the auto completion list entries */ 28 private JTable table = null; 29 30 /** the auto completion list to be displayed */ 31 private AutoCompletionList autoCompletionList = null; 32 33 /** the listeners */ 34 private ArrayList<IAutoCompletionListListener> listener = null; 35 36 /** 37 * creates the GUI 38 */ 39 protected void createGUI() { 40 setBackground(Color.WHITE); 41 setLayout(new BorderLayout()); 42 43 table = new JTable(); 44 45 // the table model 46 // 47 if (autoCompletionList == null) { 48 //logger.info("setting model to default model"); 49 table.setModel(new DefaultTableModel()); 50 } else { 51 //logger.info("setting model to " + autoCompletionList); 52 table.setModel(autoCompletionList); 53 } 54 55 // no table header required 56 table.setTableHeader(null); 57 58 // set cell renderer 59 // 60 table.setDefaultRenderer(Object.class, new AutoCompletionListRenderer()); 61 62 // embed in a scroll pane 63 JScrollPane p = new JScrollPane(table); 64 p.setBackground(Color.WHITE); 65 add(p, BorderLayout.CENTER); 66 67 // only single selection allowed 68 // 69 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 70 71 // fire item change event on double click 72 // 73 table.addMouseListener( 74 new MouseAdapter() { 75 @Override 76 public void mouseClicked(MouseEvent e) { 77 if (e.getClickCount() == 2) { 78 int row = table.getSelectedRow(); 79 String item = autoCompletionList.getFilteredItem(row).getValue(); 80 fireAutoCompletionListItemSelected(item); 81 } 82 } 83 } 84 ); 85 } 86 87 /** 88 * constructor 89 * 90 * @param list the auto completion list to be rendered. If null, the list is empty. 91 * 92 */ 93 public AutoCompletionListViewer(AutoCompletionList list) { 94 this.autoCompletionList = list; 95 createGUI(); 96 listener = new ArrayList<IAutoCompletionListListener>(); 97 } 98 99 /** 100 * constructor 101 */ 102 public AutoCompletionListViewer() { 103 this.autoCompletionList = null; 104 createGUI(); 105 listener = new ArrayList<IAutoCompletionListListener>(); 106 } 107 107 108 109 110 111 112 113 114 108 /** 109 * 110 */ 111 @Override public Dimension getMaximumSize() { 112 Dimension d = super.getMaximumSize(); 113 d.width = 100; 114 return d; 115 115 } 116 117 118 119 120 121 122 123 116 117 /** 118 * 119 */ 120 @Override public Dimension getPreferredSize() { 121 Dimension d = super.getMaximumSize(); 122 d.width = 150; 123 return d; 124 124 } 125 125 126 126 127 128 129 130 131 132 133 127 /** 128 * replies the auto completion list this viewer renders 129 * 130 * @return the auto completion list; may be null 131 */ 132 public AutoCompletionList getAutoCompletionList() { 133 return autoCompletionList; 134 134 } 135 135 136 136 137 138 139 140 141 142 143 144 145 146 147 148 137 /** 138 * sets the auto completion list this viewer renders 139 * 140 * @param autoCompletionList the auto completion list; may be null 141 */ 142 public void setAutoCompletionList(AutoCompletionList autoCompletionList) { 143 this.autoCompletionList = autoCompletionList; 144 if (autoCompletionList == null) { 145 table.setModel(new DefaultTableModel()); 146 } else { 147 table.setModel(autoCompletionList); 148 } 149 149 } 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 } 185 186 } 187 188 189 190 150 151 /** 152 * add an {@link IAutoCompletionListListener} 153 * 154 * @param listener the listener 155 */ 156 public void addAutoCompletionListListener(IAutoCompletionListListener listener) { 157 if (listener != null && !this.listener.contains(listener)) { 158 synchronized(this.listener) { 159 this.listener.add(listener); 160 } 161 } 162 } 163 164 /** 165 * removes a {@link IAutoCompletionListListener} 166 * 167 * @param listener the listener 168 */ 169 public void removeAutoCompletionListListener(IAutoCompletionListListener listener) { 170 if (listener != null && this.listener.contains(listener)) { 171 synchronized(this.listener) { 172 this.listener.remove(listener); 173 } 174 } 175 } 176 177 /** 178 * notifies listeners about a selected item in the auto completion list 179 */ 180 protected void fireAutoCompletionListItemSelected(String item) { 181 synchronized(this.listener) { 182 for (IAutoCompletionListListener target: listener) { 183 target.autoCompletionItemSelected(item); 184 } 185 } 186 } 187 188 public void installKeyAction(Action a) { 189 getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put((KeyStroke)a.getValue(AbstractAction.ACCELERATOR_KEY), a.getValue(AbstractAction.NAME)); 190 getActionMap().put(a.getValue(AbstractAction.NAME), a); 191 191 192 192 } 193 193 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/IAutoCompletionListListener.java
r14324 r23189 2 2 3 3 public interface IAutoCompletionListListener { 4 4 public void autoCompletionItemSelected(String item); 5 5 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/PresetItemListCellRenderer.java
r20058 r23189 14 14 15 15 public class PresetItemListCellRenderer extends JLabel implements ListCellRenderer { 16 16 private static final Logger logger = Logger.getLogger(PresetItemListCellRenderer.class.getName()); 17 17 18 19 18 public Component getListCellRendererComponent(JList list, Object value, 19 int index, boolean isSelected, boolean cellHasFocus) { 20 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 21 Item item = (Item)value; 22 if (item == null) { 23 setText(tr("(none)")); 24 setIcon(null); 25 } else { 26 if (isSelected) { 27 setBackground(UIManager.getColor("Table.selectionBackground")); 28 setForeground(UIManager.getColor("Table.selectionForeground")); 29 } else { 30 setBackground(UIManager.getColor("Table.background")); 31 setForeground(UIManager.getColor("Table.foreground")); 32 } 33 setIcon(item.getIcon()); 34 StringBuilder sb = new StringBuilder(); 35 sb.append(item.getParent().getName()) 36 .append("/") 37 .append(item.getName()); 38 setText(sb.toString()); 39 setOpaque(true); 40 setFont(UIManager.getFont("Table.font")); 41 } 42 return this; 43 } 44 44 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/PresetManager.java
r20058 r23189 19 19 public class PresetManager extends JPanel { 20 20 21 21 static private final Logger logger = Logger.getLogger(PresetManager.class.getName()); 22 22 23 24 25 26 23 private JComboBox presets; 24 private JButton btnRemove; 25 private JButton btnHighlight; 26 private TagEditorModel model = null; 27 27 28 29 28 protected void build() { 29 setLayout(new FlowLayout(FlowLayout.LEFT)); 30 30 31 32 33 34 35 36 37 38 39 40 31 // create the combobox to display the list of applied presets 32 // 33 presets = new JComboBox() { 34 @Override 35 public Dimension getPreferredSize() { 36 Dimension d = super.getPreferredSize(); 37 d.width = 200; 38 return d; 39 } 40 }; 41 41 42 43 44 45 46 47 48 42 presets.addItemListener( 43 new ItemListener(){ 44 public void itemStateChanged(ItemEvent e) { 45 syncWidgetStates(); 46 } 47 } 48 ); 49 49 50 51 50 presets.setRenderer(new PresetItemListCellRenderer()); 51 add(presets); 52 52 53 54 55 56 57 58 59 60 53 btnHighlight = new JButton(tr("Highlight")); 54 btnHighlight.addActionListener( 55 new ActionListener() { 56 public void actionPerformed(ActionEvent arg0) { 57 highlightCurrentPreset(); 58 } 59 } 60 ); 61 61 62 62 add(btnHighlight); 63 63 64 65 66 67 68 69 70 71 64 btnRemove = new JButton(tr("Remove")); 65 btnRemove.addActionListener( 66 new ActionListener() { 67 public void actionPerformed(ActionEvent arg0) { 68 removeCurrentPreset(); 69 } 70 } 71 ); 72 72 73 74 75 73 add(btnRemove); 74 syncWidgetStates(); 75 } 76 76 77 78 79 80 77 protected void syncWidgetStates() { 78 btnRemove.setEnabled(presets.getSelectedItem() != null); 79 btnHighlight.setEnabled(presets.getSelectedItem() != null); 80 } 81 81 82 83 84 85 86 87 82 protected void removeCurrentPreset() { 83 Item item= (Item)presets.getSelectedItem(); 84 if (item != null && model !=null) { 85 model.removeAppliedPreset(item); 86 } 87 } 88 88 89 90 91 89 protected void highlightCurrentPreset() { 90 model.highlightCurrentPreset(); 91 } 92 92 93 94 95 93 public PresetManager() { 94 build(); 95 } 96 96 97 98 99 100 97 public void setModel(TagEditorModel model) { 98 presets.setModel(model.getAppliedPresetsModel()); 99 this.model = model; 100 } 101 101 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/TableCellRenderer.java
r20197 r23189 26 26 */ 27 27 public class TableCellRenderer extends JLabel implements javax.swing.table.TableCellRenderer { 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 } 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 } 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 28 29 private static Logger logger = Logger.getLogger(TableCellRenderer.class.getName()); 30 public static final Color BG_COLOR_HIGHLIGHTED = new Color(255,255,204); 31 32 private Font fontStandard = null; 33 private Font fontItalic = null; 34 35 public TableCellRenderer() { 36 fontStandard = getFont(); 37 fontItalic = fontStandard.deriveFont(Font.ITALIC); 38 setOpaque(true); 39 setBorder(new EmptyBorder(5,5,5,5)); 40 } 41 42 /** 43 * renders the name of a tag in the second column of 44 * the table 45 * 46 * @param tag the tag 47 */ 48 protected void renderTagName(TagModel tag) { 49 setText(tag.getName()); 50 } 51 52 /** 53 * renders the value of a a tag in the third column of 54 * the table 55 * 56 * @param tag the tag 57 */ 58 protected void renderTagValue(TagModel tag) { 59 if (tag.getValueCount() == 0) { 60 setText(""); 61 } else if (tag.getValueCount() == 1) { 62 setText(tag.getValues().get(0)); 63 } else if (tag.getValueCount() > 1) { 64 setText(tr("multiple")); 65 setFont(fontItalic); 66 } 67 } 68 69 /** 70 * resets the renderer 71 */ 72 protected void resetRenderer() { 73 setText(""); 74 setIcon(null); 75 setFont(fontStandard); 76 } 77 78 protected TagEditorModel getModel(JTable table) { 79 return (TagEditorModel)table.getModel(); 80 } 81 82 protected boolean belongsToSelectedPreset(TagModel tagModel, TagEditorModel model) { 83 84 // current tag is empty or consists of whitespace only => can't belong to 85 // a selected preset 86 // 87 if (tagModel.getName().trim().equals("") && tagModel.getValue().equals("")) { 88 return false; 89 } 90 91 // no current preset selected? 92 // 93 Item item = (Item)model.getAppliedPresetsModel().getSelectedItem(); 94 if (item == null) { 95 return false; 96 } 97 98 for(Tag tag: item.getTags()) { 99 if (tag.getValue() == null) { 100 if (tagModel.getName().equals(tag.getKey())) { 101 return true; 102 } 103 } else { 104 if (tagModel.getName().equals(tag.getKey()) 105 && tagModel.getValue().equals(tag.getValue())) { 106 return true; 107 } 108 } 109 } 110 return false; 111 } 112 113 /** 114 * renders the background color. The default color is white. It is 115 * set to {@see TableCellRenderer#BG_COLOR_HIGHLIGHTED} if this cell 116 * displays the tag which is suggested by the currently selected 117 * preset. 118 * 119 * @param tagModel the tag model 120 * @param model the tag editor model 121 */ 122 protected void renderColor(TagModel tagModel, TagEditorModel model, boolean isSelected) { 123 if (isSelected){ 124 setBackground(UIManager.getColor("Table.selectionBackground")); 125 setForeground(UIManager.getColor("Table.selectionForeground")); 126 } else { 127 setBackground(UIManager.getColor("Table.background")); 128 setForeground(UIManager.getColor("Table.foreground")); 129 } 130 if (belongsToSelectedPreset(tagModel, model)) { 131 setBackground(BG_COLOR_HIGHLIGHTED); 132 } 133 } 134 135 /** 136 * replies the cell renderer component for a specific cell 137 * 138 * @param table the table 139 * @param value the value to be rendered 140 * @param isSelected true, if the value is selected 141 * @param hasFocus true, if the cell has focus 142 * @param rowIndex the row index 143 * @param vColIndex the column index 144 * 145 * @return the renderer component 146 */ 147 public Component getTableCellRendererComponent(JTable table, Object value, 148 148 boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) { 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 149 150 resetRenderer(); 151 TagModel tagModel = (TagModel)value; 152 switch(vColIndex) { 153 case 0: renderTagName(tagModel); break; 154 case 1: renderTagValue(tagModel); break; 155 } 156 renderColor(tagModel, (TagEditorModel)table.getModel(),isSelected); 157 if (hasFocus && isSelected) { 158 if (table.getSelectedColumnCount() == 1 && table.getSelectedRowCount() == 1) { 159 if (table.getEditorComponent() != null) { 160 table.getEditorComponent().requestFocusInWindow(); 161 } 162 } 163 } 164 return this; 165 } 166 166 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/TagEditor.java
r21024 r23189 56 56 public class TagEditor extends JPanel implements IAutoCompletionListListener { 57 57 58 59 60 61 62 63 64 58 private static final Logger logger = Logger.getLogger(TagEditor.class.getName()); 59 60 private TagEditorModel tagEditorModel; 61 private TagTable tblTagEditor; 62 private PresetManager presetManager; 63 64 /** 65 65 * builds the panel with the button row 66 66 * … … 85 85 86 86 public void addComponentNotStoppingCellEditing(Component c) { 87 87 tblTagEditor.addComponentNotStoppingCellEditing(c); 88 88 } 89 89 … … 94 94 JPanel pnl = new JPanel(new GridBagLayout()); 95 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 96 DefaultListSelectionModel rowSelectionModel = new DefaultListSelectionModel(); 97 DefaultListSelectionModel colSelectionModel = new DefaultListSelectionModel(); 98 99 tagEditorModel = new TagEditorModel(rowSelectionModel,colSelectionModel); 100 101 // build the scrollable table for editing tag names and tag values 102 // 103 tblTagEditor = new TagTable(tagEditorModel); 104 tblTagEditor.setTagCellEditor(new TagSpecificationAwareTagCellEditor()); 105 TableCellRenderer renderer = new TableCellRenderer(); 106 tblTagEditor.getColumnModel().getColumn(0).setCellRenderer(renderer); 107 tblTagEditor.getColumnModel().getColumn(1).setCellRenderer(renderer); 108 109 final JScrollPane scrollPane = new JScrollPane(tblTagEditor); 110 JPanel pnlTagTable = new JPanel(new BorderLayout()); 111 pnlTagTable.add(scrollPane, BorderLayout.CENTER); 112 112 113 113 GridBagConstraints gc = new GridBagConstraints(); … … 133 133 } 134 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 135 /** 136 * builds the GUI 137 * 138 */ 139 protected void build() { 140 setLayout(new BorderLayout()); 141 142 add(buildTagEditorPanel(), BorderLayout.CENTER); 143 144 // build the preset manager which shows a list of applied presets 145 // 146 presetManager = new PresetManager(); 147 presetManager.setModel(tagEditorModel); 148 add(presetManager, BorderLayout.NORTH); 149 } 150 151 /** 152 * constructor 153 */ 154 public TagEditor() { 155 build(); 156 } 157 158 /** 159 * replies the tag editor model 160 * @return the tag editor model 161 */ 162 public TagEditorModel getTagEditorModel() { 163 return tagEditorModel; 164 } 165 166 public void clearSelection() { 167 tblTagEditor.getSelectionModel().clearSelection(); 168 } 169 170 public void stopEditing() { 171 TableCellEditor editor = tblTagEditor.getCellEditor(); 172 if (editor != null) { 173 editor.stopCellEditing(); 174 } 175 } 176 177 public void setAutoCompletionList(AutoCompletionList autoCompletionList) { 178 tblTagEditor.setAutoCompletionList(autoCompletionList); 179 } 180 181 public void setAutoCompletionManager(AutoCompletionManager autocomplete) { 182 tblTagEditor.setAutoCompletionManager(autocomplete); 183 } 184 185 public void autoCompletionItemSelected(String item) { 186 logger.info("autocompletion item selected ..."); 187 TagSpecificationAwareTagCellEditor editor = (TagSpecificationAwareTagCellEditor)tblTagEditor.getCellEditor(); 188 if (editor != null) { 189 editor.autoCompletionItemSelected(item); 190 } 191 } 192 193 public void requestFocusInTopLeftCell() { 194 tblTagEditor.requestFocusInCell(0,0); 195 } 196 197 public TagEditorModel getModel() { 198 return tagEditorModel; 199 } 200 200 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/TagEditorModel.java
r20058 r23189 25 25 @SuppressWarnings("serial") 26 26 public class TagEditorModel extends org.openstreetmap.josm.gui.tagging.TagEditorModel { 27 28 29 27 static private final Logger logger = Logger.getLogger(TagEditorModel.class.getName()); 28 29 private DefaultComboBoxModel appliedPresets = null; 30 30 31 32 33 34 35 36 37 31 /** 32 * constructor 33 */ 34 public TagEditorModel(DefaultListSelectionModel rowSelectionModel, DefaultListSelectionModel colSelectionModel){ 35 super(rowSelectionModel, colSelectionModel); 36 appliedPresets = new DefaultComboBoxModel(); 37 } 38 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 39 /** 40 * applies the tags defined for a preset item to the tag model. 41 * 42 * Mandatory tags are added to the list of currently edited tags. 43 * Optional tags are not added. 44 * The model remembers the currently applied presets. 45 * 46 * @param item the preset item. Must not be null. 47 * @exception IllegalArgumentException thrown, if item is null 48 * 49 */ 50 public void applyPreset(Item item) { 51 if (item == null) 52 throw new IllegalArgumentException("argument 'item' must not be null"); 53 // check whether item is already applied 54 // 55 for(int i=0; i < appliedPresets.getSize(); i++) { 56 if (appliedPresets.getElementAt(i).equals(item)) 57 // abort - preset already applied 58 return; 59 } 60 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 61 // apply the tags proposed by the preset 62 // 63 for(Tag tag : item.getTags()) { 64 if (!tag.isOptional()) { 65 if (!includesTag(tag.getKey())) { 66 TagModel tagModel = new TagModel(tag.getKey(),tag.getValue()); 67 prepend(tagModel); 68 } else { 69 TagModel tagModel = get(tag.getKey()); 70 // only overwrite an existing value if the preset 71 // proposes a value. I.e. don't overwrite 72 // existing values for tag 'name' with an empty string 73 // 74 if (tag.getValue() != null) { 75 tagModel.setValue(tag.getValue()); 76 } 77 } 78 } 79 } 80 80 81 82 83 84 85 86 81 // remember the preset and make it the current preset 82 // 83 appliedPresets.addElement(item); 84 appliedPresets.setSelectedItem(item); 85 fireTableDataChanged(); 86 } 87 87 88 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 89 /** 90 * applies a tag given by a {@see KeyValuePair} to the model 91 * 92 * @param pair the key value pair 93 */ 94 public void applyKeyValuePair(KeyValuePair pair) { 95 TagModel tagModel = get(pair.getKey()); 96 if (tagModel == null) { 97 tagModel = new TagModel(pair.getKey(), pair.getValue()); 98 prepend(tagModel); 99 } else { 100 tagModel.setValue(pair.getValue()); 101 } 102 fireTableDataChanged(); 103 } 104 104 105 105 106 107 108 106 public DefaultComboBoxModel getAppliedPresetsModel() { 107 return appliedPresets; 108 } 109 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 110 public void removeAppliedPreset(Item item) { 111 if (item == null) 112 return; 113 for (Tag tag: item.getTags()) { 114 if (tag.getValue() != null) { 115 // preset tag with explicit key and explicit value. Remove tag model 116 // from the current model if both the key and the value match 117 // 118 TagModel tagModel = get(tag.getKey()); 119 if (tagModel !=null && tag.getValue().equals(tagModel.getValue())) { 120 tags.remove(tagModel); 121 setDirty(true); 122 } 123 } else { 124 // preset tag with required key. No explicit value given. Remove tag 125 // model with the respective key 126 // 127 TagModel tagModel = get(tag.getKey()); 128 if (tagModel != null) { 129 tags.remove(tagModel); 130 setDirty(true); 131 } 132 } 133 } 134 appliedPresets.removeElement(item); 135 fireTableDataChanged(); 136 } 137 137 138 139 140 141 138 public void clearAppliedPresets() { 139 appliedPresets.removeAllElements(); 140 fireTableDataChanged(); 141 } 142 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 143 public void highlightCurrentPreset() { 144 fireTableDataChanged(); 145 } 146 147 /** 148 * updates the tags of the primitives in the current selection with the 149 * values in the current tag model 150 * 151 */ 152 public void updateJOSMSelection() { 153 ArrayList<Command> commands = new ArrayList<Command>(); 154 Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelected(); 155 if (selection == null) 156 return; 157 for (TagModel tag : tags) { 158 Command command = createUpdateTagCommand(selection,tag); 159 if (command != null) { 160 commands.add(command); 161 } 162 } 163 Command deleteCommand = createDeleteTagsCommand(selection); 164 if (deleteCommand != null) { 165 commands.add(deleteCommand); 166 } 167 167 168 169 170 171 168 SequenceCommand command = new SequenceCommand( 169 trn("Updating properties of up to {0} object", "Updating properties of up to {0} objects", selection.size(), selection.size()), 170 commands 171 ); 172 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 173 // executes the commands and adds them to the undo/redo chains 174 Main.main.undoRedo.add(command); 175 } 176 177 /** 178 * initializes the model with the tags in the current JOSM selection 179 */ 180 public void initFromJOSMSelection() { 181 Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelected(); 182 clear(); 183 for (OsmPrimitive element : selection) { 184 for (String key : element.keySet()) { 185 String value = element.get(key); 186 add(key,value); 187 } 188 } 189 sort(); 190 setDirty(false); 191 } 192 192 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/editor/TagSpecificationAwareTagCellEditor.java
r21024 r23189 12 12 13 13 public class TagSpecificationAwareTagCellEditor extends TagCellEditor { 14 14 private static final Logger logger = Logger.getLogger(TagCellEditor.class.getName()); 15 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 16 /** 17 * initializes the auto completion list when the table cell editor starts 18 * to edit the key of a tag. In this case the auto completion list is 19 * initialized with the set of standard key values and the set of current key 20 * values from the the current JOSM data set. Keys already present in the 21 * current tag model are removed from the auto completion list. 22 * 23 * @param model the tag editor model 24 * @param currentTag the current tag 25 */ 26 protected void initAutoCompletionListForKeys(TagEditorModel model, TagModel currentTag) { 27 if (getAutoCompletionList() == null) { 28 logger.warning("autoCompletionList is null. Make sure an instance of AutoCompletionList is injected into TableCellEditor."); 29 return; 30 } 31 31 32 32 autoCompletionList.clear(); 33 33 34 35 36 37 38 39 40 34 // add the list of standard keys 35 // 36 try { 37 //autoCompletionList.add(TagSpecifications.getInstance().getKeysForAutoCompletion(context)); 38 } catch(Exception e) { 39 logger.log(Level.WARNING, "failed to initialize auto completion list with standard keys.", e); 40 } 41 41 42 43 44 45 46 47 48 49 50 51 52 42 // add the list of keys in the current data set 43 // 44 autocomplete.populateWithKeys(autoCompletionList); 45 AutoCompletionContext context = new AutoCompletionContext(); 46 try { 47 context.initFromJOSMSelection(); 48 autoCompletionList.add(TagSpecifications.getInstance().getKeysForAutoCompletion(context)); 49 } catch(Exception e) { 50 System.out.println("Warning: failed to initialize auto completion list with tag specification keys. Exception was: " + e.toString()); 51 e.printStackTrace(); 52 } 53 53 54 55 56 57 58 59 60 61 62 54 // remove the keys already present in the current tag model 55 // 56 for (String key : model.getKeys()) { 57 if (! key.equals(currentTag.getName())) { 58 autoCompletionList.remove(key); 59 } 60 } 61 autoCompletionList.fireTableDataChanged(); 62 } 63 63 64 65 66 67 68 69 70 71 72 64 /** 65 * initializes the auto completion list when the cell editor starts to edit 66 * a tag value. In this case the auto completion list is initialized with the 67 * set of standard values for a given key and the set of values present in the 68 * current data set for the given key. 69 * 70 * @param forKey the key 71 */ 72 protected void initAutoCompletionListForValues(String forKey) { 73 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 74 if (autoCompletionList == null) { 75 logger.warning("autoCompletionList is null. Make sure an instance of AutoCompletionList is injected into TableCellEditor."); 76 return; 77 } 78 autoCompletionList.clear(); 79 autocomplete.populateWithTagValues(autoCompletionList, forKey); 80 81 AutoCompletionContext context = new AutoCompletionContext(); 82 try { 83 context.initFromJOSMSelection(); 84 autoCompletionList.add(TagSpecifications.getInstance().getLabelsForAutoCompletion(forKey, context)); 85 } catch(Exception e) { 86 System.out.println("Warning: failed to initialize auto completion list with tag specification values. Exception was: " + e.toString()); 87 e.printStackTrace(); 88 } 89 89 90 91 92 93 94 95 96 97 98 99 100 90 // add the list of possible values for a key from the current selection 91 // 92 if (currentTag.getValueCount() > 1) { 93 for (String value : currentTag.getValues()) { 94 //logger.info("adding ac item " + value + " with priority IN_SELECTION");; 95 autoCompletionList.add( 96 new AutoCompletionListItem(value, AutoCompletionItemPritority.IS_IN_SELECTION) 97 ); 98 } 99 } 100 } 101 101 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/AbstractNameIconProvider.java
r20058 r23189 12 12 13 13 public abstract class AbstractNameIconProvider implements INameIconProvider { 14 15 16 17 18 19 20 21 22 14 15 protected String name; 16 protected String iconName; 17 protected ImageIcon icon; 18 protected File zipIconArchive; 19 20 public String getName() { 21 return name; 22 } 23 23 24 25 26 24 public void setName(String name) { 25 this.name = name; 26 } 27 27 28 29 30 28 public String getIconName() { 29 return iconName; 30 } 31 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 32 public void setIconName(String iconName, File zipIconArchive) { 33 this.iconName = iconName; 34 } 35 36 public Icon getIcon() { 37 if (icon == null) { 38 Collection<String> s = Main.pref.getCollection("taggingpreset.icon.sources", null); 39 icon = ImageProvider.getIfAvailable(s, "presets", null, getIconName(), zipIconArchive); 40 if (icon == null) return null; 41 Image i = icon.getImage().getScaledInstance(16, 16, Image.SCALE_DEFAULT); 42 icon = new ImageIcon(i); 43 } 44 return icon; 45 } 46 46 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Group.java
r20058 r23189 10 10 */ 11 11 public class Group extends AbstractNameIconProvider { 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 12 13 static final private Logger logger = Logger.getLogger(Group.class.getName()); 14 15 private List<Item> items = null; 16 17 public Group() { 18 items = new ArrayList<Item>(); 19 } 20 21 public Group(String name) { 22 this(); 23 setName(name); 24 } 25 26 public void addItem(Item item) { 27 item.setParent(this); 28 items.add(item); 29 } 30 31 public void removeItem(Item item) { 32 items.remove(item); 33 } 34 35 public List<Item> getItems() { 36 return items; 37 } 38 38 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/INameIconProvider.java
r20058 r23189 4 4 5 5 public interface INameIconProvider { 6 7 6 public String getName(); 7 public Icon getIcon(); 8 8 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Item.java
r20058 r23189 7 7 public class Item extends AbstractNameIconProvider { 8 8 9 9 private final static Logger logger = Logger.getLogger(Item.class.getName()); 10 10 11 12 13 11 private String label; 12 private List<Tag> tags; 13 private Group parent; 14 14 15 16 17 15 public Item() { 16 tags = new ArrayList<Tag>(); 17 } 18 18 19 20 21 19 public Group getParent() { 20 return parent; 21 } 22 22 23 24 25 23 public void setParent(Group parent) { 24 this.parent = parent; 25 } 26 26 27 28 29 27 public String getLabel() { 28 return label; 29 } 30 30 31 32 33 31 public void setLabel(String label) { 32 this.label = label; 33 } 34 34 35 36 37 35 public Item(String name) { 36 setName(name); 37 } 38 38 39 40 41 39 public void addTag(Tag tag) { 40 tags.add(tag); 41 } 42 42 43 44 45 43 public List<Tag> getTags() { 44 return tags; 45 } 46 46 47 48 49 50 51 52 53 54 55 47 @Override 48 public String toString() { 49 StringBuilder builder = new StringBuilder(); 50 builder.append("[") 51 .append(getClass().getName()) 52 .append(":") 53 .append("name=") 54 .append(name) 55 .append("]"); 56 56 57 58 57 return builder.toString(); 58 } 59 59 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Presets.java
r20058 r23189 25 25 26 26 public class Presets { 27 27 private static Logger logger = Logger.getLogger(Presets.class.getName()); 28 28 29 29 private static Presets presets = null; 30 30 31 31 static public void initPresets() { 32 32 33 34 33 presets = new Presets(); 34 LinkedList<String> sources = new LinkedList<String>(); 35 35 36 37 38 39 40 41 42 43 36 // code copied from org.openstreetmap.josm.gui.tagging.TaggingPreset 37 // and slightly modified 38 // 39 if (Main.pref.getBoolean("taggingpreset.enable-defaults", true)) { 40 sources.add("resource://data/defaultpresets.xml"); 41 } 42 sources.addAll(Main.pref.getCollection("taggingpreset.sources", 43 new LinkedList<String>())); 44 44 45 46 47 48 45 File zipIconArchive = null; 46 for (String source : sources) { 47 try { 48 MirroredInputStream s = new MirroredInputStream(source); 49 49 InputStream zip = s.getZipEntry("xml","preset"); 50 50 if(zip != null) { 51 51 zipIconArchive = s.getFile(); 52 52 } 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 53 InputStreamReader r; 54 try { 55 r = new InputStreamReader(s, "UTF-8"); 56 } catch (UnsupportedEncodingException e) { 57 r = new InputStreamReader(s); 58 } 59 presets = loadPresets(r, presets, zipIconArchive); 60 } catch (PresetIOException e) { 61 logger 62 .log(Level.SEVERE, tr( 63 "Could not read tagging preset source: {0}", 64 source), e); 65 JOptionPane.showMessageDialog(Main.parent, tr( 66 "Could not read tagging preset source: {0}", source), 67 tr("Error"), JOptionPane.ERROR_MESSAGE); 68 } catch (IOException e) { 69 e.printStackTrace(); 70 JOptionPane.showMessageDialog(Main.parent, tr( 71 "Could not read tagging preset source: {0}", source), 72 tr("Error"), JOptionPane.ERROR_MESSAGE); 73 } 74 } 75 } 76 76 77 78 79 80 81 82 83 84 85 86 87 88 77 static public Presets loadPresets(URL from) throws PresetIOException { 78 try { 79 URLConnection con = from.openConnection(); 80 con.connect(); 81 Reader reader = new InputStreamReader(con.getInputStream()); 82 return loadPresets(reader, null, null); 83 } catch (Exception e) { 84 logger.log(Level.SEVERE, 85 "exception caught while loading preset file", e); 86 throw new PresetIOException(e); 87 } 88 } 89 89 90 91 92 93 94 95 96 97 98 99 100 101 90 static public Presets loadPresets(Reader reader, Presets p, File zipIconArchive) throws PresetIOException { 91 try { 92 Parser parser = new Parser(); 93 parser.setReader(reader); 94 parser.setPresets(p); 95 parser.parse(); 96 return parser.getPresets(); 97 } catch (Exception e) { 98 logger.log(Level.SEVERE, "exception caught while loading presets",e); 99 throw new PresetIOException(e); 100 } 101 } 102 102 103 104 105 106 107 108 103 static public Presets getPresets() { 104 if (presets == null) { 105 initPresets(); 106 } 107 return presets; 108 } 109 109 110 110 private List<Group> groups; 111 111 112 113 114 112 public Presets() { 113 groups = new ArrayList<Group>(); 114 } 115 115 116 117 118 116 public void addGroup(Group group) { 117 groups.add(group); 118 } 119 119 120 121 122 120 public void removeGroup(Group group) { 121 groups.remove(group); 122 } 123 123 124 125 126 124 public List<Group> getGroups() { 125 return groups; 126 } 127 127 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/Tag.java
r20058 r23189 2 2 3 3 public class Tag { 4 5 6 7 8 9 10 4 private String key; 5 private String value; 6 private String displayName; 7 private boolean optional = false; 8 9 public Tag() { 10 } 11 11 12 13 14 12 public String getKey() { 13 return key; 14 } 15 15 16 17 18 16 public void setKey(String key) { 17 this.key = key; 18 } 19 19 20 21 22 20 public String getValue() { 21 return value; 22 } 23 23 24 25 26 24 public void setValue(String value) { 25 this.value = value; 26 } 27 27 28 29 30 28 public String getDisplayName() { 29 return displayName; 30 } 31 31 32 33 34 32 public void setDisplayName(String displayName) { 33 this.displayName = displayName; 34 } 35 35 36 37 38 36 public boolean isOptional() { 37 return optional; 38 } 39 39 40 41 42 40 public void setOptional(boolean optional) { 41 this.optional = optional; 42 } 43 43 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/io/Parser.java
r20058 r23189 22 22 23 23 public class Parser { 24 25 26 24 25 static final private Logger logger = Logger.getLogger(Parser.class.getName()); 26 27 27 private Presets presets = null; 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 } 247 248 249 250 251 252 253 254 255 256 257 258 259 260 } 261 262 263 264 265 266 267 268 269 270 271 28 private Reader reader; 29 private Stack<Group> currentGroup; 30 private Item currentItem; 31 private boolean inOptionalKeys = false; 32 private XMLReader parser; 33 private File zipIconArchive; 34 35 public Parser() { 36 currentGroup = new Stack<Group>(); 37 currentItem = null; 38 } 39 40 public Parser(Reader reader) { 41 this(); 42 if (reader == null) { 43 throw new IllegalArgumentException("reader must not be null"); 44 } 45 this.reader = reader; 46 } 47 48 public void setReader(Reader reader) { 49 this.reader = reader; 50 } 51 52 public Reader getReader() { 53 return reader; 54 } 55 56 public void setZipIconArchive(File zipIconArchive) { 57 this.zipIconArchive = zipIconArchive; 58 } 59 60 public Presets getPresets() { 61 return presets; 62 } 63 64 public void setPresets(Presets presets) { 65 this.presets = presets; 66 } 67 68 protected void init() throws PresetIOException { 69 try { 70 parser = XMLReaderFactory.createXMLReader(); 71 Handler handler = new Handler(); 72 parser.setContentHandler(handler); 73 parser.setErrorHandler(handler); 74 parser.setFeature( "http://xml.org/sax/features/validation", false); 75 parser.setFeature("http://xml.org/sax/features/namespaces", false); 76 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false); 77 } catch(SAXException e) { 78 logger.log(Level.SEVERE, "exception while creating SAX parser", e); 79 throw new PresetIOException("exception while creating SAX parser",e); 80 } 81 } 82 83 /** 84 * parses the presets given by the input source in {@see #getReader()}. 85 * Creates a new set of presets if {@see #getPresets()} is null, otherwise 86 * parses the presets into the set of presets given by {@see #getPresets()}. 87 * 88 * Call {@see #getPresets()} to retrieve the parsed presets after parsing. 89 * 90 * @throws IllegalStateException thrown, if {@see #getReader()} is null. Set a properly initialized reader first. 91 * @throws PresetIOException if an exception is detected during parsing 92 */ 93 public void parse() throws PresetIOException { 94 if (getReader() == null) { 95 throw new IllegalStateException("reader is null. set reader first."); 96 } 97 if (getPresets() == null) { 98 logger.warning("presets is null. Creating a new set of presets"); 99 setPresets(new Presets()); 100 } 101 parse(getReader()); 102 return; 103 } 104 105 /** 106 * parses the presets given by the input source in {@see #getReader()}. 107 * Creates a new set of presets if {@see #getPresets()} is null, otherwise 108 * parses the presets into the set of presets given by {@see #getPresets()}. 109 * 110 * Call {@see #getPresets()} to retrieve the parsed presets after parsing. 111 * 112 * @param reader a properly initialized reader 113 * @throws PresetIOException if an exception is detected during parsing 114 */ 115 public void parse(Reader reader) throws PresetIOException { 116 init(); 117 if (getPresets() == null) { 118 logger.warning("presets is null. Creating a new set of presets"); 119 setPresets(new Presets()); 120 } 121 try { 122 parser.parse(new InputSource(reader)); 123 } catch(Exception e) { 124 logger.log(Level.SEVERE, "exception while parsing preset file", e); 125 throw new PresetIOException(e); 126 } 127 // "release" XML parser 128 parser = null; 129 } 130 131 protected String translatedAttributeValue(String attrValue) { 132 if (attrValue == null) { 133 return null; 134 } else { 135 return tr(attrValue); 136 } 137 } 138 139 protected void onStartGroup(String name, String iconName) { 140 Group g = new Group(); 141 g.setName(translatedAttributeValue(name)); 142 g.setIconName(iconName, zipIconArchive); 143 currentGroup.push(g); 144 } 145 146 protected void onEndGroup() { 147 Group g = currentGroup.pop(); 148 presets.addGroup(g); 149 } 150 151 protected void onStartItem(String name, String iconName) { 152 currentItem = new Item(); 153 currentItem.setName(translatedAttributeValue(name)); 154 currentItem.setIconName(iconName, zipIconArchive); 155 } 156 157 protected void onEndItem() { 158 if (currentGroup == null) { 159 logger.log(Level.SEVERE, "illegal state. no current group defined"); 160 throw new IllegalStateException("illegal state. no current group defined"); 161 } 162 currentGroup.peek().addItem(currentItem); 163 currentItem = null; 164 } 165 166 protected void onStartOptionalKeys() { 167 this.inOptionalKeys = true; 168 } 169 170 protected void onEndOptionalKeys() { 171 this.inOptionalKeys = false; 172 } 173 174 protected void onTag(String key, String value, String displayName){ 175 Tag tag = new Tag(); 176 tag.setKey(key); 177 tag.setValue(value); 178 tag.setDisplayName(translatedAttributeValue(displayName)); 179 tag.setOptional(inOptionalKeys); 180 181 if (currentItem == null) { 182 logger.log(Level.SEVERE, "illegal state. no current item defined"); 183 throw new IllegalStateException("illegal state. no current item defined"); 184 } 185 currentItem.addTag(tag); 186 } 187 188 protected void onLabel(String label) { 189 if (currentItem == null) { 190 logger.log(Level.SEVERE, "illegal state. no current item defined"); 191 throw new IllegalStateException("illegal state. no current item defined"); 192 } 193 currentItem.setLabel(label); 194 } 195 196 /** 197 * The SAX handler for reading XML files with tag specifications 198 * 199 * 200 */ 201 class Handler extends DefaultHandler { 202 203 @Override 204 public void endDocument() throws SAXException { 205 logger.log(Level.FINE,"END"); 206 } 207 208 @Override 209 public void error(SAXParseException e) throws SAXException { 210 logger.log(Level.SEVERE, "XML parsing error", e); 211 } 212 213 @Override 214 public void fatalError(SAXParseException e) throws SAXException { 215 logger.log(Level.SEVERE, "XML parsing error", e); 216 } 217 218 @Override 219 public void startDocument() throws SAXException { 220 logger.log(Level.FINE,"START"); 221 } 222 223 protected String getAttribute(Attributes attributes, String qName) { 224 for (int i =0; i < attributes.getLength();i++) { 225 if (attributes.getQName(i).equals(qName)) { 226 return attributes.getValue(i); 227 } 228 } 229 return null; 230 } 231 232 @Override 233 public void startElement(String namespaceURI, String localName, String qName, 234 Attributes atts) throws SAXException { 235 if ("group".equals(qName)) { 236 onStartGroup(getAttribute(atts, "name"), getAttribute(atts, "icon")); 237 } else if ("item".equals(qName)) { 238 onStartItem(getAttribute(atts, "name"), getAttribute(atts, "icon")); 239 } else if ("label".equals(qName)) { 240 onLabel(getAttribute(atts, "text")); 241 } else if ("optional".equals(qName)) { 242 onStartOptionalKeys(); 243 } else if ("key".equals(qName) || "text".equals(qName) || "combo".equals(qName) 244 || "check".equals(qName)) { 245 onTag(getAttribute(atts, "key"), getAttribute(atts, "value"), getAttribute(atts, "text")); 246 } 247 } 248 249 @Override 250 public void endElement(String namespaceURI, String localName, String qName) 251 throws SAXException { 252 if ("group".equals(qName)) { 253 onEndGroup(); 254 } else if ("item".equals(qName)) { 255 onEndItem(); 256 } else if ("label".equals(qName)) { 257 // do nothing 258 } else if ("optional".equals(qName)) { 259 onEndOptionalKeys(); 260 } 261 } 262 263 /* (non-Javadoc) 264 * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException) 265 */ 266 @Override 267 public void warning(SAXParseException e) throws SAXException { 268 // TODO Auto-generated method stub 269 logger.log(Level.WARNING, "XML parsing warning", e); 270 } 271 } 272 272 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/io/PresetIOException.java
r20058 r23189 3 3 public class PresetIOException extends Exception { 4 4 5 6 7 8 5 public PresetIOException() { 6 super(); 7 // TODO Auto-generated constructor stub 8 } 9 9 10 11 12 13 10 public PresetIOException(String arg0, Throwable arg1) { 11 super(arg0, arg1); 12 // TODO Auto-generated constructor stub 13 } 14 14 15 16 17 18 15 public PresetIOException(String arg0) { 16 super(arg0); 17 // TODO Auto-generated constructor stub 18 } 19 19 20 21 22 23 20 public PresetIOException(Throwable arg0) { 21 super(arg0); 22 // TODO Auto-generated constructor stub 23 } 24 24 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/IPresetSelectorListener.java
r14328 r23189 5 5 public interface IPresetSelectorListener { 6 6 7 7 public void itemSelected(Item item); 8 8 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/NameIconCellRenderer.java
r15319 r23189 16 16 public class NameIconCellRenderer extends JLabel implements TableCellRenderer { 17 17 18 19 18 private static Logger logger = Logger.getLogger(NameIconCellRenderer.class.getName()); 19 public static final Color BG_COLOR_SELECTED = new Color(143,170,255); 20 20 21 21 22 23 24 25 22 protected void init() { 23 setOpaque(true); 24 setFont(new Font("SansSerif",Font.PLAIN,10)); 25 } 26 26 27 28 29 27 public NameIconCellRenderer() { 28 init(); 29 } 30 30 31 32 31 public Component getTableCellRendererComponent(JTable table, Object value, 32 boolean isSelected, boolean hasFocus, int rowIndex, int colIndex) { 33 33 34 35 36 37 38 39 40 41 42 43 34 if (isSelected) { 35 setBackground(BG_COLOR_SELECTED); 36 } else { 37 setBackground(Color.WHITE); 38 } 39 INameIconProvider provider = (INameIconProvider) value; 40 setText(provider.getName()); 41 setIcon(provider.getIcon()); 42 return this; 43 } 44 44 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/PresetsTable.java
r14328 r23189 9 9 public class PresetsTable extends JTable { 10 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 11 /** 12 * initialize the table 13 */ 14 protected void init() { 15 setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 16 setRowSelectionAllowed(true); 17 setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 18 setRowHeight(18); // icon height (=16) + minimal border 19 20 } 21 22 public PresetsTable(TableModel model, TableColumnModel columnModel) { 23 super(model,columnModel); 24 init(); 25 } 26 27 /** 28 * adjusts the width of the columns for the tag name and the tag value 29 * to the width of the scroll panes viewport. 30 * 31 * Note: {@see #getPreferredScrollableViewportSize()} did not work as expected 32 * 33 * @param scrollPaneWidth the width of the scroll panes viewport 34 */ 35 public void adjustColumnWidth(int scrollPaneWidth) { 36 TableColumnModel tcm = getColumnModel(); 37 int width = scrollPaneWidth; 38 width = width / 2; 39 if (width > 0) { 40 tcm.getColumn(0).setMinWidth(width); 41 tcm.getColumn(0).setMaxWidth(width); 42 tcm.getColumn(1).setMinWidth(width); 43 tcm.getColumn(1).setMaxWidth(width); 44 } 45 } 46 46 47 47 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/PresetsTableColumnModel.java
r14328 r23189 8 8 public class PresetsTableColumnModel extends DefaultTableColumnModel { 9 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 10 protected void createColumns() { 11 TableCellRenderer renderer = new NameIconCellRenderer(); 12 13 TableColumn col = null; 14 15 // column 0 - Group 16 col = new TableColumn(0); 17 col.setHeaderValue(tr("Group")); 18 col.setResizable(true); 19 col.setCellRenderer(renderer); 20 addColumn(col); 21 22 // column 1 - Item 23 col = new TableColumn(1); 24 col.setHeaderValue(tr("Item")); 25 col.setResizable(true); 26 col.setCellRenderer(renderer); 27 addColumn(col); 28 28 29 29 } 30 30 31 32 33 34 31 public PresetsTableColumnModel() { 32 createColumns(); 33 } 34 35 35 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/PresetsTableModel.java
r17637 r23189 14 14 public class PresetsTableModel extends AbstractTableModel { 15 15 16 16 private static final Logger logger = Logger.getLogger(PresetsTableModel.class.getName()); 17 17 18 19 20 21 18 private final ArrayList<TableModelListener> listeners = new ArrayList<TableModelListener>(); 19 private final ArrayList<Item> items = new ArrayList<Item>(); 20 private final ArrayList<Item> visibleItems = new ArrayList<Item>(); 21 private Presets presets = null; 22 22 23 24 25 26 27 28 29 30 23 protected void initModelFromPresets(Presets presets) { 24 for(Group group: presets.getGroups()) { 25 for(Item item: group.getItems()) { 26 items.add(item); 27 visibleItems.add(item); 28 } 29 } 30 } 31 31 32 33 32 public PresetsTableModel() { 33 } 34 34 35 36 37 35 public PresetsTableModel(Presets presets) { 36 setPresets(presets); 37 } 38 38 39 39 40 41 42 40 public Presets getPresets() { 41 return presets; 42 } 43 43 44 45 46 47 48 44 public void setPresets(Presets presets) { 45 this.presets = presets; 46 initModelFromPresets(presets); 47 fireTableDataChanged(); 48 } 49 49 50 51 52 53 54 55 56 57 58 59 50 @Override 51 public void addTableModelListener(TableModelListener l) { 52 synchronized(listeners) { 53 if (l == null) 54 return; 55 if (!listeners.contains(l)) { 56 listeners.add(l); 57 } 58 } 59 } 60 60 61 62 63 64 61 @Override 62 public Class<?> getColumnClass(int columnIndex) { 63 return String.class; 64 } 65 65 66 67 68 66 public int getColumnCount() { 67 return 2; 68 } 69 69 70 71 72 70 public int getRowCount() { 71 return visibleItems.size(); 72 } 73 73 74 75 76 77 78 79 74 public Object getValueAt(int rowIndex, int columnIndex) { 75 Item item = visibleItems.get(rowIndex); 76 switch(columnIndex) { 77 case 0: return item.getParent(); 78 case 1: return item; 79 default: return "unknown"; 80 80 81 82 81 } 82 } 83 83 84 85 86 87 84 @Override 85 public boolean isCellEditable(int rowIndex, int columnIndex) { 86 return false; 87 } 88 88 89 90 91 92 93 94 95 96 89 @Override 90 public void removeTableModelListener(TableModelListener l) { 91 synchronized (listeners) { 92 if (listeners.contains(l)) { 93 listeners.remove(l); 94 } 95 } 96 } 97 97 98 99 100 101 98 @Override 99 public void setValueAt(Object value, int rowIndex, int columnIndex) { 100 // do nothing. No editing allowed 101 } 102 102 103 104 105 106 107 103 public Item getVisibleItem(int idx) { 104 if (idx < 0 || idx >= this.visibleItems.size()) 105 throw new IndexOutOfBoundsException("index out of bounds. idx=" + idx); 106 return visibleItems.get(idx); 107 } 108 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 109 public void filter(String filter) { 110 synchronized(this) { 111 if (filter == null || filter.trim().equals("")) { 112 visibleItems.clear(); 113 for(Item item: items) { 114 visibleItems.add(item); 115 } 116 } else { 117 visibleItems.clear(); 118 filter = filter.toLowerCase(); 119 for(Item item: items) { 120 if ( (item.getName() != null && item.getName().toLowerCase().trim().startsWith(filter)) 121 || (item.getParent().getName() != null && item.getParent().getName().toLowerCase().trim().startsWith(filter))) { 122 visibleItems.add(item); 123 } 124 } 125 } 126 fireTableDataChanged(); 127 fireTableStructureChanged(); 128 } 129 } 130 130 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/preset/ui/TabularPresetSelector.java
r21024 r23189 37 37 public class TabularPresetSelector extends JPanel { 38 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 39 private PresetsTable presetsTable = null; 40 private JTextField tfFilter = null; 41 private final ArrayList<IPresetSelectorListener> listeners = new ArrayList<IPresetSelectorListener>(); 42 private JScrollPane scrollPane; 43 private JButton btnApply; 44 45 46 protected JPanel buildFilterPanel() { 47 JPanel pnl = new JPanel(); 48 JLabel lbl = new JLabel(tr("Search: ")); 49 pnl.setLayout(new FlowLayout(FlowLayout.LEFT)); 50 tfFilter = new JTextField(20); 51 pnl.add(lbl); 52 pnl.add(tfFilter,BorderLayout.CENTER); 53 JButton btn = new JButton(tr("Filter")); 54 pnl.add(btn); 55 btn.addActionListener( 56 new ActionListener() { 57 public void actionPerformed(ActionEvent e) { 58 filter(tfFilter.getText()); 59 } 60 61 } 62 ); 63 btn = new JButton(tr("Clear")); 64 pnl.add(btn); 65 btn.addActionListener( 66 new ActionListener() { 67 public void actionPerformed(ActionEvent e) { 68 tfFilter.setText(""); 69 tfFilter.requestFocus(); 70 } 71 } 72 ); 73 return pnl; 74 } 75 76 77 78 protected JScrollPane buildPresetGrid() { 79 80 presetsTable = new PresetsTable(new PresetsTableModel(),new PresetsTableColumnModel()); 81 82 scrollPane = new JScrollPane(presetsTable); 83 84 scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 85 scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 86 87 // this adapters ensures that the width of the tag table columns is adjusted 88 // to the width of the scroll pane viewport. Also tried to overwrite 89 // getPreferredViewportSize() in JTable, but did not work. 90 // 91 scrollPane.addComponentListener( 92 new ComponentAdapter() { 93 @Override public void componentResized(ComponentEvent e) { 94 super.componentResized(e); 95 Dimension d = scrollPane.getViewport().getExtentSize(); 96 presetsTable.adjustColumnWidth(d.width); 97 } 98 } 99 ); 100 101 // add the double click listener 102 // 103 presetsTable.addMouseListener(new DoubleClickAdapter()); 104 105 // replace Enter action. apply the current preset on enter 106 // 107 presetsTable.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0)); 108 ActionListener enterAction = new ActionListener() { 109 public void actionPerformed(ActionEvent e) { 110 int rowNum = presetsTable.getSelectedRow(); 111 if (rowNum >= 0) { 112 Item item = getModel().getVisibleItem(rowNum); 113 fireItemSelected(item); 114 } 115 } 116 }; 117 118 presetsTable.registerKeyboardAction( 119 enterAction, 120 "Enter", 121 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), 122 JComponent.WHEN_FOCUSED 123 ); 124 125 return scrollPane; 126 } 127 128 protected JPanel buildControlButtonPanel() { 129 JPanel pnl = new JPanel(); 130 pnl.setLayout(new FlowLayout(FlowLayout.LEFT)); 131 btnApply = new JButton(tr("Apply")); 132 pnl.add(btnApply); 133 btnApply.addActionListener( 134 new ActionListener() { 135 public void actionPerformed(ActionEvent arg0) { 136 int row = presetsTable.getSelectedRow(); 137 if (row >=0) { 138 Item item = getModel().getVisibleItem(row); 139 fireItemSelected(item); 140 } 141 } 142 } 143 ); 144 return pnl; 145 } 146 147 protected void build() { 148 setLayout(new BorderLayout()); 149 add(buildFilterPanel(), BorderLayout.NORTH); 150 add(buildPresetGrid(), BorderLayout.CENTER); 151 add(buildControlButtonPanel(), BorderLayout.SOUTH); 152 153 // wire the text field for filter expressions to the prests 154 // table 155 // 156 tfFilter.getDocument().addDocumentListener( 157 new DocumentListener() { 158 public void changedUpdate(DocumentEvent arg0) { 159 onUpdate(); 160 } 161 162 public void insertUpdate(DocumentEvent arg0) { 163 onUpdate(); 164 } 165 166 public void removeUpdate(DocumentEvent arg0) { 167 onUpdate(); 168 } 169 170 protected void onUpdate() { 171 filter(tfFilter.getText()); 172 } 173 } 174 ); 175 176 tfFilter.addActionListener( 177 new ActionListener() { 178 public void actionPerformed(ActionEvent e) { 179 filter(tfFilter.getText()); 180 } 181 } 182 ); 183 184 // wire the apply button to the selection model of the preset table 185 // 186 presetsTable.getSelectionModel().addListSelectionListener( 187 new ListSelectionListener() { 188 public void valueChanged(ListSelectionEvent e) { 189 btnApply.setEnabled(presetsTable.getSelectedRowCount() != 0); 190 } 191 } 192 ); 193 194 195 // load the set of presets and bind them to the preset table 196 // 197 Presets.initPresets(); 198 bindTo(Presets.getPresets()); 199 presetsTable.getSelectionModel().clearSelection(); 200 btnApply.setEnabled(false); 201 202 } 203 204 public void bindTo(Presets presets) { 205 PresetsTableModel model = (PresetsTableModel)presetsTable.getModel(); 206 model.setPresets(presets); 207 } 208 209 public TabularPresetSelector() { 210 build(); 211 } 212 213 public void addPresetSelectorListener(IPresetSelectorListener listener) { 214 synchronized(this.listeners) { 215 if (listener != null && ! listeners.contains(listener)) { 216 listeners.add(listener); 217 } 218 } 219 } 220 221 public void removePresetSelectorListener(IPresetSelectorListener listener) { 222 synchronized(this.listeners) { 223 if (listener != null) { 224 listeners.remove(listener); 225 } 226 } 227 } 228 229 protected void fireItemSelected(Item item) { 230 synchronized(this.listeners) { 231 for(IPresetSelectorListener listener: listeners) { 232 listener.itemSelected(item); 233 } 234 } 235 } 236 237 238 239 240 private class DoubleClickAdapter extends MouseAdapter { 241 @Override 242 public void mouseClicked(MouseEvent e) { 243 if (e.getClickCount() == 2) { 244 int rowNum = presetsTable.rowAtPoint(e.getPoint()); 245 Item item = getModel().getVisibleItem(rowNum); 246 fireItemSelected(item); 247 } 248 } 249 } 250 251 252 public void filter(String filter) { 253 presetsTable.getSelectionModel().clearSelection(); 254 getModel().filter(filter); 255 256 presetsTable.scrollRectToVisible(presetsTable.getCellRect(0, 0, false)); 257 258 // we change the number of rows by applying a filter condition. Because 259 // the table is embedded in a JScrollPane which again may be embedded in 260 // other JScrollPanes or JSplitPanes it seems that we have to recalculate 261 // the layout and repaint the component tree. Maybe there is a more efficient way 262 // to keep the GUI in sync with the number of rows in table. By trial 263 // and error I ended up with the following lines. 264 // 265 Component c = presetsTable; 266 while(c != null) { 267 c.doLayout(); 268 c.repaint(); 269 c = c.getParent(); 270 } 271 } 272 273 274 protected PresetsTableModel getModel() { 275 return (PresetsTableModel)presetsTable.getModel(); 276 } 277 278 public void installKeyAction(Action a) { 279 getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put((KeyStroke)a.getValue(AbstractAction.ACCELERATOR_KEY), a.getValue(AbstractAction.NAME)); 280 getActionMap().put(a.getValue(AbstractAction.NAME), a); 281 282 } 283 283 284 284 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/KeyValuePair.java
r14329 r23189 2 2 3 3 public class KeyValuePair { 4 5 6 7 8 9 10 11 12 4 private String key = new String(""); 5 private String value = new String(""); 6 7 public KeyValuePair() {} 8 9 public KeyValuePair(String key, String value) { 10 setKey(key); 11 setValue(value); 12 } 13 13 14 15 16 17 14 15 public String getKey() { 16 return key; 17 } 18 18 19 20 21 19 public void setKey(String key) { 20 this.key = key == null? "" :key; 21 } 22 22 23 24 25 23 public String getValue() { 24 return value; 25 } 26 26 27 28 29 27 public void setValue(String value) { 28 this.value = value == null ? "" : value; 29 } 30 30 31 32 33 34 35 36 37 38 31 @Override 32 public int hashCode() { 33 final int prime = 31; 34 int result = 1; 35 result = prime * result + ((key == null) ? 0 : key.hashCode()); 36 result = prime * result + ((value == null) ? 0 : value.hashCode()); 37 return result; 38 } 39 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 40 @Override 41 public boolean equals(Object obj) { 42 if (this == obj) 43 return true; 44 if (obj == null) 45 return false; 46 if (getClass() != obj.getClass()) 47 return false; 48 KeyValuePair other = (KeyValuePair) obj; 49 if (key == null) { 50 if (other.key != null) 51 return false; 52 } else if (!key.equals(other.key)) 53 return false; 54 if (value == null) { 55 if (other.value != null) 56 return false; 57 } else if (!value.equals(other.value)) 58 return false; 59 return true; 60 } 61 61 62 62 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/LableSpecification.java
r14329 r23189 5 5 public class LableSpecification { 6 6 7 8 9 10 11 12 13 14 15 16 17 18 19 7 /** the key of the tag */ 8 private String value; 9 10 11 private boolean applicableToNode = true; 12 private boolean applicableToWay = true; 13 private boolean applicableToRelation = true; 14 15 /** 16 * constructor 17 */ 18 public LableSpecification() { 19 } 20 20 21 22 23 24 25 26 27 28 29 30 31 21 public boolean isApplicable(AutoCompletionContext context) { 22 boolean ret = false; 23 if (context.isSelectionEmpty()) { 24 ret = true; 25 } else { 26 ret = ret || (applicableToNode && context.isSelectionIncludesNodes()); 27 ret = ret || (applicableToWay && context.isSelectionIncludesWays()); 28 ret = ret || (applicableToRelation && context.isSelectionIncludesRelations()); 29 } 30 return ret; 31 } 32 32 33 34 35 33 /* --------------------------------------------------------------------------- */ 34 /* setters/getters */ 35 /* --------------------------------------------------------------------------- */ 36 36 37 38 39 37 public String getValue() { 38 return value; 39 } 40 40 41 42 43 41 public void setValue(String value) { 42 this.value = value; 43 } 44 44 45 46 47 45 public boolean isApplicableToNode() { 46 return applicableToNode; 47 } 48 48 49 50 51 49 public void setApplicableToNode(boolean applicableToNode) { 50 this.applicableToNode = applicableToNode; 51 } 52 52 53 54 55 53 public boolean isApplicableToWay() { 54 return applicableToWay; 55 } 56 56 57 58 59 57 public void setApplicableToWay(boolean applicableToWay) { 58 this.applicableToWay = applicableToWay; 59 } 60 60 61 62 63 61 public boolean isApplicableToRelation() { 62 return applicableToRelation; 63 } 64 64 65 66 67 68 65 public void setApplicableToRelation(boolean applicableToRelation) { 66 this.applicableToRelation = applicableToRelation; 67 } 68 69 69 70 71 70 71 72 72 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/TagSpecification.java
r20058 r23189 10 10 * elements: 11 11 * <ul> 12 * 12 * <li>the <strong>key</strong> the of the tag</li> 13 13 * <li>the <strong>type</strong> of the tag</li> 14 14 * <li>whether the tag is applicable to a node, a way or a relation</li> … … 19 19 public class TagSpecification { 20 20 21 22 21 /** the key of the tag */ 22 private String key; 23 23 24 25 24 /** the type of the tag */ 25 private String type; 26 26 27 27 /** the type of the tag */ 28 28 29 30 31 29 private boolean applicableToNode = true; 30 private boolean applicableToWay = true; 31 private boolean applicableToRelation = true; 32 32 33 33 private ArrayList<LableSpecification> lables = null; 34 34 35 35 36 37 38 39 40 41 36 /** 37 * constructor 38 */ 39 public TagSpecification() { 40 lables = new ArrayList<LableSpecification>(); 41 } 42 42 43 44 45 46 47 48 49 50 51 52 53 54 43 @Override 44 public String toString() { 45 StringBuilder builder = new StringBuilder(); 46 builder.append("<TagSpecification "); 47 builder.append("key=\"").append(key).append("\"").append(", "); 48 builder.append("type=\"").append(type).append("\"").append(", "); 49 builder.append("applicable-to-node=\"").append(applicableToNode).append("\"").append(", "); 50 builder.append("applicable-to-way=\"").append(applicableToWay).append("\"").append(", "); 51 builder.append("applicable-to-relation=\"").append(applicableToRelation).append("\""); 52 builder.append(" />"); 53 return builder.toString(); 54 } 55 55 56 57 58 59 60 61 62 56 /** 57 * @return th e list of predefined labels for this tag; an empty list if no 58 * labels are defined 59 */ 60 public List<LableSpecification> getLables() { 61 return lables; 62 } 63 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 64 /** 65 * sets the list of lables for this tag specification 66 * 67 * @param lables the list of lables; must not be null 68 * @exception IllegalArgumentException thrown, if lables is null 69 */ 70 public void setLables(List<LableSpecification> lables) throws IllegalArgumentException { 71 if (lables == null) 72 throw new IllegalArgumentException("argument 'lables' must not be null"); 73 this.lables.clear(); 74 for (LableSpecification l : lables) { 75 this.lables.add(l); 76 } 77 } 78 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 79 /** 80 * Adds a label to the list of label for this tag specification. The label 81 * is only added if i 82 * 83 * @param lable the lalbe to add; must not be null 84 * @exception IllegalArgumentException thrown, if lable is null 85 */ 86 public void addLable(LableSpecification lable) throws IllegalArgumentException { 87 if (lable == null) 88 throw new IllegalArgumentException("argument 'lable' must not be null"); 89 if (!this.lables.contains(lable)) { 90 this.lables.add(lable); 91 } 92 } 93 93 94 95 96 97 98 99 100 101 102 103 104 94 public boolean isApplicable(AutoCompletionContext context) { 95 boolean ret = false; 96 if (context.isSelectionEmpty()) { 97 ret = true; 98 } else { 99 ret = ret || (applicableToNode && context.isSelectionIncludesNodes()); 100 ret = ret || (applicableToWay && context.isSelectionIncludesWays()); 101 ret = ret || (applicableToRelation && context.isSelectionIncludesRelations()); 102 } 103 return ret; 104 } 105 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 106 /* --------------------------------------------------------------------------- */ 107 /* setters/getters */ 108 /* --------------------------------------------------------------------------- */ 109 public String getKey() { 110 return key; 111 } 112 public void setKey(String key) { 113 this.key = key; 114 } 115 public String getType() { 116 return type; 117 } 118 public void setType(String type) { 119 this.type = type; 120 } 121 public boolean isApplicableToNode() { 122 return applicableToNode; 123 } 124 public void setApplicableToNode(boolean applicableToNode) { 125 this.applicableToNode = applicableToNode; 126 } 127 public boolean isApplicableToWay() { 128 return applicableToWay; 129 } 130 public void setApplicableToWay(boolean applicableToWay) { 131 this.applicableToWay = applicableToWay; 132 } 133 public boolean isApplicableToRelation() { 134 return applicableToRelation; 135 } 136 public void setApplicableToRelation(boolean applicableToRelation) { 137 this.applicableToRelation = applicableToRelation; 138 } 139 139 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/TagSpecifications.java
r20058 r23189 35 35 public class TagSpecifications { 36 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 37 final static public String ATTR_KEY = "key"; 38 final static public String ATTR_TYPE = "type"; 39 final static public String ATTR_FOR_NODE = "for-node"; 40 final static public String ATTR_FOR_WAY = "for-way"; 41 final static public String ATTR_FOR_RELATION = "for-relation"; 42 final static public String ATTR_VALUE = "value"; 43 44 final static public String ELEM_ROOT = "osm-tag-definitions"; 45 final static public String ELEM_TAG = "tag"; 46 final static public String ELEM_LABEL = "label"; 47 48 final static public String DTD = "osm-tag-definitions.dtd"; 49 50 51 /** the default name of the resource file with the tag specifications */ 52 static public final String RES_NAME_TAG_SPECIFICATIONS = "/resources/osm-tag-definitions.xml"; 53 54 /** the logger object */ 55 private static Logger logger = Logger.getLogger(TagSpecification.class.getName()); 56 57 /** list of tag specifications managed list */ 58 private ArrayList<TagSpecification> tagSpecifications = null; 59 60 private static TagSpecifications instance = null; 61 62 /** 63 * loads the the tag specifications from the resource file given by 64 * {@link #RES_NAME_TAG_SPECIFICATIONS}. 65 * 66 * @return the list of {@link TagSpecification}s 67 * @throws Exception thrown, if an exception occurs 68 */ 69 static public void loadFromResources() throws Exception { 70 InputStream in = TagSpecifications.class.getResourceAsStream(RES_NAME_TAG_SPECIFICATIONS); 71 if (in == null) { 72 logger.log(Level.SEVERE, "failed to create input stream for resource '" + RES_NAME_TAG_SPECIFICATIONS + "'"); 73 } 74 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 75 TagSpecifications spec = new TagSpecifications(); 76 spec.load(reader); 77 reader.close(); 78 instance = spec; 79 80 } 81 82 static public TagSpecifications getInstance() throws Exception { 83 if (instance == null) { 84 loadFromResources(); 85 } 86 return instance; 87 } 88 89 /** 90 * constructor 91 */ 92 public TagSpecifications() { 93 tagSpecifications = new ArrayList<TagSpecification>(); 94 } 95 96 97 /** 98 * loads the tag specifications from a specific reader 99 * 100 * @param in the reader to read from 101 * @throws Exception thrown, if an exception occurs 102 */ 103 public void load(Reader in) throws Exception { 104 XMLReader parser; 105 106 try { 107 parser = XMLReaderFactory.createXMLReader(); 108 Handler handler = new Handler(); 109 parser.setContentHandler(handler); 110 parser.setErrorHandler(handler); 111 parser.setEntityResolver(new ResourceEntityResolver()); 112 parser.setFeature( "http://xml.org/sax/features/validation", true); 113 parser.setFeature("http://xml.org/sax/features/namespaces", true); 114 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 115 parser.parse(new InputSource(in)); 116 117 } catch (Exception e) { 118 logger.log(Level.SEVERE, "failed to load tag specificatoin file", e); 119 throw e; 120 } finally { 121 parser = null; 122 } 123 } 124 125 public List<AutoCompletionListItem> getKeysForAutoCompletion(AutoCompletionContext context) { 126 ArrayList<AutoCompletionListItem> keys = new ArrayList<AutoCompletionListItem>(); 127 for (TagSpecification spec : tagSpecifications) { 128 if (!spec.isApplicable(context)) { 129 continue; 130 } 131 AutoCompletionListItem item = new AutoCompletionListItem(); 132 item.setValue(spec.getKey()); 133 item.setPriority(AutoCompletionItemPritority.IS_IN_STANDARD); 134 keys.add(item); 135 } 136 return keys; 137 } 138 139 public List<AutoCompletionListItem> getLabelsForAutoCompletion(String forKey, AutoCompletionContext context) { 140 ArrayList<AutoCompletionListItem> items = new ArrayList<AutoCompletionListItem>(); 141 for (TagSpecification spec : tagSpecifications) { 142 if (spec.getKey().equals(forKey)) { 143 List<LableSpecification> lables = spec.getLables(); 144 for (LableSpecification l : lables) { 145 if (!l.isApplicable(context)) { 146 continue; 147 } 148 AutoCompletionListItem item = new AutoCompletionListItem(); 149 item.setValue(l.getValue()); 150 item.setPriority(AutoCompletionItemPritority.IS_IN_STANDARD); 151 items.add(item); 152 } 153 } 154 } 155 return items; 156 } 157 158 /** 159 * replies a list of {@see KeyValuePair}s for all {@see TagSpecification}s and 160 * {@see LableSpecification}s. 161 * 162 * @return the list 163 */ 164 public ArrayList<KeyValuePair> asList() { 165 ArrayList<KeyValuePair> entries = new ArrayList<KeyValuePair>(); 166 167 for (TagSpecification s : tagSpecifications) { 168 for (LableSpecification l : s.getLables()) { 169 entries.add(new KeyValuePair(s.getKey(), l.getValue())); 170 } 171 } 172 return entries; 173 } 174 175 176 177 /** 178 * The SAX handler for reading XML files with tag specifications 179 * 180 * @author gubaer 181 * 182 */ 183 class Handler extends DefaultHandler { 184 185 /** the current tag specification. Not null, while parsing the content 186 * between <tag> ... </tag> 187 */ 188 private TagSpecification currentTagSpecification = null; 189 190 191 @Override 192 public void endDocument() throws SAXException { 193 logger.log(Level.FINE,"END"); 194 } 195 196 197 198 @Override 199 public void error(SAXParseException e) throws SAXException { 200 logger.log(Level.SEVERE, "XML parsing error", e); 201 } 202 203 @Override 204 public void fatalError(SAXParseException e) throws SAXException { 205 logger.log(Level.SEVERE, "XML parsing error", e); 206 } 207 208 @Override 209 public void startDocument() throws SAXException { 210 logger.log(Level.FINE,"START"); 211 } 212 213 214 /** 215 * parses a string value consisting of 'yes' or 'no' (exactly, case 216 * sensitive) 217 * 218 * @param value the string value 219 * @return true, if value is <code>yes</code>; false, if value is <code>no</code> 220 * @throws SAXException thrown, if value is neither <code>yes</code> nor <code>no</code> 221 */ 222 protected boolean parseYesNo(String value) throws SAXException { 223 if ("yes".equals(value)) 224 return true; 225 else if ("no".equals(value)) 226 return false; 227 else 228 throw new SAXException("expected 'yes' or 'no' as attribute value, got '" + value + "'"); 229 } 230 231 /** 232 * handles a start element with name <code>osm-tag-definitions</code> 233 * 234 * @param atts the XML attributes 235 * @throws SAXException 236 */ 237 protected void startElementOsmTagDefinitions(Attributes atts) throws SAXException { 238 tagSpecifications = new ArrayList<TagSpecification>(); 239 } 240 241 /** 242 * handles an end element with name <code>osm-tag-specifications</code> 243 * 244 * @throws SAXException 245 */ 246 protected void endElementOsmTagDefinitions() throws SAXException { 247 // do nothing 248 } 249 250 /** 251 * handles a start element with name <code>tag</code> 252 * 253 * @param atts the XML attributes of the element 254 * @throws SAXException 255 */ 256 protected void startElementTag(Attributes atts) throws SAXException { 257 currentTagSpecification = new TagSpecification(); 258 for (int i=0; i< atts.getLength(); i++) { 259 String name = atts.getQName(i); 260 String value = atts.getValue(i); 261 262 if (ATTR_KEY.equals(name)) { 263 currentTagSpecification.setKey(value); 264 } else if (ATTR_TYPE.equals(name)) { 265 currentTagSpecification.setType(value); 266 } else if (ATTR_FOR_NODE.equals(name)) { 267 currentTagSpecification.setApplicableToNode(parseYesNo(value)); 268 } else if (ATTR_FOR_WAY.equals(name)) { 269 currentTagSpecification.setApplicableToWay(parseYesNo(value)); 270 } else if (ATTR_FOR_RELATION.equals(name)) { 271 currentTagSpecification.setApplicableToRelation(parseYesNo(value)); 272 } else 273 throw new SAXException("unknown attribut '" + name + "' on element 'tag'"); 274 } 275 } 276 277 278 /** 279 * handles an end element with name <code>tag</code> 280 * @throws SAXException 281 */ 282 protected void endElementTag() throws SAXException { 283 tagSpecifications.add(currentTagSpecification); 284 currentTagSpecification = null; 285 286 } 287 288 /** 289 * handles a start element with name <code>label</code> 290 * 291 * @param atts the XML attributes 292 * @throws SAXException 293 */ 294 protected void startElementLabel(Attributes atts) throws SAXException { 295 LableSpecification ls = new LableSpecification(); 296 for (int i=0; i< atts.getLength(); i++) { 297 String name = atts.getQName(i); 298 String value = atts.getValue(i); 299 300 if (ATTR_VALUE.equals(name)) { 301 ls.setValue(value); 302 } else if (ATTR_FOR_NODE.equals(name)) { 303 ls.setApplicableToNode(parseYesNo(value)); 304 } else if (ATTR_FOR_WAY.equals(name)) { 305 ls.setApplicableToWay(parseYesNo(value)); 306 } else if (ATTR_FOR_RELATION.equals(name)) { 307 ls.setApplicableToRelation(parseYesNo(value)); 308 } else 309 throw new SAXException("unknown attribut '" + name + "' on element 'lable'"); 310 } 311 currentTagSpecification.addLable(ls); 312 } 313 314 /** 315 * handles an end element with name <code>label</code> 316 * 317 * @throws SAXException 318 */ 319 protected void endElementLabel() throws SAXException { 320 // do nothing 321 } 322 323 @Override 324 public void startElement(String namespaceURI, String localName, String qName, 325 Attributes atts) throws SAXException { 326 if (ELEM_ROOT.equals(qName)) { 327 startElementOsmTagDefinitions(atts); 328 } else if (ELEM_TAG.equals(qName)) { 329 startElementTag(atts); 330 } else if (ELEM_LABEL.equals(qName)) { 331 startElementLabel(atts); 332 } else 333 throw new SAXException("unknown element '" + qName + "'"); 334 } 335 336 @Override 337 public void endElement(String namespaceURI, String localName, String qName) 338 throws SAXException { 339 if (ELEM_ROOT.equals(qName)) { 340 endElementOsmTagDefinitions(); 341 } else if (ELEM_TAG.equals(qName)) { 342 endElementTag(); 343 } else if (ELEM_LABEL.equals(qName)) { 344 endElementLabel(); 345 } else 346 throw new SAXException("unknown element '" + qName + "'"); 347 } 348 349 @Override 350 public void warning(SAXParseException e) throws SAXException { 351 // TODO Auto-generated method stub 352 logger.log(Level.WARNING, "XML parsing warning", e); 353 } 354 } 355 356 /** 357 * 358 * 359 */ 360 class ResourceEntityResolver implements EntityResolver { 361 362 public InputSource resolveEntity(String publicId, String systemId) 363 throws SAXException, IOException { 364 if (systemId != null && systemId.endsWith(DTD)) 365 return new InputSource( 366 TagSpecifications.class.getResourceAsStream(DTD) 367 ); 368 else 369 throw new SAXException("couldn't load external DTD '" + systemId + "'"); 370 } 371 372 } 373 374 static public void main(String args[]) throws Exception{ 375 TagSpecifications.loadFromResources(); 376 } 377 377 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/ITagSelectorListener.java
r20058 r23189 4 4 5 5 public interface ITagSelectorListener { 6 6 public void itemSelected(KeyValuePair pair); 7 7 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/KeyValueCellRenderer.java
r20058 r23189 12 12 public class KeyValueCellRenderer extends JLabel implements TableCellRenderer { 13 13 14 14 private static final Logger logger = Logger.getLogger(KeyValueCellRenderer.class.getName()); 15 15 16 17 18 19 16 protected void init() { 17 setFont(new Font("Courier",Font.PLAIN,getFont().getSize())); 18 setOpaque(true); 19 } 20 20 21 22 23 21 public KeyValueCellRenderer() { 22 init(); 23 } 24 24 25 26 25 public Component getTableCellRendererComponent(JTable table, Object value, 26 boolean isSelected, boolean hasFocus, int rowIndex, int colIndex) { 27 27 28 29 30 31 32 33 34 35 36 37 38 28 if (isSelected) { 29 setBackground(UIManager.getColor("Table.selectionBackground")); 30 setForeground(UIManager.getColor("Table.selectionForeground")); 31 } else { 32 setBackground(UIManager.getColor("Table.background")); 33 setForeground(UIManager.getColor("Table.foreground")); 34 } 35 setText((String)value); 36 setIcon(null); 37 return this; 38 } 39 39 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/TabularTagSelector.java
r20058 r23189 33 33 public class TabularTagSelector extends JPanel { 34 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 35 private TagsTable tagsTable; 36 private JTextField tfFilter; 37 private JButton btnApply; 38 private JScrollPane scrollPane; 39 private final ArrayList<ITagSelectorListener> listeners = new ArrayList<ITagSelectorListener>(); 40 41 protected JPanel buildFilterPanel() { 42 JPanel pnl = new JPanel(); 43 JLabel lbl = new JLabel(tr("Search: ")); 44 pnl.setLayout(new FlowLayout(FlowLayout.LEFT)); 45 tfFilter = new JTextField(20); 46 pnl.add(lbl); 47 pnl.add(tfFilter,BorderLayout.CENTER); 48 JButton btn = new JButton(tr("Filter")); 49 pnl.add(btn); 50 btn.addActionListener( 51 new ActionListener() { 52 public void actionPerformed(ActionEvent e) { 53 filter(tfFilter.getText()); 54 } 55 56 } 57 ); 58 btn = new JButton(tr("Clear")); 59 pnl.add(btn); 60 btn.addActionListener( 61 new ActionListener() { 62 public void actionPerformed(ActionEvent e) { 63 tfFilter.setText(""); 64 tfFilter.requestFocus(); 65 } 66 } 67 ); 68 return pnl; 69 } 70 71 protected JScrollPane buildPresetGrid() { 72 73 tagsTable = new TagsTable(new TagsTableModel(),new TagsTableColumnModel()); 74 getModel().initFromTagSpecifications(); 75 76 scrollPane = new JScrollPane(tagsTable); 77 78 scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 79 scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 80 81 // this adapters ensures that the width of the tag table columns is adjusted 82 // to the width of the scroll pane viewport. Also tried to overwrite 83 // getPreferredViewportSize() in JTable, but did not work. 84 // 85 scrollPane.addComponentListener( 86 new ComponentAdapter() { 87 @Override public void componentResized(ComponentEvent e) { 88 super.componentResized(e); 89 Dimension d = scrollPane.getViewport().getExtentSize(); 90 tagsTable.adjustColumnWidth(d.width); 91 } 92 } 93 ); 94 95 // add the double click listener 96 // 97 tagsTable.addMouseListener(new DoubleClickAdapter()); 98 99 // replace Enter action. apply the current preset on enter 100 // 101 tagsTable.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0)); 102 ActionListener enterAction = new ActionListener() { 103 public void actionPerformed(ActionEvent e) { 104 int rowNum = tagsTable.getSelectedRow(); 105 if (rowNum >= 0) { 106 KeyValuePair item = getModel().getVisibleItem(rowNum); 107 fireItemSelected(item); 108 } 109 } 110 }; 111 112 tagsTable.registerKeyboardAction( 113 enterAction, 114 "Enter", 115 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), 116 JComponent.WHEN_FOCUSED 117 ); 118 119 return scrollPane; 120 } 121 122 protected JPanel buildControlButtonPanel() { 123 JPanel pnl = new JPanel(); 124 pnl.setLayout(new FlowLayout(FlowLayout.LEFT)); 125 btnApply = new JButton("Apply"); 126 pnl.add(btnApply); 127 btnApply.addActionListener( 128 new ActionListener() { 129 public void actionPerformed(ActionEvent arg0) { 130 int row = tagsTable.getSelectedRow(); 131 if (row >=0) { 132 KeyValuePair item = getModel().getVisibleItem(row); 133 fireItemSelected(item); 134 } 135 } 136 } 137 ); 138 return pnl; 139 } 140 141 protected void build() { 142 setLayout(new BorderLayout()); 143 add(buildFilterPanel(), BorderLayout.NORTH); 144 add(buildPresetGrid(), BorderLayout.CENTER); 145 add(buildControlButtonPanel(), BorderLayout.SOUTH); 146 147 // wire the text field for filter expressions to the prests 148 // table 149 // 150 tfFilter.getDocument().addDocumentListener( 151 new DocumentListener() { 152 public void changedUpdate(DocumentEvent arg0) { 153 onUpdate(); 154 } 155 156 public void insertUpdate(DocumentEvent arg0) { 157 onUpdate(); 158 } 159 160 public void removeUpdate(DocumentEvent arg0) { 161 onUpdate(); 162 } 163 164 protected void onUpdate() { 165 filter(tfFilter.getText()); 166 } 167 } 168 ); 169 170 tfFilter.addActionListener( 171 new ActionListener() { 172 public void actionPerformed(ActionEvent e) { 173 filter(tfFilter.getText()); 174 } 175 } 176 ); 177 178 // wire the apply button to the selection model of the preset table 179 // 180 tagsTable.getSelectionModel().addListSelectionListener( 181 new ListSelectionListener() { 182 public void valueChanged(ListSelectionEvent e) { 183 btnApply.setEnabled(tagsTable.getSelectedRowCount() != 0); 184 } 185 } 186 ); 187 188 189 // load the set of presets and bind them to the preset table 190 // 191 tagsTable.getSelectionModel().clearSelection(); 192 btnApply.setEnabled(false); 193 194 } 195 196 public TabularTagSelector() { 197 build(); 198 } 199 200 201 public void filter(String filter) { 202 tagsTable.getSelectionModel().clearSelection(); 203 getModel().filter(filter); 204 205 tagsTable.scrollRectToVisible(tagsTable.getCellRect(0, 0, false)); 206 207 // we change the number of rows by applying a filter condition. Because 208 // the table is embedded in a JScrollPane which again may be embedded in 209 // other JScrollPanes or JSplitPanes it seems that we have to recalculate 210 // the layout and repaint the component tree. Maybe there is a more efficient way 211 // to keep the GUI in sync with the number of rows in table. By trial 212 // and error I ended up with the following lines. 213 // 214 Component c = tagsTable; 215 while(c != null) { 216 c.doLayout(); 217 c.repaint(); 218 c = c.getParent(); 219 } 220 } 221 222 protected TagsTableModel getModel() { 223 return (TagsTableModel)tagsTable.getModel(); 224 } 225 226 227 public void addTagSelectorListener(ITagSelectorListener listener) { 228 synchronized(this.listeners) { 229 if (listener != null && ! listeners.contains(listener)) { 230 listeners.add(listener); 231 } 232 } 233 } 234 235 public void removeTagSelectorListener(ITagSelectorListener listener) { 236 synchronized(this.listeners) { 237 if (listener != null) { 238 listeners.remove(listener); 239 } 240 } 241 } 242 243 protected void fireItemSelected(KeyValuePair pair) { 244 synchronized(this.listeners) { 245 for(ITagSelectorListener listener: listeners) { 246 listener.itemSelected(pair); 247 } 248 } 249 } 250 251 private class DoubleClickAdapter extends MouseAdapter { 252 @Override 253 public void mouseClicked(MouseEvent e) { 254 if (e.getClickCount() == 2) { 255 int rowNum = tagsTable.rowAtPoint(e.getPoint()); 256 KeyValuePair pair = getModel().getVisibleItem(rowNum); 257 fireItemSelected(pair); 258 } 259 } 260 } 261 261 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/TagsTable.java
r14330 r23189 7 7 8 8 public class TagsTable extends JTable { 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 9 /** 10 * initialize the table 11 */ 12 protected void init() { 13 setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 14 setRowSelectionAllowed(true); 15 setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 16 } 17 18 public TagsTable(TableModel model, TableColumnModel columnModel) { 19 super(model,columnModel); 20 init(); 21 } 22 23 /** 24 * adjusts the width of the columns for the tag name and the tag value 25 * to the width of the scroll panes viewport. 26 * 27 * Note: {@see #getPreferredScrollableViewportSize()} did not work as expected 28 * 29 * @param scrollPaneWidth the width of the scroll panes viewport 30 */ 31 public void adjustColumnWidth(int scrollPaneWidth) { 32 TableColumnModel tcm = getColumnModel(); 33 int width = scrollPaneWidth; 34 width = width / 2; 35 if (width > 0) { 36 tcm.getColumn(0).setMinWidth(width); 37 tcm.getColumn(0).setMaxWidth(width); 38 tcm.getColumn(1).setMinWidth(width); 39 tcm.getColumn(1).setMaxWidth(width); 40 } 41 } 42 42 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/TagsTableColumnModel.java
r14330 r23189 8 8 9 9 public class TagsTableColumnModel extends DefaultTableColumnModel { 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 10 11 protected void createColumns() { 12 TableCellRenderer renderer = new KeyValueCellRenderer(); 13 14 TableColumn col = null; 15 16 // column 0 - Key 17 col = new TableColumn(0); 18 col.setHeaderValue(tr("Key")); 19 col.setResizable(true); 20 col.setCellRenderer(renderer); 21 addColumn(col); 22 23 // column 1 - Value 24 col = new TableColumn(1); 25 col.setHeaderValue(tr("Value")); 26 col.setResizable(true); 27 col.setCellRenderer(renderer); 28 addColumn(col); 29 } 30 30 31 32 33 31 public TagsTableColumnModel() { 32 createColumns(); 33 } 34 34 } -
applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/tagspec/ui/TagsTableModel.java
r20058 r23189 15 15 public class TagsTableModel extends AbstractTableModel { 16 16 17 17 static private Logger logger = Logger.getLogger(TagsTableModel.class.getName()); 18 18 19 20 19 private ArrayList<KeyValuePair> items = null; 20 private ArrayList<KeyValuePair> visibleItems = null; 21 21 22 23 24 25 22 public TagsTableModel() { 23 items = new ArrayList<KeyValuePair>(); 24 visibleItems = new ArrayList<KeyValuePair>(); 25 } 26 26 27 28 29 30 31 32 33 27 protected void sort() { 28 Collections.sort( 29 items, 30 new Comparator<KeyValuePair>() { 31 public int compare(KeyValuePair self, 32 KeyValuePair other) { 33 int ret =self.getKey().compareToIgnoreCase(other.getKey()); 34 34 35 36 37 38 39 40 41 42 35 if (ret == 0) 36 return self.getValue().compareToIgnoreCase(other.getValue()); 37 else 38 return ret; 39 } 40 } 41 ); 42 } 43 43 44 45 46 47 44 protected void clear() { 45 items.clear(); 46 visibleItems.clear(); 47 } 48 48 49 50 51 49 public void initFromTagSpecifications() { 50 clear(); 51 TagSpecifications spec; 52 52 53 54 55 56 57 58 53 try { 54 spec = TagSpecifications.getInstance(); 55 } catch(Exception e) { 56 logger.log(Level.SEVERE, "failed to init TagTableModel. Exception:" + e); 57 return; 58 } 59 59 60 61 62 63 64 65 60 items = spec.asList(); 61 sort(); 62 for(KeyValuePair item : items) { 63 visibleItems.add(item); 64 } 65 } 66 66 67 68 69 67 public int getColumnCount() { 68 return 2; 69 } 70 70 71 72 73 71 public int getRowCount() { 72 return visibleItems.size(); 73 } 74 74 75 76 77 78 79 80 81 82 83 84 75 public Object getValueAt(int row, int col) { 76 KeyValuePair pair = visibleItems.get(row); 77 switch(col) { 78 case 0: return pair.getKey(); 79 case 1: return pair.getValue(); 80 default: 81 /* should not happen */ 82 throw new IllegalArgumentException(tr("unexpected column number {0}",col)); 83 } 84 } 85 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 86 public void filter(String filter) { 87 synchronized(this) { 88 if (filter == null || filter.trim().equals("")) { 89 visibleItems.clear(); 90 for(KeyValuePair pair: items) { 91 visibleItems.add(pair); 92 } 93 } else { 94 visibleItems.clear(); 95 filter = filter.toLowerCase(); 96 for(KeyValuePair pair: items) { 97 if (pair.getKey().toLowerCase().trim().startsWith(filter) 98 || pair.getValue().toLowerCase().trim().startsWith(filter)) { 99 visibleItems.add(pair); 100 } 101 } 102 } 103 fireTableDataChanged(); 104 fireTableStructureChanged(); 105 } 106 } 107 107 108 109 110 111 108 @Override 109 public boolean isCellEditable(int rowIndex, int columnIndex) { 110 return false; 111 } 112 112 113 114 115 116 117 113 public KeyValuePair getVisibleItem(int row) { 114 if (row < 0 || row >= visibleItems.size()) 115 throw new IndexOutOfBoundsException("row is out of bound: row=" + row); 116 return visibleItems.get(row); 117 } 118 118 } -
applications/editors/josm/plugins/tagging-preset-tester/src/org/openstreetmap/josm/plugins/taggingpresettester/TaggingPresetTester.java
r21797 r23189 55 55 panel.repaint(); 56 56 } 57 57 58 58 public TaggingPresetTester(String[] args) { 59 59 super(tr("Tagging Preset Tester")); -
applications/editors/josm/plugins/undelete/src/org/openstreetmap/josm/plugins/undelete/Undelete.java
r22291 r23189 50 50 51 51 public Undelete(PluginInformation info) { 52 52 super(info); 53 53 Undelete = MainMenu.add(Main.main.menu.fileMenu, new UndeleteAction()); 54 54 55 55 } 56 57 56 57 58 58 private class UndeleteAction extends JosmAction { 59 59 /** 60 * 61 62 63 60 * 61 */ 62 private static final long serialVersionUID = 1L; 63 public UndeleteAction() { 64 64 super(tr("Undelete object..."), "undelete", tr("Undelete object by id"), Shortcut.registerShortcut("tools:undelete", tr("File: {0}", tr("Undelete object...")), 65 65 KeyEvent.VK_U, Shortcut.GROUP_EDIT, KeyEvent.SHIFT_DOWN_MASK|KeyEvent.ALT_DOWN_MASK), true); … … 117 117 undelete(layer.isSelected(), cbType.getType(), ids, 0); 118 118 } 119 } 120 119 } 120 121 121 /** 122 122 * Download the given primitive. … … 128 128 Main.main.addLayer(tmpLayer); 129 129 } 130 130 131 131 final DataSet datas = tmpLayer.data; 132 132 final OsmDataLayer layer=tmpLayer; 133 133 134 134 HistoryLoadTask task = new HistoryLoadTask(); 135 135 for (long id: ids) … … 138 138 } 139 139 140 141 140 141 142 142 Main.worker.execute(task); 143 143 144 144 Runnable r = new Runnable() { 145 145 public void run() { … … 149 149 150 150 History h = HistoryDataSet.getInstance().getHistory(id, type); 151 151 152 152 OsmPrimitive primitive; 153 153 HistoryOsmPrimitive hPrimitive1=h.getLatest(); 154 154 HistoryOsmPrimitive hPrimitive2; 155 155 156 156 boolean visible=hPrimitive1.isVisible(); 157 157 158 158 if (visible) 159 159 { 160 160 // If the object is not deleted we get the real object 161 161 DownloadPrimitiveTask download=new DownloadPrimitiveTask(new SimplePrimitiveId(id, type), layer); 162 System.out.println(tr("Will get {0}", id)); 162 System.out.println(tr("Will get {0}", id)); 163 163 download.run(); 164 165 166 System.out.println(tr("Looking for {0}", id)); 164 165 166 System.out.println(tr("Looking for {0}", id)); 167 167 primitive=datas.getPrimitiveById(id, type); 168 168 System.out.println(tr("Found {0}", primitive.getId())); … … 178 178 // We get all info from the latest version 179 179 hPrimitive2=hPrimitive1; 180 180 181 181 Node node = new Node(id, (int) hPrimitive1.getVersion()); 182 182 183 183 HistoryNode hNode = (HistoryNode) hPrimitive1; 184 184 node.setCoor(hNode.getCoords()); 185 185 186 186 primitive=node; 187 187 if (parent>0) … … 196 196 hPrimitive2 = h.getByVersion(h.getNumVersions()-1); 197 197 198 199 198 199 200 200 Way way = new Way(id, (int) hPrimitive1.getVersion()); 201 201 202 202 HistoryWay hWay = (HistoryWay) hPrimitive2; 203 203 //System.out.println(tr("Primitive {0} version {1}: {2} nodes", hPrimitive2.getId(), hPrimitive2.getVersion(), hWay.getNumNodes())); 204 204 List<Long> nodeIds = hWay.getNodes(); 205 205 undelete(false, OsmPrimitiveType.NODE, nodeIds, id); 206 206 207 207 primitive=way; 208 208 209 209 } 210 210 else 211 { 211 { 212 212 primitive=new Node(); 213 213 hPrimitive1=h.getLatest(); … … 216 216 217 217 User user = User.createOsmUser(hPrimitive1.getUid(), hPrimitive1.getUser()); 218 218 219 219 primitive.setUser(user); 220 220 221 221 primitive.setKeys(hPrimitive2.getTags()); 222 222 223 223 primitive.put("history", "retrieved using undelete JOSM plugin"); 224 224 225 225 primitive.setModified(true); 226 227 datas.addPrimitive(primitive); 226 227 datas.addPrimitive(primitive); 228 228 } 229 229 230 230 231 231 //HistoryBrowserDialogManager.getInstance().show(h); … … 234 234 { 235 235 Way parentWay=(Way)datas.getPrimitiveById(parent, OsmPrimitiveType.WAY); 236 236 237 237 parentWay.setNodes(nodes); 238 238 } … … 240 240 }; 241 241 Main.worker.submit(r); 242 242 243 243 //if (downloadReferrers) { 244 244 // Main.worker.submit(new DownloadReferrersTask(layer, id, type)); 245 245 //} 246 } 246 } 247 247 } -
applications/editors/josm/plugins/wayselector/src/org/openstreetmap/josm/plugins/wayselector/WaySelectorPlugin.java
r20482 r23189 50 50 51 51 public void actionPerformed(ActionEvent ev) { 52 53 54 52 DataSet ds = Main.main.getCurrentDataSet(); 53 WaySelection ws = new WaySelection(ds.getSelectedWays()); 54 ws.extend(ds); 55 55 } 56 56
Note:
See TracChangeset
for help on using the changeset viewer.