Skip to content

Commit

Permalink
Prohibit copy-paste from MapWithAI layer to OSM layer
Browse files Browse the repository at this point in the history
Signed-off-by: Taylor Smock <tsmock@fb.com>
  • Loading branch information
tsmock committed May 26, 2021
1 parent b2b22a7 commit 21959b2
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadSourceType;
import org.openstreetmap.josm.plugins.mapwithai.gui.preferences.MapWithAIPreferences;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapPaintUtils;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapWithAICopyProhibit;
import org.openstreetmap.josm.spi.preferences.Config;
import org.openstreetmap.josm.tools.Destroyable;
import org.openstreetmap.josm.tools.Logging;
Expand Down Expand Up @@ -129,6 +130,8 @@ public MapWithAIPlugin(PluginInformation info) {
mapFrameInitialized(null, MainApplication.getMap());
OSMDownloadSource.addDownloadType(new MapWithAIDownloadSourceType());
MainApplication.worker.execute(() -> UpdateProd.doProd(info.mainversion));

destroyables.add(new MapWithAICopyProhibit());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.mapwithai.tools;

import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
import org.openstreetmap.josm.gui.layer.MainLayerManager;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAILayer;
import org.openstreetmap.josm.tools.Destroyable;
import org.openstreetmap.josm.tools.Logging;

import javax.swing.JOptionPane;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.stream.Stream;

import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
import static org.openstreetmap.josm.tools.I18n.tr;

/**
* Keep users from copying from the MapWithAI layer to the OSM layer
*/
public class MapWithAICopyProhibit implements MainLayerManager.ActiveLayerChangeListener, Destroyable {
/**
* Create a new listener to keep copy-paste from happening between the MapWithAI
* layer and the OSM layer
*/
public MapWithAICopyProhibit() {
MainApplication.getLayerManager().addActiveLayerChangeListener(this);
}

@Override
public void activeOrEditLayerChanged(MainLayerManager.ActiveLayerChangeEvent e) {
if (e.getPreviousActiveLayer() instanceof MapWithAILayer && ClipboardUtils.getClipboardContent() != null
&& Stream.of(ClipboardUtils.getClipboardContent().getTransferDataFlavors())
.anyMatch(PrimitiveTransferData.DATA_FLAVOR::equals)) {
PrimitiveTransferData data;
try {
Object tData = ClipboardUtils.getClipboardContent().getTransferData(PrimitiveTransferData.DATA_FLAVOR);
if (tData instanceof PrimitiveTransferData) {
data = (PrimitiveTransferData) tData;
} else {
return;
}
} catch (UnsupportedFlavorException | IOException exception) {
Logging.error(exception);
return;
}
DataSet dataSet = ((MapWithAILayer) e.getPreviousActiveLayer()).getDataSet();
if (data.getAll().stream().anyMatch(pdata -> dataSet.getPrimitiveById(pdata) != null)) {
ClipboardUtils.clear();
Notification notification = new Notification(tr(
"Please use the `MapWithAI: Add Selected Data` command instead of copying and pasting from the MapWithAI Layer."))
.setDuration(Notification.TIME_DEFAULT).setIcon(JOptionPane.INFORMATION_MESSAGE)
.setHelpTopic(ht("Plugin/MapWithAI#BasicUsage"));
GuiHelper.runInEDT(notification::show);
}
}
}

@Override
public void destroy() {
MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.mapwithai.tools;

import mockit.Mock;
import mockit.MockUp;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.openstreetmap.josm.TestUtils;
import org.openstreetmap.josm.actions.CopyAction;
import org.openstreetmap.josm.actions.PasteAction;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.layer.MainLayerManager;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAILayer;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import org.openstreetmap.josm.testutils.mockers.WindowMocker;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Test class for {@link MapWithAICopyProhibit}
*
* @author Taylor Smock
*/
class MapWithAICopyProhibitTest {
private static class BlacklistUtilsMock extends MockUp<BlacklistUtils> {
@Mock
public static boolean isBlacklisted() {
return false;
}
}

// preferences for nodes, main for actions, projection for mapview
@RegisterExtension
JOSMTestRules josmTestRules = new JOSMTestRules().preferences().main().projection();

@Test
void testDestroyable() {
MapWithAICopyProhibit mapWithAICopyProhibit = new MapWithAICopyProhibit();
assertDoesNotThrow(
() -> MainApplication.getLayerManager().removeActiveLayerChangeListener(mapWithAICopyProhibit));
MainLayerManager layerManager = MainApplication.getLayerManager();
IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
() -> layerManager.removeActiveLayerChangeListener(mapWithAICopyProhibit));
assertEquals("Attempted to remove listener that was not in list: " + mapWithAICopyProhibit,
illegalArgumentException.getMessage());
layerManager.addActiveLayerChangeListener(mapWithAICopyProhibit);
mapWithAICopyProhibit.destroy();
illegalArgumentException = assertThrows(IllegalArgumentException.class,
() -> layerManager.removeActiveLayerChangeListener(mapWithAICopyProhibit));
assertEquals("Attempted to remove listener that was not in list: " + mapWithAICopyProhibit,
illegalArgumentException.getMessage());
}

@Test
void testCopyProhibit() {
TestUtils.assumeWorkingJMockit();
new WindowMocker();
new BlacklistUtilsMock();

MapWithAICopyProhibit mapWithAICopyProhibit = new MapWithAICopyProhibit();
MainLayerManager layerManager = MainApplication.getLayerManager();
OsmDataLayer osmDataLayer = new OsmDataLayer(new DataSet(), "TEST", null);
MapWithAILayer mapWithAILayer = new MapWithAILayer(new DataSet(), "TEST", null);
layerManager.addLayer(osmDataLayer);
layerManager.addLayer(mapWithAILayer);
DataSet mapWithAIDataSet = mapWithAILayer.getDataSet();
Node testNode = new Node(LatLon.ZERO);
mapWithAIDataSet.addPrimitive(testNode);
mapWithAIDataSet.setSelected(testNode);
layerManager.setActiveLayer(mapWithAILayer);

CopyAction copyAction = new CopyAction();
copyAction.actionPerformed(null);
PasteAction pasteAction = new PasteAction();

assertEquals(1, mapWithAIDataSet.allPrimitives().size());
pasteAction.actionPerformed(null);
assertEquals(2, mapWithAIDataSet.allPrimitives().size());
pasteAction.actionPerformed(null);
assertEquals(3, mapWithAIDataSet.allPrimitives().size());

layerManager.setActiveLayer(osmDataLayer);
assertEquals(0, osmDataLayer.getDataSet().allPrimitives().size());
for (int i = 0; i < 10; i++) {
pasteAction.actionPerformed(null);
assertEquals(0, osmDataLayer.getDataSet().allPrimitives().size());
}
}
}

0 comments on commit 21959b2

Please sign in to comment.