Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java
r6336 r6564 10 10 import java.util.Collection; 11 11 import java.util.HashMap; 12 import java.util.HashSet; 12 13 import java.util.List; 13 14 import java.util.Map; … … 33 34 import org.openstreetmap.josm.gui.Notification; 34 35 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor; 36 import org.openstreetmap.josm.tools.Pair; 35 37 import org.openstreetmap.josm.tools.Shortcut; 38 import org.openstreetmap.josm.tools.Utils; 36 39 37 40 /** … … 56 59 */ 57 60 public CreateMultipolygonAction() { 58 super(tr("Create multipolygon"), "multipoly_create", tr("Create multipolygon ."),61 super(tr("Create multipolygon"), "multipoly_create", tr("Create multipolygon"), 59 62 Shortcut.registerShortcut("tools:multipoly", tr("Tool: {0}", tr("Create multipolygon")), 60 63 KeyEvent.VK_A, Shortcut.ALT_CTRL), true); … … 76 79 } 77 80 78 Collection<Way> selectedWays = Main.main.getCurrentDataSet().getSelectedWays(); 81 final Collection<Way> selectedWays = Main.main.getCurrentDataSet().getSelectedWays(); 82 final Collection<Relation> selectedRelations = Main.main.getCurrentDataSet().getSelectedRelations(); 79 83 80 84 if (selectedWays.size() < 1) { … … 89 93 } 90 94 91 MultipolygonCreate polygon = this.analyzeWays(selectedWays); 92 93 if (polygon == null) 94 return; //could not make multipolygon. 95 96 final Relation relation = this.createRelation(polygon); 97 98 if (Main.pref.getBoolean("multipoly.show-relation-editor", false)) { 99 //Open relation edit window, if set up in preferences 100 RelationEditor editor = RelationEditor.getEditor(Main.main.getEditLayer(), relation, null); 101 102 editor.setModal(true); 103 editor.setVisible(true); 104 105 //TODO: cannot get the resulting relation from RelationEditor :(. 106 /* 107 if (relationCountBefore < relationCountAfter) { 108 //relation saved, clean up the tags 109 List<Command> list = this.removeTagsFromInnerWays(relation); 110 if (list.size() > 0) 111 { 112 Main.main.undoRedo.add(new SequenceCommand(tr("Remove tags from multipolygon inner ways"), list)); 113 } 114 } 115 */ 116 95 final Pair<SequenceCommand, Relation> commandAndRelation = createMultipolygonCommand(selectedWays, selectedRelations); 96 final Command command = commandAndRelation.a; 97 final Relation relation = commandAndRelation.b; 98 if (command == null) { 99 return; 100 } 101 Main.main.undoRedo.add(command); 102 103 // Use 'SwingUtilities.invokeLater' to make sure the relationListDialog 104 // knows about the new relation before we try to select it. 105 // (Yes, we are already in event dispatch thread. But DatasetEventManager 106 // uses 'SwingUtilities.invokeLater' to fire events so we have to do 107 // the same.) 108 SwingUtilities.invokeLater(new Runnable() { 109 @Override 110 public void run() { 111 Main.map.relationListDialog.selectRelation(relation); 112 if (Main.pref.getBoolean("multipoly.show-relation-editor", false)) { 113 //Open relation edit window, if set up in preferences 114 RelationEditor editor = RelationEditor.getEditor(Main.main.getEditLayer(), relation, null); 115 116 editor.setModal(true); 117 editor.setVisible(true); 118 } 119 } 120 }); 121 122 } 123 124 private static Relation getSelectedMultipolygonRelation(Collection<Relation> selectedRelations) { 125 return selectedRelations.size() == 1 && "multipolygon".equals(selectedRelations.iterator().next().get("type")) 126 ? selectedRelations.iterator().next() 127 : null; 128 } 129 130 /** 131 * Returns a {@link Pair} of the old multipolygon {@link Relation} (or null) and the newly created/modified multipolygon {@link Relation}. 132 */ 133 public static Pair<Relation, Relation> createMultipolygonRelation(Collection<Way> selectedWays, Collection<Relation> selectedRelations) { 134 135 final Relation selectedMultipolygonRelation = getSelectedMultipolygonRelation(selectedRelations); 136 if (selectedMultipolygonRelation != null) { 137 // add ways of existing relation to include them in polygon analysis 138 selectedWays = new HashSet<Way>(selectedWays); 139 selectedWays.addAll(Utils.filteredCollection(selectedMultipolygonRelation.getMemberPrimitives(), Way.class)); 140 } 141 142 final MultipolygonCreate polygon = analyzeWays(selectedWays); 143 if (polygon == null) { 144 return null; //could not make multipolygon. 145 } 146 147 if (selectedMultipolygonRelation != null) { 148 return Pair.create(selectedMultipolygonRelation, createRelation(polygon, new Relation(selectedMultipolygonRelation))); 117 149 } else { 118 //Just add the relation 119 List<Command> list = this.removeTagsFromWaysIfNeeded(relation); 150 return Pair.create(null, createRelation(polygon, new Relation())); 151 } 152 } 153 154 /** 155 * Returns a pair of a multipolygon creating/modifying {@link Command} as well as the multipolygon {@link Relation}. 156 */ 157 public static Pair<SequenceCommand, Relation> createMultipolygonCommand(Collection<Way> selectedWays, Collection<Relation> selectedRelations) { 158 159 final Pair<Relation, Relation> rr = createMultipolygonRelation(selectedWays, selectedRelations); 160 if (rr == null) { 161 return null; 162 } 163 final Relation existingRelation = rr.a; 164 final Relation relation = rr.b; 165 166 final List<Command> list = removeTagsFromWaysIfNeeded(relation); 167 final String commandName; 168 if (existingRelation == null) { 120 169 list.add(new AddCommand(relation)); 121 Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list)); 122 // Use 'SwingUtilities.invokeLater' to make sure the relationListDialog 123 // knows about the new relation before we try to select it. 124 // (Yes, we are already in event dispatch thread. But DatasetEventManager 125 // uses 'SwingUtilities.invokeLater' to fire events so we have to do 126 // the same.) 127 SwingUtilities.invokeLater(new Runnable() { 128 @Override 129 public void run() { 130 Main.map.relationListDialog.selectRelation(relation); 131 } 132 }); 133 } 134 135 170 commandName = tr("Create multipolygon"); 171 } else { 172 list.add(new ChangeCommand(existingRelation, relation)); 173 commandName = tr("Update multipolygon"); 174 } 175 return Pair.create(new SequenceCommand(commandName, list), relation); 136 176 } 137 177 … … 152 192 @Override protected void updateEnabledState(Collection < ? extends OsmPrimitive > selection) { 153 193 setEnabled(selection != null && !selection.isEmpty()); 194 putValue(NAME, getSelectedMultipolygonRelation(getCurrentDataSet().getSelectedRelations()) != null 195 ? tr("Update multipolygon") 196 : tr("Create multipolygon") 197 ); 154 198 } 155 199 … … 159 203 * @return <code>null</code>, if there was a problem with the ways. 160 204 */ 161 private MultipolygonCreate analyzeWays(Collection < Way > selectedWays) {205 private static MultipolygonCreate analyzeWays(Collection < Way > selectedWays) { 162 206 163 207 MultipolygonCreate pol = new MultipolygonCreate(); … … 179 223 * @return multipolygon relation 180 224 */ 181 private Relation createRelation(MultipolygonCreate pol) {225 private static Relation createRelation(MultipolygonCreate pol, final Relation rel) { 182 226 // Create new relation 183 Relation rel = new Relation();184 227 rel.put("type", "multipolygon"); 185 228 // Add ways to it 186 229 for (JoinedPolygon jway:pol.outerWays) { 187 for (Way way:jway.ways) { 188 rel.addMember(new RelationMember("outer", way)); 189 } 230 addMembers(jway, rel, "outer"); 190 231 } 191 232 192 233 for (JoinedPolygon jway:pol.innerWays) { 193 for (Way way:jway.ways) { 194 rel.addMember(new RelationMember("inner", way)); 195 } 234 addMembers(jway, rel, "inner"); 196 235 } 197 236 return rel; 237 } 238 239 private static void addMembers(JoinedPolygon polygon, Relation rel, String role) { 240 final int count = rel.getMembersCount(); 241 final HashSet<Way> ways = new HashSet<Way>(polygon.ways); 242 for (int i = 0; i < count; i++) { 243 final RelationMember m = rel.getMember(i); 244 if (ways.contains(m.getMember()) && !role.equals(m.getRole())) { 245 rel.setMember(i, new RelationMember(role, m.getMember())); 246 } 247 } 248 ways.removeAll(rel.getMemberPrimitives()); 249 for (final Way way : ways) { 250 rel.addMember(new RelationMember(role, way)); 251 } 198 252 } 199 253 … … 206 260 * @return a list of commands to execute 207 261 */ 208 private List<Command> removeTagsFromWaysIfNeeded( Relation relation ) {262 private static List<Command> removeTagsFromWaysIfNeeded( Relation relation ) { 209 263 Map<String, String> values = new HashMap<String, String>(); 210 264 -
trunk/src/org/openstreetmap/josm/data/osm/Relation.java
r6491 r6564 5 5 import java.util.Arrays; 6 6 import java.util.Collection; 7 import java.util.Collections; 7 8 import java.util.HashSet; 8 9 import java.util.List; … … 14 15 import org.openstreetmap.josm.data.osm.visitor.Visitor; 15 16 import org.openstreetmap.josm.tools.CopyList; 17 import org.openstreetmap.josm.tools.Predicate; 16 18 import org.openstreetmap.josm.tools.Utils; 17 19 … … 319 321 */ 320 322 public void removeMembersFor(OsmPrimitive primitive) { 321 if (primitive == null) 322 return; 323 324 boolean locked = writeLock(); 325 try { 326 List<RelationMember> todelete = new ArrayList<RelationMember>(); 327 for (RelationMember member: members) { 328 if (member.getMember() == primitive) { 329 todelete.add(member); 330 } 331 } 332 List<RelationMember> members = getMembers(); 333 members.removeAll(todelete); 334 setMembers(members); 335 } finally { 336 writeUnlock(locked); 337 } 323 removeMembersFor(Collections.singleton(primitive)); 338 324 } 339 325 … … 356 342 357 343 /** 344 * Obtains all members with member.member == primitive 345 * @param primitives the primitives to check for 346 */ 347 public Collection<RelationMember> getMembersFor(final Collection<? extends OsmPrimitive> primitives) { 348 return Utils.filter(getMembers(), new Predicate<RelationMember>() { 349 @Override 350 public boolean evaluate(RelationMember member) { 351 return primitives.contains(member.getMember()); 352 } 353 }); 354 } 355 356 /** 358 357 * removes all members with member.member == primitive 359 358 * … … 367 366 boolean locked = writeLock(); 368 367 try { 369 List<RelationMember> todelete = new ArrayList<RelationMember>();370 for (RelationMember member: members) {371 if (primitives.contains(member.getMember())) {372 todelete.add(member);373 }374 }375 368 List<RelationMember> members = getMembers(); 376 members.removeAll( todelete);369 members.removeAll(getMembersFor(primitives)); 377 370 setMembers(members); 378 371 } finally {
Note:
See TracChangeset
for help on using the changeset viewer.