- Timestamp:
- 2016-07-23T14:54:19+02:00 (8 years ago)
- Location:
- trunk
- Files:
-
- 15 added
- 41 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/Main.java
r10601 r10604 84 84 import org.openstreetmap.josm.gui.MapFrame; 85 85 import org.openstreetmap.josm.gui.MapFrameListener; 86 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 86 87 import org.openstreetmap.josm.gui.help.HelpUtil; 87 88 import org.openstreetmap.josm.gui.io.SaveLayersDialog; … … 178 179 /** 179 180 * The global paste buffer. 180 */ 181 * @deprecated Use swing CCP instead. See {@link OsmTransferHandler} 182 */ 183 @Deprecated 181 184 public static final PrimitiveDeepCopy pasteBuffer = new PrimitiveDeepCopy(); 182 185 183 186 /** 184 187 * The layer source from which {@link Main#pasteBuffer} data comes from. 185 */ 188 * @deprecated During a copy operation, the layer should be added. See {@link OsmLayerTransferData}. 189 */ 190 @Deprecated 186 191 public static Layer pasteSource; 187 192 -
trunk/src/org/openstreetmap/josm/actions/CopyAction.java
r10448 r10604 9 9 import java.awt.event.KeyEvent; 10 10 import java.util.Collection; 11 import java.util.Collections; 11 12 12 13 import javax.swing.JOptionPane; 13 14 14 15 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.data.osm.DataSet; 15 17 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 17 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 18 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 19 import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable; 20 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 18 21 import org.openstreetmap.josm.tools.Shortcut; 19 import org.openstreetmap.josm.tools.Utils;20 22 21 23 /** … … 23 25 * @since 404 24 26 */ 25 public final class CopyAction extends JosmAction { 26 27 /** regular expression that matches text clipboard contents after copying */ 28 public static final String CLIPBOARD_REGEXP = "((node|way|relation)\\s\\d+,)*(node|way|relation)\\s\\d+"; 29 27 public class CopyAction extends JosmAction { 30 28 /** 31 29 * Constructs a new {@code CopyAction}. … … 43 41 @Override 44 42 public void actionPerformed(ActionEvent e) { 45 if (isEmptySelection()) return; 46 Collection<OsmPrimitive> selection = getLayerManager().getEditDataSet().getSelected(); 43 DataSet set = getLayerManager().getEditDataSet(); 44 Collection<OsmPrimitive> selection = set == null ? Collections.<OsmPrimitive>emptySet() : set.getSelected(); 45 if (selection.isEmpty()) { 46 showEmptySelectionWarning(); 47 return; 48 } 47 49 48 copy( getLayerManager().getEditLayer(),selection);50 copy(selection); 49 51 } 50 52 … … 52 54 * Copies the given primitive ids to the clipboard. The output by this function 53 55 * looks similar to: node 1089302677,node 1089303458,way 93793372 54 * @param source The OSM data layer source55 56 * @param primitives The OSM primitives to copy 56 57 */ 57 public static void copy( OsmDataLayer source,Collection<OsmPrimitive> primitives) {58 public static void copy(Collection<OsmPrimitive> primitives) { 58 59 // copy ids to the clipboard 59 String ids = getCopyString(primitives); 60 Utils.copyToClipboard(ids); 61 62 Main.pasteBuffer.makeCopy(primitives); 63 Main.pasteSource = source; 64 } 65 66 static String getCopyString(Collection<? extends OsmPrimitive> primitives) { 67 StringBuilder idsBuilder = new StringBuilder(); 68 for (OsmPrimitive p : primitives) { 69 idsBuilder.append(OsmPrimitiveType.from(p).getAPIName()).append(' ').append(p.getId()).append(','); 70 } 71 return idsBuilder.substring(0, idsBuilder.length() - 1); 60 ClipboardUtils.copy(new PrimitiveTransferable(PrimitiveTransferData.getDataWithReferences(primitives))); 72 61 } 73 62 … … 82 71 } 83 72 84 private boolean isEmptySelection() { 85 Collection<OsmPrimitive> sel = getLayerManager().getEditDataSet().getSelected(); 86 if (sel.isEmpty()) { 87 JOptionPane.showMessageDialog( 88 Main.parent, 89 tr("Please select something to copy."), 90 tr("Information"), 91 JOptionPane.INFORMATION_MESSAGE 92 ); 93 return true; 94 } 95 return false; 73 protected void showEmptySelectionWarning() { 74 JOptionPane.showMessageDialog( 75 Main.parent, 76 tr("Please select something to copy."), 77 tr("Information"), 78 JOptionPane.INFORMATION_MESSAGE 79 ); 96 80 } 97 81 } -
trunk/src/org/openstreetmap/josm/actions/CopyCoordinatesAction.java
r10448 r10604 12 12 import org.openstreetmap.josm.data.osm.Node; 13 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; 14 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 14 15 import org.openstreetmap.josm.tools.Shortcut; 15 16 import org.openstreetmap.josm.tools.Utils; … … 35 36 s.append('\n'); 36 37 } 37 Utils.copyToClipboard(s.toString().trim());38 ClipboardUtils.copyString(s.toString().trim()); 38 39 } 39 40 -
trunk/src/org/openstreetmap/josm/actions/DuplicateAction.java
r10409 r10604 12 12 import org.openstreetmap.josm.Main; 13 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; 14 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 14 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 15 import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable; 16 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 15 17 import org.openstreetmap.josm.tools.Shortcut; 16 18 19 /** 20 * An action that dupplicates the given nodes. They are not added to the clipboard. 21 */ 17 22 public final class DuplicateAction extends JosmAction { 18 23 … … 22 27 public DuplicateAction() { 23 28 super(tr("Duplicate"), "duplicate", 24 tr("Duplicate selection by copy and immediate paste."),29 tr("Duplicate selection."), 25 30 Shortcut.registerShortcut("system:duplicate", tr("Edit: {0}", tr("Duplicate")), KeyEvent.VK_D, Shortcut.CTRL), true); 26 31 putValue("help", ht("/Action/Duplicate")); … … 29 34 @Override 30 35 public void actionPerformed(ActionEvent e) { 31 Main.main.menu.paste.pasteData(32 new PrimitiveDeepCopy(getLayerManager().getEditDataSet().getSelected()), getLayerManager().getEditLayer(), e);36 PrimitiveTransferData data = PrimitiveTransferData.getDataWithReferences(getLayerManager().getEditDataSet().getSelected()); 37 new OsmTransferHandler().pasteOn(Main.getLayerManager().getEditLayer(), data.getCenter(), new PrimitiveTransferable(data)); 33 38 } 34 39 -
trunk/src/org/openstreetmap/josm/actions/MapRectifierWMSmenuAction.java
r10463 r10604 23 23 import org.openstreetmap.josm.data.imagery.ImageryInfo; 24 24 import org.openstreetmap.josm.gui.ExtendedDialog; 25 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 25 26 import org.openstreetmap.josm.gui.layer.WMSLayer; 26 27 import org.openstreetmap.josm.gui.widgets.JosmTextField; … … 28 29 import org.openstreetmap.josm.tools.GBC; 29 30 import org.openstreetmap.josm.tools.Shortcut; 30 import org.openstreetmap.josm.tools.Utils;31 31 32 32 /** … … 124 124 JosmTextField tfWmsUrl = new JosmTextField(30); 125 125 126 String clip = Utils.getClipboardContent();126 String clip = ClipboardUtils.getClipboardStringContent(); 127 127 clip = clip == null ? "" : clip.trim(); 128 128 ButtonGroup group = new ButtonGroup(); -
trunk/src/org/openstreetmap/josm/actions/PasteAction.java
r10413 r10604 8 8 import java.awt.MouseInfo; 9 9 import java.awt.Point; 10 import java.awt.datatransfer.FlavorEvent; 11 import java.awt.datatransfer.FlavorListener; 10 12 import java.awt.event.ActionEvent; 11 13 import java.awt.event.KeyEvent; 12 import java.util.ArrayList;13 import java.util.HashMap;14 import java.util.List;15 import java.util.Map;16 14 17 15 import org.openstreetmap.josm.Main; 18 import org.openstreetmap.josm.command.AddPrimitivesCommand;19 16 import org.openstreetmap.josm.data.coor.EastNorth; 20 import org.openstreetmap.josm.data.osm.NodeData; 21 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 22 import org.openstreetmap.josm.data.osm.PrimitiveData; 23 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 24 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy.PasteBufferChangedListener; 25 import org.openstreetmap.josm.data.osm.RelationData; 26 import org.openstreetmap.josm.data.osm.RelationMemberData; 27 import org.openstreetmap.josm.data.osm.WayData; 28 import org.openstreetmap.josm.gui.ExtendedDialog; 29 import org.openstreetmap.josm.gui.layer.Layer; 17 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 18 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 30 19 import org.openstreetmap.josm.tools.Shortcut; 31 20 … … 34 23 * @since 404 35 24 */ 36 public final class PasteAction extends JosmAction implements PasteBufferChangedListener { 25 public final class PasteAction extends JosmAction implements FlavorListener { 26 27 private final OsmTransferHandler transferHandler; 37 28 38 29 /** … … 46 37 Main.registerActionShortcut(this, 47 38 Shortcut.registerShortcut("system:paste:cua", tr("Edit: {0}", tr("Paste")), KeyEvent.VK_INSERT, Shortcut.SHIFT)); 48 Main.pasteBuffer.addPasteBufferChangedListener(this); 39 transferHandler = new OsmTransferHandler(); 40 ClipboardUtils.getClipboard().addFlavorListener(this); 49 41 } 50 42 51 43 @Override 52 44 public void actionPerformed(ActionEvent e) { 53 if (!isEnabled())54 return;55 pasteData(Main.pasteBuffer, Main.pasteSource, e);56 }57 58 /**59 * Paste OSM primitives from the given paste buffer and OSM data layer source to the current edit layer.60 * @param pasteBuffer The paste buffer containing primitive ids to copy61 * @param source The OSM data layer used to look for primitive ids62 * @param e The ActionEvent that triggered this operation63 */64 public void pasteData(PrimitiveDeepCopy pasteBuffer, Layer source, ActionEvent e) {65 /* Find the middle of the pasteBuffer area */66 double maxEast = -1E100;67 double minEast = 1E100;68 double maxNorth = -1E100;69 double minNorth = 1E100;70 boolean incomplete = false;71 for (PrimitiveData data : pasteBuffer.getAll()) {72 if (data instanceof NodeData) {73 NodeData n = (NodeData) data;74 if (n.getEastNorth() != null) {75 double east = n.getEastNorth().east();76 double north = n.getEastNorth().north();77 if (east > maxEast) {78 maxEast = east;79 }80 if (east < minEast) {81 minEast = east;82 }83 if (north > maxNorth) {84 maxNorth = north;85 }86 if (north < minNorth) {87 minNorth = north;88 }89 }90 }91 if (data.isIncomplete()) {92 incomplete = true;93 }94 }95 96 // Allow to cancel paste if there are incomplete primitives97 if (incomplete && !confirmDeleteIncomplete()) {98 return;99 }100 101 45 // default to paste in center of map (pasted via menu or cursor not in MapView) 102 46 EastNorth mPosition = Main.map.mapView.getCenter(); … … 113 57 } 114 58 115 double offsetEast = mPosition.east() - (maxEast + minEast)/2.0; 116 double offsetNorth = mPosition.north() - (maxNorth + minNorth)/2.0; 117 118 // Make a copy of pasteBuffer and map from old id to copied data id 119 List<PrimitiveData> bufferCopy = new ArrayList<>(); 120 List<PrimitiveData> toSelect = new ArrayList<>(); 121 Map<Long, Long> newNodeIds = new HashMap<>(); 122 Map<Long, Long> newWayIds = new HashMap<>(); 123 Map<Long, Long> newRelationIds = new HashMap<>(); 124 for (PrimitiveData data: pasteBuffer.getAll()) { 125 if (data.isIncomplete()) { 126 continue; 127 } 128 PrimitiveData copy = data.makeCopy(); 129 copy.clearOsmMetadata(); 130 if (data instanceof NodeData) { 131 newNodeIds.put(data.getUniqueId(), copy.getUniqueId()); 132 } else if (data instanceof WayData) { 133 newWayIds.put(data.getUniqueId(), copy.getUniqueId()); 134 } else if (data instanceof RelationData) { 135 newRelationIds.put(data.getUniqueId(), copy.getUniqueId()); 136 } 137 bufferCopy.add(copy); 138 if (pasteBuffer.getDirectlyAdded().contains(data)) { 139 toSelect.add(copy); 140 } 141 } 142 143 // Update references in copied buffer 144 for (PrimitiveData data:bufferCopy) { 145 if (data instanceof NodeData) { 146 NodeData nodeData = (NodeData) data; 147 if (Main.getLayerManager().getEditLayer() == source) { 148 nodeData.setEastNorth(nodeData.getEastNorth().add(offsetEast, offsetNorth)); 149 } 150 } else if (data instanceof WayData) { 151 List<Long> newNodes = new ArrayList<>(); 152 for (Long oldNodeId: ((WayData) data).getNodes()) { 153 Long newNodeId = newNodeIds.get(oldNodeId); 154 if (newNodeId != null) { 155 newNodes.add(newNodeId); 156 } 157 } 158 ((WayData) data).setNodes(newNodes); 159 } else if (data instanceof RelationData) { 160 List<RelationMemberData> newMembers = new ArrayList<>(); 161 for (RelationMemberData member: ((RelationData) data).getMembers()) { 162 OsmPrimitiveType memberType = member.getMemberType(); 163 Long newId; 164 switch (memberType) { 165 case NODE: 166 newId = newNodeIds.get(member.getMemberId()); 167 break; 168 case WAY: 169 newId = newWayIds.get(member.getMemberId()); 170 break; 171 case RELATION: 172 newId = newRelationIds.get(member.getMemberId()); 173 break; 174 default: throw new AssertionError(); 175 } 176 if (newId != null) { 177 newMembers.add(new RelationMemberData(member.getRole(), memberType, newId)); 178 } 179 } 180 ((RelationData) data).setMembers(newMembers); 181 } 182 } 183 184 /* Now execute the commands to add the duplicated contents of the paste buffer to the map */ 185 Main.main.undoRedo.add(new AddPrimitivesCommand(bufferCopy, toSelect)); 186 Main.map.mapView.repaint(); 187 } 188 189 private static boolean confirmDeleteIncomplete() { 190 ExtendedDialog ed = new ExtendedDialog(Main.parent, 191 tr("Delete incomplete members?"), 192 new String[] {tr("Paste without incomplete members"), tr("Cancel")}); 193 ed.setButtonIcons(new String[] {"dialogs/relation/deletemembers", "cancel"}); 194 ed.setContent(tr("The copied data contains incomplete objects. " 195 + "When pasting the incomplete objects are removed. " 196 + "Do you want to paste the data without the incomplete objects?")); 197 ed.showDialog(); 198 return ed.getValue() == 1; 59 transferHandler.pasteOn(Main.getLayerManager().getEditLayer(), mPosition); 199 60 } 200 61 201 62 @Override 202 63 protected void updateEnabledState() { 203 if (getLayerManager().getEditDataSet() == null || Main.pasteBuffer == null) { 204 setEnabled(false); 205 return; 206 } 207 setEnabled(!Main.pasteBuffer.isEmpty()); 64 setEnabled(getLayerManager().getEditDataSet() != null && transferHandler.isDataAvailable()); 208 65 } 209 66 210 67 @Override 211 public void pasteBufferChanged(PrimitiveDeepCopy pasteBuffer) {68 public void flavorsChanged(FlavorEvent e) { 212 69 updateEnabledState(); 213 70 } -
trunk/src/org/openstreetmap/josm/actions/PasteTagsAction.java
r10383 r10604 26 26 import org.openstreetmap.josm.data.osm.TagCollection; 27 27 import org.openstreetmap.josm.gui.conflict.tags.PasteTagsConflictResolverDialog; 28 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 28 29 import org.openstreetmap.josm.tools.I18n; 29 30 import org.openstreetmap.josm.tools.Shortcut; 30 31 import org.openstreetmap.josm.tools.TextTagParser; 31 import org.openstreetmap.josm.tools.Utils;32 32 33 33 /** … … 42 42 43 43 private static final String help = ht("/Action/PasteTags"); 44 private final OsmTransferHandler transferHandler = new OsmTransferHandler(); 44 45 45 46 /** … … 54 55 } 55 56 57 /** 58 * Used to update the tags. 59 */ 56 60 public static class TagPaster { 57 61 … … 259 263 return; 260 264 261 String buf = Utils.getClipboardContent(); 262 if (buf == null || buf.isEmpty() || buf.matches(CopyAction.CLIPBOARD_REGEXP)) { 263 pasteTagsFromJOSMBuffer(selection); 264 } else { 265 // Paste tags from arbitrary text 266 pasteTagsFromText(selection, buf); 267 } 265 transferHandler.pasteTags(selection); 268 266 } 269 267 … … 290 288 commitCommands(selection, commands); 291 289 return !commands.isEmpty(); 292 }293 294 /**295 * Paste tags from JOSM buffer296 * @param selection objects that will have the tags297 * @return false if JOSM buffer was empty298 */299 public static boolean pasteTagsFromJOSMBuffer(Collection<OsmPrimitive> selection) {300 List<PrimitiveData> directlyAdded = Main.pasteBuffer.getDirectlyAdded();301 if (directlyAdded == null || directlyAdded.isEmpty()) return false;302 303 PasteTagsAction.TagPaster tagPaster = new PasteTagsAction.TagPaster(directlyAdded, selection);304 List<Command> commands = new ArrayList<>();305 for (Tag tag : tagPaster.execute()) {306 commands.add(new ChangePropertyCommand(selection, tag.getKey(), "".equals(tag.getValue()) ? null : tag.getValue()));307 }308 commitCommands(selection, commands);309 return true;310 290 } 311 291 -
trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java
r10153 r10604 81 81 oos.writeInt(changesetId); 82 82 oos.writeInt(timestamp); 83 oos.writeObject(keys); 83 84 oos.defaultWriteObject(); 84 85 } … … 92 93 changesetId = ois.readInt(); 93 94 timestamp = ois.readInt(); 95 keys = (String[]) ois.readObject(); 94 96 ois.defaultReadObject(); 95 97 } -
trunk/src/org/openstreetmap/josm/data/osm/PrimitiveDeepCopy.java
r10600 r10604 2 2 package org.openstreetmap.josm.data.osm; 3 3 4 import java.awt.datatransfer.UnsupportedFlavorException; 5 import java.io.IOException; 4 6 import java.util.ArrayList; 5 7 import java.util.Collection; 6 import java.util. HashSet;8 import java.util.Collections; 7 9 import java.util.List; 8 import java.util.Set;9 import java.util.concurrent.CopyOnWriteArrayList;10 10 11 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor; 11 import org.openstreetmap.josm.Main; 12 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 13 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 14 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 12 15 13 16 /** 14 17 * This class allows to create and keep a deep copy of primitives. Provides methods to access directly added 15 18 * primitives and reference primitives 19 * <p> 20 * To be removed end of 2016 16 21 * @since 2305 22 * @deprecated This has been replaced by Swing Copy+Paste support. Use {@link OsmTransferHandler} instead. 17 23 */ 24 @Deprecated 18 25 public class PrimitiveDeepCopy { 19 20 @FunctionalInterface21 public interface PasteBufferChangedListener {22 void pasteBufferChanged(PrimitiveDeepCopy pasteBuffer);23 }24 25 private final List<PrimitiveData> directlyAdded = new ArrayList<>();26 private final List<PrimitiveData> referenced = new ArrayList<>();27 private final CopyOnWriteArrayList<PasteBufferChangedListener> listeners = new CopyOnWriteArrayList<>();28 26 29 27 /** … … 35 33 36 34 /** 37 * Constructs a new {@code PrimitiveDeepCopy} of given OSM primitives. 38 * @param primitives OSM primitives to copy 39 * @since 7961 35 * Gets the list of primitives that were explicitly added to this copy. 36 * @return The added primitives 40 37 */ 41 public PrimitiveDeepCopy(final Collection<? extends OsmPrimitive> primitives) {42 makeCopy(primitives);43 }44 45 /**46 * Replace content of the object with copy of provided primitives.47 * @param primitives OSM primitives to copy48 * @since 796149 */50 public final void makeCopy(final Collection<? extends OsmPrimitive> primitives) {51 directlyAdded.clear();52 referenced.clear();53 54 final Set<Long> visitedNodeIds = new HashSet<>();55 final Set<Long> visitedWayIds = new HashSet<>();56 final Set<Long> visitedRelationIds = new HashSet<>();57 58 new AbstractVisitor() {59 private boolean firstIteration;60 61 @Override62 public void visit(Node n) {63 if (!visitedNodeIds.add(n.getUniqueId()))64 return;65 (firstIteration ? directlyAdded : referenced).add(n.save());66 }67 68 @Override69 public void visit(Way w) {70 if (!visitedWayIds.add(w.getUniqueId()))71 return;72 (firstIteration ? directlyAdded : referenced).add(w.save());73 firstIteration = false;74 for (Node n : w.getNodes()) {75 visit(n);76 }77 }78 79 @Override80 public void visit(Relation r) {81 if (!visitedRelationIds.add(r.getUniqueId()))82 return;83 (firstIteration ? directlyAdded : referenced).add(r.save());84 firstIteration = false;85 for (RelationMember m : r.getMembers()) {86 m.getMember().accept(this);87 }88 }89 90 public void visitAll() {91 for (OsmPrimitive osm : primitives) {92 firstIteration = true;93 osm.accept(this);94 }95 }96 }.visitAll();97 98 firePasteBufferChanged();99 }100 101 38 public List<PrimitiveData> getDirectlyAdded() { 102 return directlyAdded; 103 } 104 105 public List<PrimitiveData> getReferenced() { 106 return referenced; 107 } 108 109 public List<PrimitiveData> getAll() { 110 List<PrimitiveData> result = new ArrayList<>(directlyAdded.size() + referenced.size()); 111 result.addAll(directlyAdded); 112 result.addAll(referenced); 113 return result; 39 try { 40 PrimitiveTransferData data = (PrimitiveTransferData) ClipboardUtils.getClipboard().getData(PrimitiveTransferData.DATA_FLAVOR); 41 return new ArrayList<>(data.getDirectlyAdded()); 42 } catch (UnsupportedFlavorException | IOException e) { 43 Main.debug(e); 44 return Collections.emptyList(); 45 } 114 46 } 115 47 116 48 public boolean isEmpty() { 117 return directlyAdded.isEmpty() && referenced.isEmpty(); 118 } 119 120 private void firePasteBufferChanged() { 121 for (PasteBufferChangedListener listener: listeners) { 122 listener.pasteBufferChanged(this); 123 } 124 } 125 126 public void addPasteBufferChangedListener(PasteBufferChangedListener listener) { 127 listeners.addIfAbsent(listener); 128 } 129 130 public void removePasteBufferChangedListener(PasteBufferChangedListener listener) { 131 listeners.remove(listener); 49 return !ClipboardUtils.getClipboard().isDataFlavorAvailable(PrimitiveTransferData.DATA_FLAVOR); 132 50 } 133 51 } -
trunk/src/org/openstreetmap/josm/data/osm/TagMap.java
r9978 r10604 2 2 package org.openstreetmap.josm.data.osm; 3 3 4 import java.io.Serializable; 4 5 import java.util.AbstractMap; 5 6 import java.util.AbstractSet; 7 import java.util.ArrayList; 6 8 import java.util.Arrays; 7 9 import java.util.ConcurrentModificationException; 8 10 import java.util.Iterator; 11 import java.util.List; 12 import java.util.Map; 9 13 import java.util.NoSuchElementException; 10 14 import java.util.Set; … … 17 21 * @author Michael Zangl 18 22 */ 19 public class TagMap extends AbstractMap<String, String> { 23 public class TagMap extends AbstractMap<String, String> implements Serializable { 24 static final long serialVersionUID = 1; 20 25 /** 21 26 * We use this array every time we want to represent an empty map. … … 108 113 */ 109 114 public TagMap() { 110 this(null); 115 this((String[]) null); 116 } 117 118 /** 119 * Create a new tag map and load it from the other map. 120 * @param tags The map to load from. 121 * @since 10604 122 */ 123 public TagMap(Map<String, String> tags) { 124 putAll(tags); 125 } 126 127 /** 128 * Copy constructor. 129 * @param tagMap The map to copy from. 130 * @since 10604 131 */ 132 public TagMap(TagMap tagMap) { 133 this(tagMap.tags); 111 134 } 112 135 … … 210 233 211 234 /** 235 * Gets a list of all tags contained in this map. 236 * @return The list of tags in the order they were added. 237 * @since 10604 238 */ 239 public List<Tag> getTags() { 240 List<Tag> tagList = new ArrayList<>(); 241 for (int i = 0; i < tags.length; i += 2) { 242 tagList.add(new Tag(tags[i], tags[i+1])); 243 } 244 return tagList; 245 } 246 247 /** 212 248 * Finds a key in an array that is structured like the {@link #tags} array and returns the position. 213 249 * <p> -
trunk/src/org/openstreetmap/josm/gui/MapFrame.java
r10600 r10604 9 9 import java.awt.Dimension; 10 10 import java.awt.Font; 11 import java.awt.GraphicsEnvironment;12 11 import java.awt.GridBagLayout; 13 12 import java.awt.Rectangle; … … 197 196 198 197 mapView = new MapView(Main.getLayerManager(), contentPane, viewportData); 199 if (!GraphicsEnvironment.isHeadless()) {200 new FileDrop(mapView);201 }202 198 203 199 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true); -
trunk/src/org/openstreetmap/josm/gui/MapView.java
r10600 r10604 53 53 import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache; 54 54 import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle; 55 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 55 56 import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable; 56 57 import org.openstreetmap.josm.gui.layer.GpxLayer; … … 581 582 add(c); 582 583 } 584 setTransferHandler(new OsmTransferHandler()); 583 585 } 584 586 -
trunk/src/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferable.java
r9969 r10604 5 5 import java.awt.datatransfer.Transferable; 6 6 import java.awt.datatransfer.UnsupportedFlavorException; 7 import java.io.Serializable;8 7 import java.util.ArrayList; 9 import java.util.Collection; 8 import java.util.Arrays; 9 import java.util.List; 10 10 11 import org.openstreetmap.josm.data.osm.OsmPrimitive ;11 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 12 12 import org.openstreetmap.josm.data.osm.PrimitiveData; 13 import org.openstreetmap.josm.gui. DefaultNameFormatter;14 import org.openstreetmap.josm. tools.CheckParameterUtil;13 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 14 import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData; 15 15 16 16 /** 17 * Transferable objects for {@link Primitive Data}.17 * Transferable objects for {@link PrimitiveTransferData} objects 18 18 * @since 9369 19 * @since 10604 Complete rework 19 20 */ 20 21 public class PrimitiveTransferable implements Transferable { 21 22 22 23 /** 23 * A wrapper for a collection of {@link PrimitiveData}.24 * The flavors that are available for normal primitives. 24 25 */ 25 public static final class Data implements Serializable { 26 private static final long serialVersionUID = -1485089993600213704L; 27 private final Collection<PrimitiveData> primitiveData; 28 29 private Data(Collection<PrimitiveData> primitiveData) { 30 CheckParameterUtil.ensureThat(primitiveData instanceof Serializable, "primitiveData must be instanceof Serializable"); 31 this.primitiveData = primitiveData; 32 } 33 34 /** 35 * Returns the contained {@link PrimitiveData} 36 * @return the contained {@link PrimitiveData} 37 */ 38 public Collection<PrimitiveData> getPrimitiveData() { 39 return primitiveData; 40 } 41 } 42 43 /** 44 * Data flavor for {@link PrimitiveData} which is wrapped in {@link Data}. 45 */ 46 public static final DataFlavor PRIMITIVE_DATA = new DataFlavor(Data.class, Data.class.getName()); 47 private final Collection<? extends OsmPrimitive> primitives; 26 private static final List<DataFlavor> PRIMITIVE_FLAVORS = Arrays.asList(PrimitiveTransferData.DATA_FLAVOR, 27 TagTransferData.FLAVOR, DataFlavor.stringFlavor); 28 private final PrimitiveTransferData primitives; 48 29 49 30 /** … … 51 32 * @param primitives collection of OSM primitives 52 33 */ 53 public PrimitiveTransferable( Collection<? extends OsmPrimitive>primitives) {34 public PrimitiveTransferable(PrimitiveTransferData primitives) { 54 35 this.primitives = primitives; 55 36 } … … 57 38 @Override 58 39 public DataFlavor[] getTransferDataFlavors() { 59 return new DataFlavor[]{PRIMITIVE_DATA, DataFlavor.stringFlavor}; 40 ArrayList<DataFlavor> flavors = new ArrayList<>(PRIMITIVE_FLAVORS); 41 return flavors.toArray(new DataFlavor[flavors.size()]); 60 42 } 61 43 62 44 @Override 63 45 public boolean isDataFlavorSupported(DataFlavor flavor) { 64 return flavor == PRIMITIVE_DATA; 46 DataFlavor[] flavors = getTransferDataFlavors(); 47 for (DataFlavor f : flavors) { 48 if (flavor.equals(f)) { 49 return true; 50 } 51 } 52 return false; 65 53 } 66 54 … … 69 57 if (DataFlavor.stringFlavor.equals(flavor)) { 70 58 return getStringData(); 71 } else if (PRIMITIVE_DATA.equals(flavor)) { 72 return getPrimitiveData(); 59 } else if (PrimitiveTransferData.DATA_FLAVOR.equals(flavor)) { 60 return primitives; 61 } else if (TagTransferData.FLAVOR.equals(flavor)) { 62 return new TagTransferData(primitives.getDirectlyAdded()); 63 } else { 64 throw new UnsupportedFlavorException(flavor); 73 65 } 74 throw new UnsupportedFlavorException(flavor);75 66 } 76 67 77 68 protected String getStringData() { 78 69 final StringBuilder sb = new StringBuilder(); 79 for ( OsmPrimitive primitive : primitives) {80 sb.append(primitive.getType())81 .append(' ').append(primitive.getUniqueId())82 .append(" # ").append(primitive.getDisplayName(DefaultNameFormatter.getInstance()))83 .append('\n');70 for (PrimitiveData primitive : primitives.getAll()) { 71 if (sb.length() > 0) { 72 sb.append("\n"); 73 } 74 sb.append(OsmPrimitiveType.from(primitive).getAPIName()).append(' ').append(primitive.getId()); 84 75 } 85 76 return sb.toString().replace("\u200E", "").replace("\u200F", ""); 86 77 } 87 88 protected Data getPrimitiveData() {89 final Collection<PrimitiveData> r = new ArrayList<>(primitives.size());90 for (OsmPrimitive primitive : primitives) {91 r.add(primitive.save());92 }93 return new Data(r);94 }95 78 } -
trunk/src/org/openstreetmap/josm/gui/datatransfer/RelationMemberTransferable.java
r9969 r10604 7 7 import java.io.Serializable; 8 8 import java.util.ArrayList; 9 import java.util.Arrays; 9 10 import java.util.Collection; 11 import java.util.Collections; 12 import java.util.HashSet; 10 13 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; 11 15 import org.openstreetmap.josm.data.osm.RelationMember; 12 16 import org.openstreetmap.josm.data.osm.RelationMemberData; 13 17 import org.openstreetmap.josm.gui.DefaultNameFormatter; 18 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 14 19 import org.openstreetmap.josm.tools.CheckParameterUtil; 15 20 … … 37 42 */ 38 43 public Collection<RelationMemberData> getRelationMemberData() { 39 return relationMemberDatas; 44 return Collections.unmodifiableCollection(relationMemberDatas); 45 } 46 47 /** 48 * Gets the Data for the given list of members. 49 * @param members The collection. The order is preserved. 50 * @return The data. 51 */ 52 public static Data getData(Collection<RelationMember> members) { 53 final Collection<RelationMemberData> r = new ArrayList<>(members.size()); 54 for (RelationMember member : members) { 55 r.add(new RelationMemberData(member.getRole(), member.getType(), member.getUniqueId())); 56 } 57 return new Data(r); 40 58 } 41 59 } … … 44 62 * Data flavor for {@link RelationMemberData} which is wrapped in {@link Data}. 45 63 */ 46 public static final DataFlavor RELATION_MEMBER_DATA = new DataFlavor(Data.class, Data.class.getName());64 public static final DataFlavor RELATION_MEMBER_DATA = new DataFlavor(Data.class, "Relation member"); 47 65 private final Collection<RelationMember> members; 48 66 … … 52 70 */ 53 71 public RelationMemberTransferable(Collection<RelationMember> members) { 54 this.members = members;72 this.members = new ArrayList<>(members); 55 73 } 56 74 57 75 @Override 58 76 public DataFlavor[] getTransferDataFlavors() { 59 return new DataFlavor[]{RELATION_MEMBER_DATA, DataFlavor.stringFlavor};77 return new DataFlavor[]{RELATION_MEMBER_DATA, PrimitiveTransferData.DATA_FLAVOR, DataFlavor.stringFlavor}; 60 78 } 61 79 62 80 @Override 63 81 public boolean isDataFlavorSupported(DataFlavor flavor) { 64 return flavor == RELATION_MEMBER_DATA;82 return Arrays.asList(getTransferDataFlavors()).contains(flavor); 65 83 } 66 84 … … 71 89 } else if (RELATION_MEMBER_DATA.equals(flavor)) { 72 90 return getRelationMemberData(); 91 } else if (PrimitiveTransferData.DATA_FLAVOR.equals(flavor)) { 92 return getPrimitiveData(); 73 93 } 74 94 throw new UnsupportedFlavorException(flavor); 95 } 96 97 private PrimitiveTransferData getPrimitiveData() { 98 Collection<OsmPrimitive> primitives = new HashSet<>(); 99 for (RelationMember member : members) { 100 primitives.add(member.getMember()); 101 } 102 return PrimitiveTransferData.getData(primitives); 75 103 } 76 104 … … 88 116 89 117 protected Data getRelationMemberData() { 90 final Collection<RelationMemberData> r = new ArrayList<>(members.size()); 91 for (RelationMember member : members) { 92 r.add(new RelationMemberData(member.getRole(), member.getType(), member.getUniqueId())); 93 } 94 return new Data(r); 118 return Data.getData(members); 95 119 } 96 120 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/OsmIdSelectionDialog.java
r10173 r10604 34 34 import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 35 35 import org.openstreetmap.josm.gui.ExtendedDialog; 36 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 36 37 import org.openstreetmap.josm.gui.widgets.HistoryComboBox; 37 38 import org.openstreetmap.josm.gui.widgets.HtmlPanel; … … 202 203 203 204 protected void tryToPasteFromClipboard(OsmIdTextField tfId, OsmPrimitiveTypesComboBox cbType) { 204 String buf = Utils.getClipboardContent();205 String buf = ClipboardUtils.getClipboardStringContent(); 205 206 if (buf == null || buf.isEmpty()) return; 206 207 if (buf.length() > Main.pref.getInteger("downloadprimitive.max-autopaste-length", 2000)) return; -
trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
r10453 r10604 70 70 import org.openstreetmap.josm.gui.SideButton; 71 71 import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable; 72 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 72 73 import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager; 73 74 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; … … 881 882 @Override 882 883 protected Transferable createTransferable(JComponent c) { 883 return new PrimitiveTransferable( getSelectedPrimitives());884 return new PrimitiveTransferable(PrimitiveTransferData.getData(getSelectedPrimitives())); 884 885 } 885 886 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
r10446 r10604 87 87 import org.openstreetmap.josm.gui.PopupMenuHandler; 88 88 import org.openstreetmap.josm.gui.SideButton; 89 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 89 90 import org.openstreetmap.josm.gui.dialogs.ToggleDialog; 90 91 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor; … … 1265 1266 String key = editHelper.getDataKey(tagTable.getSelectedRow()); 1266 1267 Collection<OsmPrimitive> sel = Main.main.getInProgressSelection(); 1267 String clipboard = Utils.getClipboardContent();1268 String clipboard = ClipboardUtils.getClipboardStringContent(); 1268 1269 if (sel.isEmpty() || clipboard == null) 1269 1270 return; … … 1295 1296 } 1296 1297 if (!values.isEmpty()) { 1297 Utils.copyToClipboard(Utils.join("\n", values));1298 ClipboardUtils.copyString(Utils.join("\n", values)); 1298 1299 } 1299 1300 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java
r10413 r10604 77 77 import org.openstreetmap.josm.data.preferences.StringProperty; 78 78 import org.openstreetmap.josm.gui.ExtendedDialog; 79 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 79 80 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles; 80 81 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox; … … 584 585 private void selectACComboBoxSavingUnixBuffer(AutoCompletingComboBox cb) { 585 586 // select combobox with saving unix system selection (middle mouse paste) 586 Clipboard sysSel = GuiHelper.getSystemSelection();587 Clipboard sysSel = ClipboardUtils.getSystemSelection(); 587 588 if (sysSel != null) { 588 Transferable old = Utils.getTransferableContent(sysSel);589 Transferable old = ClipboardUtils.getClipboardContent(sysSel); 589 590 cb.requestFocusInWindow(); 590 591 cb.getEditor().selectAll(); -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
r10454 r10604 12 12 import java.awt.GridBagLayout; 13 13 import java.awt.Window; 14 import java.awt.datatransfer.Clipboard; 15 import java.awt.datatransfer.FlavorListener; 14 16 import java.awt.event.ActionEvent; 15 17 import java.awt.event.FocusAdapter; … … 62 64 import org.openstreetmap.josm.gui.DefaultNameFormatter; 63 65 import org.openstreetmap.josm.gui.MainMenu; 66 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 64 67 import org.openstreetmap.josm.gui.dialogs.relation.actions.AddSelectedAfterSelection; 65 68 import org.openstreetmap.josm.gui.dialogs.relation.actions.AddSelectedAtEndAction; … … 153 156 */ 154 157 private final CancelAction cancelAction; 158 /** 159 * A list of listeners that need to be notified on clipboard content changes. 160 */ 161 private final ArrayList<FlavorListener> clipboardListeners = new ArrayList<>(); 155 162 156 163 /** … … 274 281 // CHECKSTYLE.ON: LineLength 275 282 276 registerCopyPasteAction(new PasteMembersAction(memberTable Model, getLayer(), this) {283 registerCopyPasteAction(new PasteMembersAction(memberTable, getLayer(), this) { 277 284 @Override 278 285 public void actionPerformed(ActionEvent e) { … … 743 750 } 744 751 super.setVisible(visible); 752 Clipboard clipboard = ClipboardUtils.getClipboard(); 745 753 if (visible) { 746 754 leftButtonToolbar.sortBelowButton.setVisible(ExpertToggleAction.isExpert()); … … 750 758 } 751 759 tagEditorPanel.requestFocusInWindow(); 760 for (FlavorListener listener : clipboardListeners) { 761 clipboard.addFlavorListener(listener); 762 } 752 763 } else { 753 764 // make sure all registered listeners are unregistered … … 760 771 Main.main.menu.windowMenu.remove(windowMenuItem); 761 772 windowMenuItem = null; 773 } 774 for (FlavorListener listener : clipboardListeners) { 775 clipboard.removeFlavorListener(listener); 762 776 } 763 777 dispose(); … … 824 838 } 825 839 826 private staticvoid registerCopyPasteAction(AbstractAction action, Object actionName, KeyStroke shortcut,840 private void registerCopyPasteAction(AbstractAction action, Object actionName, KeyStroke shortcut, 827 841 JRootPane rootPane, JTable... tables) { 828 842 int mods = shortcut.getModifiers(); … … 840 854 table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shortcut, actionName); 841 855 table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName); 856 } 857 if (action instanceof FlavorListener) { 858 clipboardListeners.add((FlavorListener) action); 842 859 } 843 860 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTable.java
r10478 r10604 86 86 zoomToGap = new ZoomToGapAction(); 87 87 registerListeners(); 88 menu.addSeparator(); 88 89 getSelectionModel().addListSelectionListener(zoomToGap); 89 90 menu.add(zoomToGap); -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
r10413 r10604 480 480 } 481 481 invalidateConnectionType(); 482 final List<Integer> selection = getSelectedIndices();483 482 fireTableRowsInserted(index, idx - 1); 484 setSelectedMembersIdx(selection);485 483 } 486 484 -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTransferHandler.java
r10212 r10604 17 17 import org.openstreetmap.josm.data.osm.OsmPrimitive; 18 18 import org.openstreetmap.josm.data.osm.PrimitiveData; 19 import org.openstreetmap.josm.data.osm.PrimitiveId; 19 20 import org.openstreetmap.josm.data.osm.RelationMember; 20 21 import org.openstreetmap.josm.data.osm.RelationMemberData; 21 import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable;22 22 import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable; 23 import org.openstreetmap.josm. tools.Utils.Function;23 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 24 24 25 class MemberTransferHandler extends TransferHandler { 25 /** 26 * A transfer handler that helps with importing / exporting members for relations. 27 * @author Michael Zangl 28 * @since 10604 29 */ 30 public class MemberTransferHandler extends TransferHandler { 26 31 27 32 @Override … … 38 43 @Override 39 44 public boolean canImport(TransferSupport support) { 40 support.setShowDropLocation(true); 45 if (support.isDrop()) { 46 support.setShowDropLocation(true); 47 } 41 48 return support.isDataFlavorSupported(RelationMemberTransferable.RELATION_MEMBER_DATA) 42 || support.isDataFlavorSupported(PrimitiveTransfer able.PRIMITIVE_DATA);49 || support.isDataFlavorSupported(PrimitiveTransferData.DATA_FLAVOR); 43 50 } 44 51 45 52 @Override 46 53 public boolean importData(TransferSupport support) { 47 finalMemberTable destination = (MemberTable) support.getComponent();48 final int insertRow = ((JTable.DropLocation) support.getDropLocation()).getRow();54 MemberTable destination = (MemberTable) support.getComponent(); 55 int insertRow = computeInsertionRow(support, destination); 49 56 57 return importDataAt(support, destination, insertRow); 58 } 59 60 private int computeInsertionRow(TransferSupport support, MemberTable destination) { 61 final int insertRow; 62 if (support.isDrop()) { 63 insertRow = ((JTable.DropLocation) support.getDropLocation()).getRow(); 64 } else { 65 int selection = destination.getSelectedRow(); 66 if (selection < 0) { 67 // no selection, add at the end. 68 insertRow = destination.getRowCount(); 69 } else { 70 insertRow = selection; 71 } 72 } 73 return insertRow; 74 } 75 76 private boolean importDataAt(TransferSupport support, MemberTable destination, int insertRow) { 50 77 try { 51 78 if (support.isDataFlavorSupported(RelationMemberTransferable.RELATION_MEMBER_DATA)) { 52 79 importRelationMemberData(support, destination, insertRow); 53 } else if (support.isDataFlavorSupported(PrimitiveTransferable.PRIMITIVE_DATA)) { 80 return true; 81 } else if (support.isDataFlavorSupported(PrimitiveTransferData.DATA_FLAVOR)) { 54 82 importPrimitiveData(support, destination, insertRow); 83 return true; 84 } else { 85 return false; 55 86 } 56 87 } catch (IOException | UnsupportedFlavorException e) { … … 58 89 return false; 59 90 } 60 61 return true;62 91 } 63 92 … … 66 95 final RelationMemberTransferable.Data memberData = (RelationMemberTransferable.Data) 67 96 support.getTransferable().getTransferData(RelationMemberTransferable.RELATION_MEMBER_DATA); 68 importData(destination, insertRow, memberData.getRelationMemberData(), new Function<RelationMemberData, RelationMember>() {97 importData(destination, insertRow, memberData.getRelationMemberData(), new AbstractRelationMemberConverter<RelationMemberData>() { 69 98 @Override 70 public RelationMember apply(RelationMemberData member) { 71 final OsmPrimitive p = destination.getLayer().data.getPrimitiveById(member.getUniqueId(), member.getType()); 72 if (p == null) { 73 Main.warn(tr("Cannot add {0} since it is not part of dataset", member)); 74 return null; 75 } else { 76 return new RelationMember(member.getRole(), p); 77 } 99 protected RelationMember getMember(MemberTable destination, RelationMemberData data, OsmPrimitive p) { 100 return new RelationMember(data.getRole(), p); 78 101 } 79 102 }); … … 82 105 protected void importPrimitiveData(TransferSupport support, final MemberTable destination, int insertRow) 83 106 throws UnsupportedFlavorException, IOException { 84 final PrimitiveTransfer able.Data data = (PrimitiveTransferable.Data)85 support.getTransferable().getTransferData(PrimitiveTransfer able.PRIMITIVE_DATA);86 importData(destination, insertRow, data.get PrimitiveData(), new Function<PrimitiveData, RelationMember>() {107 final PrimitiveTransferData data = (PrimitiveTransferData) 108 support.getTransferable().getTransferData(PrimitiveTransferData.DATA_FLAVOR); 109 importData(destination, insertRow, data.getDirectlyAdded(), new AbstractRelationMemberConverter<PrimitiveData>() { 87 110 @Override 88 public RelationMember apply(PrimitiveData data) { 89 final OsmPrimitive p = destination.getLayer().data.getPrimitiveById(data); 90 if (p == null) { 91 Main.warn(tr("Cannot add {0} since it is not part of dataset", data)); 92 return null; 93 } else { 94 return destination.getMemberTableModel().getRelationMemberForPrimitive(p); 95 } 111 protected RelationMember getMember(MemberTable destination, PrimitiveData data, OsmPrimitive p) { 112 return destination.getMemberTableModel().getRelationMemberForPrimitive(p); 96 113 } 97 114 }); 98 115 } 99 116 100 protected <T > void importData(MemberTable destination, int insertRow,101 Collection<T> memberData, Function<T, RelationMember> toMemberFunction) {117 protected <T extends PrimitiveId> void importData(MemberTable destination, int insertRow, 118 Collection<T> memberData, AbstractRelationMemberConverter<T> toMemberFunction) { 102 119 final Collection<RelationMember> membersToAdd = new ArrayList<>(memberData.size()); 103 for (T i: memberData) {104 final RelationMember member = toMemberFunction. apply(i);120 for (T data : memberData) { 121 final RelationMember member = toMemberFunction.importPrimitive(destination, data); 105 122 if (member != null) { 106 123 membersToAdd.add(member); … … 120 137 model.selectionChanged(null); 121 138 } 139 140 private abstract static class AbstractRelationMemberConverter<T extends PrimitiveId> { 141 protected RelationMember importPrimitive(MemberTable destination, T data) { 142 final OsmPrimitive p = destination.getLayer().data.getPrimitiveById(data); 143 if (p == null) { 144 Main.warn(tr("Cannot add {0} since it is not part of dataset", data)); 145 return null; 146 } else { 147 return getMember(destination, data, p); 148 } 149 } 150 151 protected abstract RelationMember getMember(MemberTable destination, T data, OsmPrimitive p); 152 } 122 153 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/CopyMembersAction.java
r9710 r10604 5 5 import java.util.Collection; 6 6 7 import org.openstreetmap.josm.actions.CopyAction; 8 import org.openstreetmap.josm.data.osm.OsmPrimitive; 7 import org.openstreetmap.josm.data.osm.RelationMember; 8 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 9 import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable; 9 10 import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor; 10 11 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel; … … 29 30 @Override 30 31 public void actionPerformed(ActionEvent e) { 31 final Collection<OsmPrimitive> primitives = memberTableModel.getSelectedChildPrimitives(); 32 if (!primitives.isEmpty()) { 33 CopyAction.copy(layer, primitives); 32 final Collection<RelationMember> members = memberTableModel.getSelectedMembers(); 33 34 if (!members.isEmpty()) { 35 ClipboardUtils.copy(new RelationMemberTransferable(members)); 34 36 } 35 37 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersAction.java
r10420 r10604 2 2 package org.openstreetmap.josm.gui.dialogs.relation.actions; 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 4 import java.awt.datatransfer.FlavorEvent; 5 import java.awt.datatransfer.FlavorListener; 6 import java.awt.event.ActionEvent; 5 7 6 import java.awt.event.ActionEvent; 7 import java.util.ArrayList; 8 import java.util.List; 8 import javax.swing.TransferHandler.TransferSupport; 9 9 10 import javax.swing.JOptionPane; 11 12 import org.openstreetmap.josm.Main; 13 import org.openstreetmap.josm.data.osm.DataSet; 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 import org.openstreetmap.josm.data.osm.PrimitiveData; 16 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException; 10 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 17 11 import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor; 18 import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel; 12 import org.openstreetmap.josm.gui.dialogs.relation.MemberTable; 13 import org.openstreetmap.josm.gui.dialogs.relation.MemberTransferHandler; 19 14 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 20 15 … … 23 18 * @since 9496 24 19 */ 25 public class PasteMembersAction extends AddFromSelectionAction {20 public class PasteMembersAction extends AddFromSelectionAction implements FlavorListener { 26 21 27 22 /** 28 23 * Constructs a new {@code PasteMembersAction}. 29 * @param memberTable Model member table model24 * @param memberTable member table 30 25 * @param layer OSM data layer 31 26 * @param editor relation editor 32 27 */ 33 public PasteMembersAction(MemberTableModel memberTableModel, OsmDataLayer layer, IRelationEditor editor) { 34 super(null, memberTableModel, null, null, null, layer, editor); 28 public PasteMembersAction(MemberTable memberTable, OsmDataLayer layer, IRelationEditor editor) { 29 super(memberTable, null, null, null, null, layer, editor); 30 updateEnabledState(); 35 31 } 36 32 37 33 @Override 38 34 public void actionPerformed(ActionEvent e) { 39 try { 40 List<PrimitiveData> primitives = Main.pasteBuffer.getDirectlyAdded(); 41 DataSet ds = layer.data; 42 List<OsmPrimitive> toAdd = new ArrayList<>(); 43 boolean hasNewInOtherLayer = false; 35 new MemberTransferHandler().importData(getSupport()); 36 } 44 37 45 for (PrimitiveData primitive: primitives) { 46 OsmPrimitive primitiveInDs = ds.getPrimitiveById(primitive); 47 if (primitiveInDs != null) { 48 toAdd.add(primitiveInDs); 49 } else if (!primitive.isNew()) { 50 OsmPrimitive p = primitive.getType().newInstance(primitive.getUniqueId(), true); 51 ds.addPrimitive(p); 52 toAdd.add(p); 53 } else { 54 hasNewInOtherLayer = true; 55 break; 56 } 57 } 58 59 if (hasNewInOtherLayer) { 60 JOptionPane.showMessageDialog(Main.parent, 61 tr("Members from paste buffer cannot be added because they are not included in current layer")); 62 return; 63 } 64 65 toAdd = filterConfirmedPrimitives(toAdd); 66 int index = memberTableModel.getSelectionModel().getMaxSelectionIndex(); 67 if (index == -1) { 68 index = memberTableModel.getRowCount() - 1; 69 } 70 memberTableModel.addMembersAfterIdx(toAdd, index); 71 72 } catch (AddAbortException ex) { 73 Main.trace(ex); 74 } 38 private TransferSupport getSupport() { 39 return new TransferSupport(memberTable, ClipboardUtils.getClipboard().getContents(null)); 75 40 } 76 41 77 42 @Override 78 43 protected void updateEnabledState() { 79 // Do nothing 44 setEnabled(new MemberTransferHandler().canImport(getSupport())); 45 } 46 47 @Override 48 public void flavorsChanged(FlavorEvent e) { 49 updateEnabledState(); 80 50 } 81 51 } -
trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java
r10424 r10604 39 39 import org.openstreetmap.josm.data.Bounds; 40 40 import org.openstreetmap.josm.gui.MapView; 41 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 41 42 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction; 42 43 import org.openstreetmap.josm.gui.help.HelpUtil; … … 48 49 import org.openstreetmap.josm.tools.InputMapUtils; 49 50 import org.openstreetmap.josm.tools.OsmUrlToBounds; 50 import org.openstreetmap.josm.tools.Utils;51 51 import org.openstreetmap.josm.tools.WindowGeometry; 52 52 … … 243 243 @Override 244 244 public void actionPerformed(ActionEvent e) { 245 String clip = Utils.getClipboardContent();245 String clip = ClipboardUtils.getClipboardStringContent(); 246 246 if (clip == null) { 247 247 return; -
trunk/src/org/openstreetmap/josm/gui/layer/NoteLayer.java
r10484 r10604 31 31 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 32 32 import org.openstreetmap.josm.gui.MapView; 33 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 33 34 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 34 35 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; … … 41 42 import org.openstreetmap.josm.tools.ColorHelper; 42 43 import org.openstreetmap.josm.tools.ImageProvider; 43 import org.openstreetmap.josm.tools.Utils;44 44 import org.openstreetmap.josm.tools.date.DateUtils; 45 45 … … 238 238 if (SwingUtilities.isRightMouseButton(e) && noteData.getSelectedNote() != null) { 239 239 final String url = OsmApi.getOsmApi().getBaseUrl() + "notes/" + noteData.getSelectedNote().getId(); 240 Utils.copyToClipboard(url);240 ClipboardUtils.copyString(url); 241 241 return; 242 242 } else if (!SwingUtilities.isLeftMouseButton(e)) { -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
r10436 r10604 53 53 import org.openstreetmap.josm.gui.NavigatableComponent; 54 54 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 55 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 55 56 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 56 57 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; … … 725 726 public void copyCurrentPhotoPath() { 726 727 if (data != null && !data.isEmpty() && currentPhoto >= 0 && currentPhoto < data.size()) { 727 Utils.copyToClipboard(data.get(currentPhoto).getFile().toString());728 ClipboardUtils.copyString(data.get(currentPhoto).getFile().toString()); 728 729 } 729 730 } -
trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorModel.java
r10217 r10604 8 8 import java.util.ArrayList; 9 9 import java.util.Collection; 10 import java.util.Collections; 10 11 import java.util.Comparator; 11 12 import java.util.EnumSet; … … 25 26 import org.openstreetmap.josm.data.osm.Tag; 26 27 import org.openstreetmap.josm.data.osm.TagCollection; 28 import org.openstreetmap.josm.data.osm.TagMap; 27 29 import org.openstreetmap.josm.data.osm.Tagged; 28 30 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType; … … 47 49 48 50 private transient OsmPrimitive primitive; 51 52 private EndEditListener endEditListener; 49 53 50 54 /** … … 167 171 */ 168 172 public void clear() { 173 commitPendingEdit(); 169 174 boolean wasEmpty = tags.isEmpty(); 170 175 tags.clear(); … … 183 188 */ 184 189 public void add(TagModel tag) { 190 commitPendingEdit(); 185 191 CheckParameterUtil.ensureParameterNotNull(tag, "tag"); 186 192 tags.add(tag); … … 189 195 } 190 196 197 /** 198 * Add a tag at the beginning of the table. 199 * 200 * @param tag The tag to add 201 * 202 * @throws IllegalArgumentException if tag is null 203 * 204 * @see #add(TagModel) 205 */ 191 206 public void prepend(TagModel tag) { 207 commitPendingEdit(); 192 208 CheckParameterUtil.ensureParameterNotNull(tag, "tag"); 193 209 tags.add(0, tag); … … 209 225 */ 210 226 public void add(String name, String value) { 227 commitPendingEdit(); 211 228 String key = (name == null) ? "" : name; 212 229 String val = (value == null) ? "" : value; … … 259 276 if (tags == null) 260 277 return; 278 commitPendingEdit(); 261 279 for (int tagIdx : tagIndices) { 262 280 TagModel tag = tags.get(tagIdx); … … 277 295 if (tags == null) 278 296 return; 297 commitPendingEdit(); 279 298 for (int tagIdx : tagIndices) { 280 299 TagModel tag = tags.get(tagIdx); … … 293 312 */ 294 313 public void delete(String name) { 314 commitPendingEdit(); 295 315 if (name == null) 296 316 return; … … 318 338 if (tags == null) 319 339 return; 340 commitPendingEdit(); 320 341 List<TagModel> toDelete = new ArrayList<>(); 321 342 for (int tagIdx : tagIndices) { … … 356 377 */ 357 378 public void initFromPrimitive(Tagged primitive) { 379 commitPendingEdit(); 358 380 this.tags.clear(); 359 381 for (String key : primitive.keySet()) { … … 361 383 this.tags.add(new TagModel(key, value)); 362 384 } 385 sort(); 363 386 TagModel tag = new TagModel(); 364 sort();365 387 tags.add(tag); 366 388 setDirty(false); … … 374 396 */ 375 397 public void initFromTags(Map<String, String> tags) { 398 commitPendingEdit(); 376 399 this.tags.clear(); 377 400 for (Entry<String, String> entry : tags.entrySet()) { … … 391 414 */ 392 415 public void initFromTags(TagCollection tags) { 416 commitPendingEdit(); 393 417 this.tags.clear(); 394 418 if (tags == null) { … … 424 448 */ 425 449 private Map<String, String> applyToTags(boolean keepEmpty) { 426 Map<String, String> result = new HashMap<>(); 450 // TagMap preserves the order of tags. 451 TagMap result = new TagMap(); 427 452 for (TagModel tag: this.tags) { 428 453 // tag still holds an unchanged list of different values for the same key. … … 433 458 434 459 // tag name holds an empty key. Don't apply it to the selection. 435 //436 460 if (!keepEmpty && (tag.getName().trim().isEmpty() || tag.getValue().trim().isEmpty())) { 437 461 continue; … … 539 563 */ 540 564 protected void sort() { 541 java.util.Collections.sort(565 Collections.sort( 542 566 tags, 543 567 new Comparator<TagModel>() { … … 591 615 */ 592 616 public void updateTags(List<Tag> tags) { 593 617 if (tags.isEmpty()) 594 618 return; 595 619 620 commitPendingEdit(); 596 621 Map<String, TagModel> modelTags = new HashMap<>(); 597 622 for (int i = 0; i < getRowCount(); i++) { … … 648 673 } 649 674 675 /** 676 * Sets the listener that is notified when an edit should be aborted. 677 * @param endEditListener The listener to be notified when editing should be aborted. 678 */ 679 public void setEndEditListener(EndEditListener endEditListener) { 680 this.endEditListener = endEditListener; 681 } 682 683 private void commitPendingEdit() { 684 if (endEditListener != null) { 685 endEditListener.endCellEditing(); 686 } 687 } 688 650 689 class SelectionStateMemento { 651 690 private final int rowMin; … … 674 713 } 675 714 } 715 716 /** 717 * A listener that is called whenever the cells may be updated from outside the editor and the editor should thus be commited. 718 * @since 10604 719 */ 720 @FunctionalInterface 721 public interface EndEditListener { 722 /** 723 * Requests to end the editing of any cells on this model 724 */ 725 void endCellEditing(); 726 } 676 727 } -
trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java
r10378 r10604 2 2 package org.openstreetmap.josm.gui.tagging; 3 3 4 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;5 4 import static org.openstreetmap.josm.tools.I18n.tr; 6 5 … … 13 12 import java.beans.PropertyChangeEvent; 14 13 import java.beans.PropertyChangeListener; 15 import java.util.ArrayList;16 14 import java.util.Collections; 17 15 import java.util.EventObject; 18 import java.util.List;19 import java.util.Map;20 16 import java.util.concurrent.CopyOnWriteArrayList; 21 17 … … 32 28 33 29 import org.openstreetmap.josm.Main; 34 import org.openstreetmap.josm.actions.CopyAction;35 import org.openstreetmap.josm.actions.PasteTagsAction;36 import org.openstreetmap.josm.data.osm.OsmPrimitive;37 import org.openstreetmap.josm.data.osm.PrimitiveData;38 30 import org.openstreetmap.josm.data.osm.Relation; 39 import org.openstreetmap.josm.data.osm.Tag; 31 import org.openstreetmap.josm.data.osm.TagMap; 32 import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler; 33 import org.openstreetmap.josm.gui.tagging.TagEditorModel.EndEditListener; 40 34 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList; 41 35 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager; 42 36 import org.openstreetmap.josm.gui.widgets.JosmTable; 43 37 import org.openstreetmap.josm.tools.ImageProvider; 44 import org.openstreetmap.josm.tools.TextTagParser;45 import org.openstreetmap.josm.tools.Utils;46 38 47 39 /** … … 49 41 * @since 1762 50 42 */ 51 public class TagTable extends JosmTable {43 public class TagTable extends JosmTable implements EndEditListener { 52 44 /** the table cell editor used by this table */ 53 45 private TagCellEditor editor; … … 211 203 } 212 204 213 if (isEditing()) { 214 CellEditor cEditor = getCellEditor(); 215 if (cEditor != null) { 216 cEditor.cancelCellEditing(); 217 } 218 } 205 endCellEditing(); 219 206 220 207 if (model.getRowCount() == 0) { … … 233 220 234 221 protected final void updateEnabledState() { 235 if (isEditing() && getSelectedColumnCount() == 1 && getSelectedRowCount() == 1) { 236 setEnabled(true); 237 } else if (!isEditing() && getSelectedColumnCount() == 1 && getSelectedRowCount() == 1) { 238 setEnabled(true); 239 } else if (getSelectedColumnCount() > 1 || getSelectedRowCount() > 1) { 222 if (getSelectedColumnCount() >= 1 && getSelectedRowCount() >= 1) { 240 223 setEnabled(true); 241 224 } else { … … 295 278 Relation relation = new Relation(); 296 279 model.applyToPrimitive(relation); 297 298 String buf = Utils.getClipboardContent(); 299 if (buf == null || buf.isEmpty() || buf.matches(CopyAction.CLIPBOARD_REGEXP)) { 300 List<PrimitiveData> directlyAdded = Main.pasteBuffer.getDirectlyAdded(); 301 if (directlyAdded == null || directlyAdded.isEmpty()) return; 302 PasteTagsAction.TagPaster tagPaster = new PasteTagsAction.TagPaster(directlyAdded, 303 Collections.<OsmPrimitive>singletonList(relation)); 304 model.updateTags(tagPaster.execute()); 305 } else { 306 // Paste tags from arbitrary text 307 Map<String, String> tags = TextTagParser.readTagsFromText(buf); 308 if (tags == null || tags.isEmpty()) { 309 TextTagParser.showBadBufferMessage(ht("/Action/PasteTags")); 310 } else if (TextTagParser.validateTags(tags)) { 311 List<Tag> newTags = new ArrayList<>(); 312 for (Map.Entry<String, String> entry: tags.entrySet()) { 313 String k = entry.getKey(); 314 String v = entry.getValue(); 315 newTags.add(new Tag(k, v)); 316 } 317 model.updateTags(newTags); 318 } 319 } 280 new OsmTransferHandler().pasteTags(Collections.singleton(relation)); 281 model.updateTags(new TagMap(relation.getKeys()).getTags()); 320 282 } 321 283 … … 415 377 model.getRowSelectionModel()); 416 378 this.model = model; 379 model.setEndEditListener(this); 417 380 init(maxCharacters); 418 381 } … … 488 451 */ 489 452 public void setTagCellEditor(TagCellEditor editor) { 490 if (isEditing()) { 491 this.editor.cancelCellEditing(); 492 } 453 endCellEditing(); 493 454 this.editor = editor; 494 455 getColumnModel().getColumn(0).setCellEditor(editor); … … 546 507 // delegate to the default implementation 547 508 return super.editCellAt(row, column, e); 509 } 510 511 @Override 512 public void endCellEditing() { 513 if (isEditing()) { 514 CellEditor cEditor = getCellEditor(); 515 if (cEditor != null) { 516 // First attempt to commit. If this does not work, cancel. 517 cEditor.stopCellEditing(); 518 cEditor.cancelCellEditing(); 519 } 520 } 548 521 } 549 522 -
trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletingComboBox.java
r10308 r10604 24 24 25 25 import org.openstreetmap.josm.Main; 26 import org.openstreetmap.josm.gui. util.GuiHelper;26 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 27 27 import org.openstreetmap.josm.gui.widgets.JosmComboBox; 28 import org.openstreetmap.josm.tools.Utils;29 28 30 29 /** … … 134 133 final JTextComponent editorComponent = comboBox.getEditorComponent(); 135 134 // save unix system selection (middle mouse paste) 136 Clipboard sysSel = GuiHelper.getSystemSelection();135 Clipboard sysSel = ClipboardUtils.getSystemSelection(); 137 136 if (sysSel != null) { 138 Transferable old = Utils.getTransferableContent(sysSel);137 Transferable old = ClipboardUtils.getClipboardContent(sysSel); 139 138 editorComponent.select(start, end); 140 139 if (old != null) { … … 201 200 } 202 201 // save unix system selection (middle mouse paste) 203 Clipboard sysSel = GuiHelper.getSystemSelection();202 Clipboard sysSel = ClipboardUtils.getSystemSelection(); 204 203 if (sysSel != null) { 205 Transferable old = Utils.getTransferableContent(sysSel);204 Transferable old = ClipboardUtils.getClipboardContent(sysSel); 206 205 editorComponent.selectAll(); 207 206 if (old != null) { -
trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java
r10471 r10604 21 21 import java.awt.Toolkit; 22 22 import java.awt.Window; 23 import java.awt.datatransfer.Clipboard;24 23 import java.awt.event.ActionListener; 25 24 import java.awt.event.HierarchyEvent; … … 497 496 498 497 /** 499 * Gets the singleton instance of the system selection as a <code>Clipboard</code> object.500 * This allows an application to read and modify the current, system-wide selection.501 * @return the system selection as a <code>Clipboard</code>, or <code>null</code> if the native platform does not502 * support a system selection <code>Clipboard</code> or if GraphicsEnvironment.isHeadless() returns true503 * @see Toolkit#getSystemSelection504 * @since 9576505 */506 public static Clipboard getSystemSelection() {507 return GraphicsEnvironment.isHeadless() ? null : Toolkit.getDefaultToolkit().getSystemSelection();508 }509 510 /**511 498 * Returns the first <code>Window</code> ancestor of event source, or 512 499 * {@code null} if event source is not a component contained inside a <code>Window</code>. -
trunk/src/org/openstreetmap/josm/gui/widgets/AbstractIdTextField.java
r10212 r10604 5 5 6 6 import org.openstreetmap.josm.Main; 7 import org.openstreetmap.josm. tools.Utils;7 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 8 8 9 9 /** … … 71 71 */ 72 72 public void tryToPasteFromClipboard() { 73 tryToPasteFrom( Utils.getClipboardContent());73 tryToPasteFrom(ClipboardUtils.getClipboardStringContent()); 74 74 } 75 75 -
trunk/src/org/openstreetmap/josm/gui/widgets/UrlLabel.java
r10181 r10604 11 11 import javax.swing.SwingUtilities; 12 12 13 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 13 14 import org.openstreetmap.josm.tools.OpenBrowser; 14 import org.openstreetmap.josm.tools.Utils;15 15 16 16 /** … … 112 112 OpenBrowser.displayUrl(url); 113 113 } else if (SwingUtilities.isRightMouseButton(e)) { 114 Utils.copyToClipboard(url);114 ClipboardUtils.copyString(url); 115 115 } 116 116 } -
trunk/src/org/openstreetmap/josm/tools/TextTagParser.java
r10378 r10604 19 19 import org.openstreetmap.josm.Main; 20 20 import org.openstreetmap.josm.gui.ExtendedDialog; 21 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 21 22 import org.openstreetmap.josm.gui.help.HelpUtil; 22 23 import org.openstreetmap.josm.gui.widgets.UrlLabel; … … 291 292 if (r == 0) r = 2; 292 293 // clean clipboard if user asked 293 if (r == 3) Utils.copyToClipboard("");294 if (r == 3) ClipboardUtils.copyString(""); 294 295 return r; 295 296 } … … 326 327 int r = ed.getValue(); 327 328 // clean clipboard if user asked 328 if (r == 2) Utils.copyToClipboard("");329 if (r == 2) ClipboardUtils.copyString(""); 329 330 } 330 331 } -
trunk/src/org/openstreetmap/josm/tools/Utils.java
r10600 r10604 8 8 import java.awt.Color; 9 9 import java.awt.Font; 10 import java.awt.HeadlessException;11 import java.awt.Toolkit;12 10 import java.awt.datatransfer.Clipboard; 13 import java.awt.datatransfer.ClipboardOwner;14 import java.awt.datatransfer.DataFlavor;15 import java.awt.datatransfer.StringSelection;16 11 import java.awt.datatransfer.Transferable; 17 import java.awt.datatransfer.UnsupportedFlavorException;18 12 import java.awt.font.FontRenderContext; 19 13 import java.awt.font.GlyphVector; … … 73 67 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; 74 68 import org.openstreetmap.josm.Main; 69 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 75 70 import org.w3c.dom.Document; 76 71 import org.xml.sax.InputSource; … … 645 640 * @param s string to be copied to clipboard. 646 641 * @return true if succeeded, false otherwise. 647 */ 642 * @deprecated Use {@link ClipboardUtils#copyString(String)}. To be removed end of 2016. 643 */ 644 @Deprecated 648 645 public static boolean copyToClipboard(String s) { 649 try { 650 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(s), new ClipboardOwner() { 651 @Override 652 public void lostOwnership(Clipboard clpbrd, Transferable t) { 653 // Do nothing 654 } 655 }); 656 return true; 657 } catch (IllegalStateException | HeadlessException ex) { 658 Main.error(ex); 659 return false; 660 } 646 return ClipboardUtils.copyString(s); 661 647 } 662 648 … … 666 652 * @return clipboard contents if available, {@code null} otherwise. 667 653 * @since 8429 668 */ 654 * @deprecated Use {@link ClipboardUtils#getClipboardContent(Clipboard)} instead. To be removed end of 2016. 655 */ 656 @Deprecated 669 657 public static Transferable getTransferableContent(Clipboard clipboard) { 670 Transferable t = null; 671 for (int tries = 0; t == null && tries < 10; tries++) { 672 try { 673 t = clipboard.getContents(null); 674 } catch (IllegalStateException e) { 675 // Clipboard currently unavailable. 676 // On some platforms, the system clipboard is unavailable while it is accessed by another application. 677 try { 678 Thread.sleep(1); 679 } catch (InterruptedException ex) { 680 Main.warn("InterruptedException in "+Utils.class.getSimpleName()+" while getting clipboard content"); 681 } 682 } catch (NullPointerException e) { 683 // JDK-6322854: On Linux/X11, NPE can happen for unknown reasons, on all versions of Java 684 Main.error(e); 685 } 686 } 687 return t; 658 return ClipboardUtils.getClipboardContent(clipboard); 688 659 } 689 660 … … 691 662 * Extracts clipboard content as string. 692 663 * @return string clipboard contents if available, {@code null} otherwise. 693 */ 664 * @deprecated Use {@link ClipboardUtils#getClipboardStringContent()}. To be removed end of 2016 665 */ 666 @Deprecated 694 667 public static String getClipboardContent() { 695 try { 696 Transferable t = getTransferableContent(Toolkit.getDefaultToolkit().getSystemClipboard()); 697 if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { 698 return (String) t.getTransferData(DataFlavor.stringFlavor); 699 } 700 } catch (UnsupportedFlavorException | IOException | HeadlessException ex) { 701 Main.error(ex); 702 return null; 703 } 704 return null; 668 return ClipboardUtils.getClipboardStringContent(); 705 669 } 706 670 -
trunk/src/org/openstreetmap/josm/tools/bugreport/DebugTextDisplay.java
r10585 r10604 6 6 import javax.swing.JScrollPane; 7 7 8 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 8 9 import org.openstreetmap.josm.gui.widgets.JosmTextArea; 9 10 import org.openstreetmap.josm.tools.Utils; … … 61 62 62 63 /** 63 * Copies the debug text to the clip pboard. This includes the code tags for trac.64 * Copies the debug text to the clipboard. This includes the code tags for trac. 64 65 * @return <code>true</code> if copy was successful 65 66 */ 66 67 public boolean copyToClippboard() { 67 return Utils.copyToClipboard(String.format(CODE_PATTERN, text));68 return ClipboardUtils.copyString(String.format(CODE_PATTERN, text)); 68 69 } 69 70 -
trunk/test/unit/org/openstreetmap/josm/actions/CopyActionTest.java
r8876 r10604 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertNotNull; 7 import static org.junit.Assert.assertTrue; 8 import static org.junit.Assert.fail; 5 9 10 import java.awt.datatransfer.Clipboard; 11 import java.awt.datatransfer.DataFlavor; 12 import java.awt.datatransfer.StringSelection; 13 import java.awt.datatransfer.UnsupportedFlavorException; 14 import java.io.IOException; 6 15 import java.util.Arrays; 7 import java.util.Collections;8 16 9 import org.junit. BeforeClass;17 import org.junit.Rule; 10 18 import org.junit.Test; 11 import org.openstreetmap.josm.JOSMFixture; 12 import org.openstreetmap.josm.data.osm.Relation; 19 import org.openstreetmap.josm.Main; 20 import org.openstreetmap.josm.data.coor.LatLon; 21 import org.openstreetmap.josm.data.osm.DataSet; 22 import org.openstreetmap.josm.data.osm.Node; 13 23 import org.openstreetmap.josm.data.osm.Way; 24 import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils; 25 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 26 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 27 import org.openstreetmap.josm.testutils.JOSMTestRules; 28 29 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 14 30 15 31 /** … … 17 33 */ 18 34 public class CopyActionTest { 35 private static final class CapturingCopyAction extends CopyAction { 36 private boolean warningShown; 19 37 20 /** 21 * Setup test. 22 */ 23 @BeforeClass 24 public static void setUpBeforeClass() { 25 JOSMFixture.createUnitTestFixture().init(); 38 @Override 39 protected void showEmptySelectionWarning() { 40 warningShown = true; 41 } 26 42 } 27 43 28 44 /** 29 * Test of {@link CopyAction#getCopyString} method for a single way. 45 * We need prefs for this. 46 */ 47 @Rule 48 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 49 public JOSMTestRules test = new JOSMTestRules().preferences().platform().fakeAPI(); 50 51 /** 52 * Test that copy action copies the selected primitive 53 * @throws IOException if an I/O error occurs 54 * @throws UnsupportedFlavorException if the requested data flavor is not supported 30 55 */ 31 56 @Test 32 public void testCopyStringWay() { 33 final Way way = new Way(123L); 34 assertEquals("way 123", CopyAction.getCopyString(Collections.singleton(way))); 57 public void testWarnOnEmpty() throws UnsupportedFlavorException, IOException { 58 Clipboard clipboard = ClipboardUtils.getClipboard(); 59 clipboard.setContents(new StringSelection("test"), null); 60 61 CapturingCopyAction action = new CapturingCopyAction(); 62 63 action.updateEnabledState(); 64 assertFalse(action.isEnabled()); 65 action.actionPerformed(null); 66 assertTrue(action.warningShown); 67 68 Main.getLayerManager().addLayer(new OsmDataLayer(new DataSet(), "test", null)); 69 action.warningShown = false; 70 71 action.updateEnabledState(); 72 assertFalse(action.isEnabled()); 73 action.actionPerformed(null); 74 assertTrue(action.warningShown); 75 76 assertEquals("test", clipboard.getContents(null).getTransferData(DataFlavor.stringFlavor)); 35 77 } 36 78 37 79 /** 38 * Test of {@link CopyAction#getCopyString} method for a way and a relation. 80 * Test that copy action copies the selected primitive 81 * @throws Exception if an error occurs 39 82 */ 40 83 @Test 41 public void testCopyStringWayRelation() { 42 final Way way = new Way(123L); 43 final Relation relation = new Relation(456); 44 assertEquals("way 123,relation 456", CopyAction.getCopyString(Arrays.asList(way, relation))); 45 assertEquals("relation 456,way 123", CopyAction.getCopyString(Arrays.asList(relation, way))); 84 public void testCopySinglePrimitive() throws Exception { 85 DataSet data = new DataSet(); 86 87 Node node1 = new Node(); 88 node1.setCoor(LatLon.ZERO); 89 data.addPrimitive(node1); 90 91 Node node2 = new Node(); 92 node2.setCoor(LatLon.ZERO); 93 data.addPrimitive(node2); 94 Way way = new Way(); 95 way.setNodes(Arrays.asList(node1, node2)); 96 data.addPrimitive(way); 97 data.setSelected(way); 98 99 Main.getLayerManager().addLayer(new OsmDataLayer(data, "test", null)); 100 101 CopyAction action = new CopyAction() { 102 @Override 103 protected void showEmptySelectionWarning() { 104 fail("Selection is not empty."); 105 } 106 }; 107 action.updateEnabledState(); 108 assertTrue(action.isEnabled()); 109 action.actionPerformed(null); 110 111 Object copied = ClipboardUtils.getClipboard().getContents(null).getTransferData(PrimitiveTransferData.DATA_FLAVOR); 112 assertNotNull(copied); 113 assertTrue(copied instanceof PrimitiveTransferData); 114 PrimitiveTransferData ptd = (PrimitiveTransferData) copied; 115 Object[] direct = ptd.getDirectlyAdded().toArray(); 116 assertEquals(1, direct.length); 117 Object[] referenced = ptd.getReferenced().toArray(); 118 assertEquals(2, referenced.length); 46 119 } 47 120 } -
trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferableTest.java
r9711 r10604 5 5 import static org.junit.Assert.assertFalse; 6 6 import static org.junit.Assert.assertTrue; 7 import static org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable.PRIMITIVE_DATA;8 7 9 8 import java.awt.datatransfer.DataFlavor; 10 9 import java.awt.datatransfer.UnsupportedFlavorException; 10 import java.util.Arrays; 11 11 import java.util.Collection; 12 12 import java.util.Collections; 13 import java.util.List; 13 14 14 import org.junit. BeforeClass;15 import org.junit.Rule; 15 16 import org.junit.Test; 16 import org.openstreetmap.josm.JOSMFixture;17 17 import org.openstreetmap.josm.data.osm.Node; 18 import org.openstreetmap.josm.data.osm.NodeData; 18 19 import org.openstreetmap.josm.data.osm.PrimitiveData; 20 import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData; 21 import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData; 22 import org.openstreetmap.josm.testutils.JOSMTestRules; 23 24 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 19 25 20 26 /** … … 22 28 */ 23 29 public class PrimitiveTransferableTest { 30 /** 31 * Prefs to use OSM primitives 32 */ 33 @Rule 34 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 35 public JOSMTestRules test = new JOSMTestRules().preferences(); 24 36 25 37 /** 26 * Setup tests 27 */ 28 @BeforeClass 29 public static void setUpBeforeClass() { 30 JOSMFixture.createUnitTestFixture().init(); 31 } 32 33 /** 34 * Test of {@link PrimitiveTransferable#getTransferDataFlavors()} method. 38 * Test of {@link PrimitiveTransferable#getTransferDataFlavors()} method response order 35 39 */ 36 40 @Test 37 41 public void testGetTransferDataFlavors() { 38 DataFlavor[] flavors = new PrimitiveTransferable(null).getTransferDataFlavors(); 39 assertEquals(2, flavors.length); 40 assertEquals(PRIMITIVE_DATA, flavors[0]); 41 assertEquals(DataFlavor.stringFlavor, flavors[1]); 42 List<DataFlavor> flavors = Arrays.asList(new PrimitiveTransferable(null).getTransferDataFlavors()); 43 int ptd = flavors.indexOf(PrimitiveTransferData.DATA_FLAVOR); 44 int tags = flavors.indexOf(TagTransferData.FLAVOR); 45 int string = flavors.indexOf(DataFlavor.stringFlavor); 46 47 assertTrue(ptd >= 0); 48 assertTrue(tags >= 0); 49 assertTrue(string >= 0); 50 51 assertTrue(ptd < tags); 52 assertTrue(tags < string); 42 53 } 43 54 … … 47 58 @Test 48 59 public void testIsDataFlavorSupported() { 49 assertTrue(new PrimitiveTransferable(null).isDataFlavorSupported(P RIMITIVE_DATA));50 assertFalse(new PrimitiveTransferable(null).isDataFlavorSupported( null));60 assertTrue(new PrimitiveTransferable(null).isDataFlavorSupported(PrimitiveTransferData.DATA_FLAVOR)); 61 assertFalse(new PrimitiveTransferable(null).isDataFlavorSupported(DataFlavor.imageFlavor)); 51 62 } 52 63 … … 57 68 @Test 58 69 public void testGetTransferDataNominal() throws UnsupportedFlavorException { 59 PrimitiveTransferable pt = new PrimitiveTransferable(Collections.singleton(new Node(1))); 60 assertEquals("node 1 # incomplete\n", pt.getTransferData(DataFlavor.stringFlavor)); 61 Collection<PrimitiveData> td = ((PrimitiveTransferable.Data) pt.getTransferData(PRIMITIVE_DATA)).getPrimitiveData(); 70 PrimitiveTransferData data = PrimitiveTransferData.getData(Collections.singleton(new Node(1))); 71 PrimitiveTransferable pt = new PrimitiveTransferable(data); 72 assertEquals("node 1", pt.getTransferData(DataFlavor.stringFlavor)); 73 Collection<PrimitiveData> td = ((PrimitiveTransferData) pt.getTransferData(PrimitiveTransferData.DATA_FLAVOR)).getAll(); 62 74 assertEquals(1, td.size()); 63 assertTrue(td.iterator().next() instanceof PrimitiveData); 75 assertTrue(td.iterator().next() instanceof NodeData); 76 77 78 data = PrimitiveTransferData.getData(Arrays.asList(new Node(1), new Node(2))); 79 pt = new PrimitiveTransferable(data); 80 assertEquals("node 1\nnode 2", pt.getTransferData(DataFlavor.stringFlavor)); 64 81 } 65 82 … … 70 87 @Test(expected = UnsupportedFlavorException.class) 71 88 public void testGetTransferDataError() throws UnsupportedFlavorException { 72 new PrimitiveTransferable(Collections.singleton(new Node(1))).getTransferData(null); 89 PrimitiveTransferData data = PrimitiveTransferData.getData(Collections.singleton(new Node(1))); 90 new PrimitiveTransferable(data).getTransferData(DataFlavor.imageFlavor); 73 91 } 74 92 } -
trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/RelationMemberTransferableTest.java
r9717 r10604 38 38 @Test 39 39 public void testGetTransferDataFlavors() { 40 DataFlavor[] flavors = new RelationMemberTransferable( null).getTransferDataFlavors();40 DataFlavor[] flavors = new RelationMemberTransferable(Collections.<RelationMember>emptyList()).getTransferDataFlavors(); 41 41 assertEquals(2, flavors.length); 42 42 assertEquals(RELATION_MEMBER_DATA, flavors[0]); … … 49 49 @Test 50 50 public void testIsDataFlavorSupported() { 51 assertTrue(new RelationMemberTransferable(null).isDataFlavorSupported(RELATION_MEMBER_DATA)); 52 assertFalse(new RelationMemberTransferable(null).isDataFlavorSupported(null)); 51 RelationMemberTransferable transferable = new RelationMemberTransferable(Collections.<RelationMember>emptyList()); 52 assertTrue(transferable.isDataFlavorSupported(RELATION_MEMBER_DATA)); 53 assertFalse(transferable.isDataFlavorSupported(null)); 53 54 } 54 55 -
trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java
r10113 r10604 2 2 package org.openstreetmap.josm.gui.dialogs.relation.actions; 3 3 4 import org.junit. BeforeClass;4 import org.junit.Rule; 5 5 import org.junit.Test; 6 import org.openstreetmap.josm.JOSMFixture;7 6 import org.openstreetmap.josm.data.osm.DataSet; 8 7 import org.openstreetmap.josm.data.osm.Relation; … … 15 14 import org.openstreetmap.josm.gui.tagging.TagEditorModel; 16 15 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField; 16 import org.openstreetmap.josm.testutils.JOSMTestRules; 17 18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 17 19 18 20 /** … … 20 22 */ 21 23 public class RelationEditorActionsTest { 24 /** 25 * Plattform for tooltips. 26 */ 27 @Rule 28 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 29 public JOSMTestRules test = new JOSMTestRules().preferences().platform().commands(); 22 30 23 31 /** 24 * Setup test. 25 */ 26 @BeforeClass 27 public static void setUpBeforeClass() { 28 JOSMFixture.createUnitTestFixture().init(true); 29 } 30 31 /** 32 * Test all actions with minimal data. 32 * Check that all actions do not crash. 33 33 */ 34 34 @Test … … 58 58 59 59 new CopyMembersAction(memberTableModel, layer, editor).actionPerformed(null); 60 new PasteMembersAction(memberTable Model, layer, editor).actionPerformed(null);60 new PasteMembersAction(memberTable, layer, editor).actionPerformed(null); 61 61 62 62 new DeleteCurrentRelationAction(layer, editor).actionPerformed(null); -
trunk/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
r10588 r10604 12 12 import org.junit.runners.model.InitializationError; 13 13 import org.junit.runners.model.Statement; 14 import org.openstreetmap.josm.JOSMFixture; 14 15 import org.openstreetmap.josm.Main; 15 16 import org.openstreetmap.josm.data.projection.Projections; … … 40 41 private boolean platform; 41 42 private boolean useProjection; 43 private boolean commands; 42 44 private boolean allowMemoryManagerLeaks; 43 45 … … 132 134 public JOSMTestRules projection() { 133 135 useProjection = true; 136 return this; 137 } 138 139 /** 140 * Allow the execution of commands using {@link Main#undoRedo} 141 * @return this instance, for easy chaining 142 */ 143 public JOSMTestRules commands() { 144 commands = true; 134 145 return this; 135 146 } … … 221 232 if (platform) { 222 233 Main.determinePlatformHook(); 234 } 235 236 if (commands) { 237 // TODO: Implement a more selective version of this once Main is restructured. 238 JOSMFixture.createUnitTestFixture().init(true); 223 239 } 224 240 }
Note:
See TracChangeset
for help on using the changeset viewer.