source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerListTransferHandler.java

Last change on this file was 19519, checked in by stoecker, 2 months ago

unify eol-style

  • Property svn:eol-style set to native
File size: 7.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.layer;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.datatransfer.Transferable;
7import java.awt.datatransfer.UnsupportedFlavorException;
8import java.io.Closeable;
9import java.io.IOException;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.List;
13import java.util.stream.Collectors;
14
15import javax.swing.JComponent;
16import javax.swing.JTable;
17import javax.swing.TransferHandler;
18
19import org.openstreetmap.josm.data.osm.DataSet;
20import org.openstreetmap.josm.gui.datatransfer.LayerTransferable;
21import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel;
22import org.openstreetmap.josm.gui.layer.Layer;
23import org.openstreetmap.josm.gui.layer.OsmDataLayer;
24import org.openstreetmap.josm.tools.Logging;
25import org.openstreetmap.josm.tools.Utils;
26
27/**
28 * This class allows the user to transfer layers using drag+drop.
29 * <p>
30 * It supports copy (duplication) of layers, simple moves and linking layers to a new layer manager.
31 *
32 * @author Michael Zangl
33 * @since 10605
34 */
35public class LayerListTransferHandler extends TransferHandler {
36 private static final long serialVersionUID = -5924044609120394316L;
37
38 @Override
39 public int getSourceActions(JComponent c) {
40 if (c instanceof JTable) {
41 LayerListModel tableModel = (LayerListModel) ((JTable) c).getModel();
42 if (!tableModel.getSelectedLayers().isEmpty()) {
43 int actions = MOVE;
44 if (onlyDataLayersSelected(tableModel)) {
45 actions |= COPY;
46 }
47 return actions /* soon: | LINK*/;
48 }
49 }
50 return NONE;
51 }
52
53 private static boolean onlyDataLayersSelected(LayerListModel tableModel) {
54 return tableModel.getSelectedLayers().stream().allMatch(OsmDataLayer.class::isInstance);
55 }
56
57 @Override
58 protected Transferable createTransferable(JComponent c) {
59 if (c instanceof JTable) {
60 LayerListModel tableModel = (LayerListModel) ((JTable) c).getModel();
61 return new LayerTransferable(tableModel.getLayerManager(), tableModel.getSelectedLayers());
62 }
63 return null;
64 }
65
66 @Override
67 public boolean canImport(TransferSupport support) {
68 if (support.isDrop()) {
69 support.setShowDropLocation(true);
70 }
71
72 if (!support.isDataFlavorSupported(LayerTransferable.LAYER_DATA)) {
73 return false;
74 }
75
76 // cannot link yet.
77 return support.getDropAction() != LINK;
78 }
79
80 @Override
81 public boolean importData(TransferSupport support) {
82 try {
83 LayerListModel tableModel = (LayerListModel) ((JTable) support.getComponent()).getModel();
84
85 final Object data = support.getTransferable()
86 .getTransferData(LayerTransferable.LAYER_DATA);
87 final LayerTransferable.Data layers;
88 if (data instanceof LayerTransferable.Data) {
89 layers = (LayerTransferable.Data) data;
90 } else if (data instanceof Closeable) {
91 // We should never hit this code -- Coverity thinks that it is possible for this to be called with a
92 // StringSelection transferable, which is not currently possible with our code. It *could* be done from
93 // a plugin though.
94 Utils.close((Closeable) data);
95 throw new UnsupportedFlavorException(LayerTransferable.LAYER_DATA);
96 } else {
97 throw new UnsupportedFlavorException(LayerTransferable.LAYER_DATA);
98 }
99
100 int dropLocation;
101 if (support.isDrop()) {
102 DropLocation dl = support.getDropLocation();
103 if (dl instanceof JTable.DropLocation) {
104 dropLocation = ((JTable.DropLocation) dl).getRow();
105 } else {
106 dropLocation = 0;
107 }
108 } else {
109 dropLocation = layers.getLayers().get(0).getDefaultLayerPosition().getPosition(layers.getManager());
110 }
111
112 boolean isSameLayerManager = tableModel.getLayerManager() == layers.getManager();
113
114 if (isSameLayerManager && support.getDropAction() == MOVE) {
115 for (Layer layer : layers.getLayers()) {
116 boolean wasBeforeInsert = layers.getManager().getLayers().indexOf(layer) <= dropLocation;
117 if (wasBeforeInsert) {
118 // need to move insertion point one down to preserve order
119 dropLocation--;
120 }
121 layers.getManager().moveLayer(layer, dropLocation);
122 dropLocation++;
123 }
124 } else {
125 List<Layer> layersToUse = layers.getLayers();
126 if (support.getDropAction() == COPY) {
127 layersToUse = createCopy(layersToUse, layers.getManager().getLayers());
128 }
129 for (Layer layer : layersToUse) {
130 layers.getManager().addLayer(layer);
131 layers.getManager().moveLayer(layer, dropLocation);
132 dropLocation++;
133 }
134 }
135
136 return true;
137 } catch (UnsupportedFlavorException e) {
138 Logging.warn("Flavor not supported", e);
139 return false;
140 } catch (IOException e) {
141 Logging.warn("Error while pasting layer", e);
142 return false;
143 }
144 }
145
146 private static List<Layer> createCopy(List<Layer> layersToUse, List<Layer> namesToAvoid) {
147 Collection<String> layerNames = getNames(namesToAvoid);
148 ArrayList<Layer> layers = new ArrayList<>();
149 for (Layer layer : layersToUse) {
150 if (layer instanceof OsmDataLayer) {
151 String newName = suggestNewLayerName(layer.getName(), layerNames);
152 OsmDataLayer newLayer = new OsmDataLayer(new DataSet(((OsmDataLayer) layer).getDataSet()), newName, null);
153 layers.add(newLayer);
154 layerNames.add(newName);
155 }
156 }
157 return layers;
158 }
159
160 /**
161 * Suggests a new name in the form "copy of name"
162 * @param name The base name
163 * @param namesToAvoid The list of layers to use to avoid duplicate names.
164 * @return The new name
165 */
166 public static String suggestNewLayerName(String name, List<Layer> namesToAvoid) {
167 Collection<String> layerNames = getNames(namesToAvoid);
168
169 return suggestNewLayerName(name, layerNames);
170 }
171
172 private static List<String> getNames(List<Layer> namesToAvoid) {
173 return namesToAvoid.stream().map(Layer::getName).collect(Collectors.toList());
174 }
175
176 private static String suggestNewLayerName(String name, Collection<String> layerNames) {
177 // Translators: "Copy of {layer name}"
178 String newName = tr("Copy of {0}", name);
179 int i = 2;
180 while (layerNames.contains(newName)) {
181 // Translators: "Copy {number} of {layer name}"
182 newName = tr("Copy {1} of {0}", name, i);
183 i++;
184 }
185 return newName;
186 }
187}
Note: See TracBrowser for help on using the repository browser.