001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.command; 003 004import static org.openstreetmap.josm.tools.I18n.marktr; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.util.Collection; 008import java.util.Collections; 009import java.util.Objects; 010 011import javax.swing.Icon; 012 013import org.openstreetmap.josm.data.osm.DataSet; 014import org.openstreetmap.josm.data.osm.OsmPrimitive; 015import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 016import org.openstreetmap.josm.data.osm.Way; 017import org.openstreetmap.josm.gui.DefaultNameFormatter; 018import org.openstreetmap.josm.gui.layer.OsmDataLayer; 019import org.openstreetmap.josm.tools.ImageProvider; 020 021/** 022 * A command that adds an osm primitive to a dataset. Keys cannot be added this way. 023 * 024 * See {@link ChangeCommand} for comments on relation back references. 025 * 026 * @author imi 027 */ 028public class AddCommand extends Command { 029 030 /** 031 * The primitive to add to the dataset. 032 */ 033 private final OsmPrimitive osm; 034 035 /** 036 * Creates the command and specify the element to add in the context of the current edit layer, if any. 037 * @param osm The primitive to add 038 */ 039 public AddCommand(OsmPrimitive osm) { 040 this.osm = Objects.requireNonNull(osm, "osm"); 041 } 042 043 /** 044 * Creates the command and specify the element to add in the context of the given data layer. 045 * @param layer The data layer. Must not be {@code null} 046 * @param osm The primitive to add 047 */ 048 public AddCommand(OsmDataLayer layer, OsmPrimitive osm) { 049 super(layer); 050 this.osm = Objects.requireNonNull(osm, "osm"); 051 } 052 053 /** 054 * Creates the command and specify the element to add in the context of the given data set. 055 * @param data The data set. Must not be {@code null} 056 * @param osm The primitive to add 057 * @since 11240 058 */ 059 public AddCommand(DataSet data, OsmPrimitive osm) { 060 super(data); 061 this.osm = Objects.requireNonNull(osm, "osm"); 062 } 063 064 protected static final void checkNodeStyles(OsmPrimitive osm) { 065 if (osm instanceof Way) { 066 // Fix #10557 - node icon not updated after undoing/redoing addition of a way 067 ((Way) osm).clearCachedNodeStyles(); 068 } 069 } 070 071 @Override 072 public boolean executeCommand() { 073 getAffectedDataSet().addPrimitive(osm); 074 osm.setModified(true); 075 checkNodeStyles(osm); 076 return true; 077 } 078 079 @Override 080 public void undoCommand() { 081 getAffectedDataSet().removePrimitive(osm); 082 checkNodeStyles(osm); 083 } 084 085 @Override 086 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { 087 added.add(osm); 088 } 089 090 @Override 091 public String getDescriptionText() { 092 String msg; 093 switch(OsmPrimitiveType.from(osm)) { 094 case NODE: msg = marktr("Add node {0}"); break; 095 case WAY: msg = marktr("Add way {0}"); break; 096 case RELATION: msg = marktr("Add relation {0}"); break; 097 default: /* should not happen */msg = ""; break; 098 } 099 return tr(msg, osm.getDisplayName(DefaultNameFormatter.getInstance())); 100 } 101 102 @Override 103 public Icon getDescriptionIcon() { 104 return ImageProvider.get(osm.getDisplayType()); 105 } 106 107 @Override 108 public Collection<OsmPrimitive> getParticipatingPrimitives() { 109 return Collections.singleton(osm); 110 } 111 112 @Override 113 public int hashCode() { 114 return Objects.hash(super.hashCode(), osm); 115 } 116 117 @Override 118 public boolean equals(Object obj) { 119 if (this == obj) return true; 120 if (obj == null || getClass() != obj.getClass()) return false; 121 if (!super.equals(obj)) return false; 122 AddCommand that = (AddCommand) obj; 123 return Objects.equals(osm, that.osm); 124 } 125}