From 377c68987af7ebcc664c40252db6866de5eb2f0c Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Mon, 27 Apr 2020 09:02:59 -0600 Subject: [PATCH 01/20] Don't redownload images that are already obtained. This fixes #72 (pre-fetching does work, but the code forced a download anyway) Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../plugins/mapillary/cache/CacheUtils.java | 21 ++++++------------- .../mapillary/gui/MapillaryMainDialog.java | 6 ++++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/CacheUtils.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/CacheUtils.java index 79c8f935f..ee498bd05 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/CacheUtils.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/CacheUtils.java @@ -55,21 +55,12 @@ public static void downloadPicture(MapillaryImage img) { * both.) */ public static void downloadPicture(MapillaryImage img, PICTURE pic) { - switch (pic) { - case BOTH: - if (new MapillaryCache(img.getKey(), MapillaryCache.Type.THUMBNAIL).get() == null) - submit(img.getKey(), MapillaryCache.Type.THUMBNAIL, IGNORE_DOWNLOAD); - if (new MapillaryCache(img.getKey(), MapillaryCache.Type.FULL_IMAGE).get() == null) - submit(img.getKey(), MapillaryCache.Type.FULL_IMAGE, IGNORE_DOWNLOAD); - break; - case THUMBNAIL: - submit(img.getKey(), MapillaryCache.Type.THUMBNAIL, IGNORE_DOWNLOAD); - break; - case FULL_IMAGE: - default: - submit(img.getKey(), MapillaryCache.Type.FULL_IMAGE, IGNORE_DOWNLOAD); - break; - } + boolean thumbnail = new MapillaryCache(img.getKey(), MapillaryCache.Type.THUMBNAIL).get() == null && (PICTURE.BOTH.equals(pic) || PICTURE.THUMBNAIL.equals(pic)); + boolean fullImage = new MapillaryCache(img.getKey(), MapillaryCache.Type.FULL_IMAGE).get() == null && (PICTURE.BOTH.equals(pic) || PICTURE.FULL_IMAGE.equals(pic)); + if (thumbnail) + submit(img.getKey(), MapillaryCache.Type.THUMBNAIL, IGNORE_DOWNLOAD); + if (fullImage) + submit(img.getKey(), MapillaryCache.Type.FULL_IMAGE, IGNORE_DOWNLOAD); } /** diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java index 95939ded8..d757e2312 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java @@ -334,7 +334,8 @@ public synchronized void updateImage(boolean fullQuality) { this.thumbnailCache.cancelOutstandingTasks(); this.thumbnailCache = new MapillaryCache(mapillaryImage.getKey(), MapillaryCache.Type.THUMBNAIL); try { - this.thumbnailCache.submit(this, false); + if (this.thumbnailCache.get() == null) + this.thumbnailCache.submit(this, false); } catch (IOException e) { Logging.error(e); } @@ -345,7 +346,8 @@ public synchronized void updateImage(boolean fullQuality) { this.imageCache.cancelOutstandingTasks(); this.imageCache = new MapillaryCache(mapillaryImage.getKey(), MapillaryCache.Type.FULL_IMAGE); try { - this.imageCache.submit(this, false); + if (this.imageCache.get() == null) + this.imageCache.submit(this, false); } catch (IOException e) { Logging.error(e); } From 325c1fe0213128897da8ae2ce0892d8b068a97c6 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 09:28:49 -0600 Subject: [PATCH 02/20] Modify actions to use the PointObjectLayer * Traffic signs and point features use the same base layer * The Point Object layer can now merge with other Point Object layers, if they are of the same type (traffic signs/point features) Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../actions/MapObjectLayerAction.java | 27 ++-- .../actions/MapPointObjectLayerAction.java | 27 ++-- .../mapillary/gui/MapillaryFilterDialog.java | 4 +- .../mapillary/gui/layer/PointObjectLayer.java | 131 +++++++++++------- .../plugins/mapillary/utils/MapillaryURL.java | 2 +- .../actions/MapObjectLayerActionTest.java | 22 +-- 6 files changed, 135 insertions(+), 78 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerAction.java index 78acd66b4..df89293ea 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerAction.java @@ -2,28 +2,33 @@ package org.openstreetmap.josm.plugins.mapillary.actions; import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; import org.openstreetmap.josm.actions.JosmAction; +import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.util.GuiHelper; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapObjectLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; +import org.openstreetmap.josm.tools.Shortcut; public class MapObjectLayerAction extends JosmAction { private static final long serialVersionUID = -8388752916891634738L; + private static final String ACTION_NAME = I18n.marktr("Mapillary traffic signs layer"); + private static final String DESCRIPTION = I18n + .marktr("Displays the layer displaying the traffic sign objects detected by Mapillary"); public MapObjectLayerAction() { super( - I18n.tr("Mapillary object layer"), + I18n.tr(ACTION_NAME), MapillaryPlugin.LOGO.setSize(ImageSizes.DEFAULT), - I18n.tr("Displays the layer displaying the map objects detected by Mapillary"), - null, + I18n.tr(DESCRIPTION), + Shortcut.registerShortcut("mapillary:trafficSignLayer", ACTION_NAME, KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, - "mapillaryObjectLayer", - false - ); + "mapillary:trafficSignLayer", + false); } @Override @@ -32,8 +37,12 @@ public void actionPerformed(ActionEvent e) { // Synchronization lock must be held by EDT thread // See {@link LayerManager#addLayer(org.openstreetmap.josm.gui.layer.Layer, boolean)}. synchronized (MainApplication.getLayerManager()) { - if (!MainApplication.getLayerManager().containsLayer(MapObjectLayer.getInstance())) { - MainApplication.getLayerManager().addLayer(MapObjectLayer.getInstance()); + DataSet followDataSet = MainApplication.getLayerManager().getActiveDataSet(); + if (MainApplication.getLayerManager().getActiveDataSet() != null + && MainApplication.getLayerManager().getLayersOfType(PointObjectLayer.class).parallelStream() + .filter(PointObjectLayer::hasTrafficSigns) + .noneMatch(p -> p.followDataSet != null && p.followDataSet.equals(followDataSet))) { + MainApplication.getLayerManager().addLayer(new PointObjectLayer(true), false); } } }); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapPointObjectLayerAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapPointObjectLayerAction.java index cacb99c26..17a5974c3 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapPointObjectLayerAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapPointObjectLayerAction.java @@ -8,6 +8,7 @@ import java.awt.event.KeyEvent; import org.openstreetmap.josm.actions.JosmAction; +import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.gui.util.GuiHelper; @@ -21,15 +22,16 @@ */ public class MapPointObjectLayerAction extends JosmAction { private static final long serialVersionUID = 5780337309290262545L; - private static final String ACTION_NAME = marktr("Mapillary point object layer"); + private static final String ACTION_NAME = marktr("Mapillary point features layer"); private static final String TOOLTIP = marktr( - "Displays the layer displaying the map point objects detected by Mapillary" - ); + "Displays the layer displaying the map point objects detected by Mapillary"); public MapPointObjectLayerAction() { super( - tr(ACTION_NAME), MapillaryPlugin.LOGO.setSize(ImageSizes.DEFAULT), tr(TOOLTIP), Shortcut.registerShortcut(tr(ACTION_NAME), tr(TOOLTIP), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false, "mapillary:pointObjectLayer", false - ); + tr(ACTION_NAME), MapillaryPlugin.LOGO.setSize(ImageSizes.DEFAULT), tr(TOOLTIP), + Shortcut.registerShortcut("mapillary:pointFeaturesLayer", tr(ACTION_NAME), KeyEvent.CHAR_UNDEFINED, + Shortcut.NONE), + false, "mapillary:pointFeaturesLayer", false); } @Override @@ -40,13 +42,18 @@ public void actionPerformed(ActionEvent e) { // See {@link LayerManager#addLayer(org.openstreetmap.josm.gui.layer.Layer, boolean)}. synchronized (MainApplication.getLayerManager()) { Layer layer = MainApplication.getLayerManager().getActiveLayer(); - MainApplication.getLayerManager().addLayer(new PointObjectLayer(), false); - if (layer != null) { - MainApplication.getLayerManager().setActiveLayer(layer); + DataSet followDataSet = MainApplication.getLayerManager().getActiveDataSet(); + if (MainApplication.getLayerManager().getActiveDataSet() != null + && MainApplication.getLayerManager().getLayersOfType(PointObjectLayer.class).parallelStream() + .filter(PointObjectLayer::hasPointFeatures) + .noneMatch(p -> p.followDataSet != null && p.followDataSet.equals(followDataSet))) { + MainApplication.getLayerManager().addLayer(new PointObjectLayer(false), false); + if (layer != null) { + MainApplication.getLayerManager().setActiveLayer(layer); + } } } - } - ); + }); } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java index 6fc6caec0..b891ec7cd 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java @@ -89,8 +89,8 @@ public final class MapillaryFilterDialog extends ToggleDialog implements Mapilla final JComboBox<OrganizationRecord> organizations = new JComboBox<>(); - private IDatePicker<?> startDate; - private IDatePicker<?> endDate; + private final IDatePicker<?> startDate; + private final IDatePicker<?> endDate; private boolean destroyed; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java index d3fcd4f48..472ea8232 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java @@ -76,6 +76,7 @@ import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.MapViewState.MapViewPoint; import org.openstreetmap.josm.gui.dialogs.LayerListDialog; +import org.openstreetmap.josm.gui.dialogs.LayerListPopup; import org.openstreetmap.josm.gui.layer.AbstractOsmDataLayer; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; @@ -101,9 +102,11 @@ import org.openstreetmap.josm.plugins.mapillary.data.osm.event.FilterEventListener; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryExpertFilterDialog; +import org.openstreetmap.josm.plugins.mapillary.io.download.MapillaryDownloader; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.oauth.OAuthUtils; +import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.HttpClient; @@ -119,14 +122,18 @@ public class PointObjectLayer extends AbstractOsmDataLayer implements DataSourceListener, MouseListener, Listener, HighlightUpdateListener, DataSelectionListener, MapillaryDataListener, LayerChangeListener { private final Collection<DataSource> dataSources = new HashSet<>(); - private static final String NAME = marktr("Mapillary Point Objects"); + private static final String[] NAMES = new String[] { marktr("Mapillary point features"), + marktr("Mapillary traffic signs") }; private static final int HATCHED_SIZE = 15; - private final DataSet followDataSet; + public final DataSet followDataSet; private final FilterEventListener tableModelListener; private static final String PAINT_STYLE_SOURCE = "resource://mapcss/Mapillary.mapcss"; private static MapCSSStyleSource mapcss; private final DataSet data; private final DataSetListenerAdapter dataSetListenerAdapter; + /** If true, display traffic signs. If false, display point objects. */ + private final boolean trafficSigns; + private static final String DETECTIONS = "detections"; /** * a texture for non-downloaded area Copied from OsmDataLayer @@ -139,10 +146,10 @@ public class PointObjectLayer extends AbstractOsmDataLayer private static MapCSSStyleSource getMapCSSStyle() { List<MapCSSStyleSource> styles = MapPaintStyles.getStyles().getStyleSources().parallelStream() - .filter(MapCSSStyleSource.class::isInstance).map(MapCSSStyleSource.class::cast) - .filter(s -> PAINT_STYLE_SOURCE.equals(s.url)).collect(Collectors.toList()); + .filter(MapCSSStyleSource.class::isInstance).map(MapCSSStyleSource.class::cast) + .filter(s -> PAINT_STYLE_SOURCE.equals(s.url)).collect(Collectors.toList()); mapcss = styles.isEmpty() ? new MapCSSStyleSource(PAINT_STYLE_SOURCE, "Mapillary", "Mapillary Point Objects") - : styles.get(0); + : styles.get(0); return mapcss; } @@ -162,15 +169,17 @@ public static void createHatchTexture() { hatched = bi; } - public PointObjectLayer() { - super(NAME); + public PointObjectLayer(boolean trafficSigns) { + super(tr(trafficSigns ? NAMES[1] : NAMES[0])); + String name = trafficSigns ? NAMES[1] : NAMES[0]; + this.trafficSigns = trafficSigns; data = new DataSet(); data.setUploadPolicy(UploadPolicy.BLOCKED); data.setDownloadPolicy(DownloadPolicy.BLOCKED); data.lock(); followDataSet = MainApplication.getLayerManager().getActiveDataSet(); followDataSet.addDataSourceListener(this); - this.setName(NAME + ": " + MainApplication.getLayerManager().getActiveDataLayer().getName()); + this.setName(name + ": " + followDataSet.getName()); MainApplication.worker.execute(() -> followDataSet.getDataSources().forEach(this::getData)); getMapCSSStyle(); if (!MapPaintStyles.getStyles().getStyleSources().contains(mapcss)) { @@ -184,7 +193,7 @@ public PointObjectLayer() { MainApplication.getMap().filterDialog.getFilterModel().addTableModelListener(tableModelListener); tableModelListener.tableChanged(null); - this.data.setName(NAME); + this.data.setName(name); this.dataSetListenerAdapter = new DataSetListenerAdapter(this); data.addDataSetListener(dataSetListenerAdapter); data.addDataSetListener(MultipolygonCache.getInstance()); @@ -198,18 +207,26 @@ public PointObjectLayer() { @Override public void dataSourceChange(DataSourceChangeEvent event) { - if (SwingUtilities.isEventDispatchThread()) { - MainApplication.worker.execute(() -> event.getAdded().forEach(this::getData)); - } else { - event.getAdded().forEach(this::getData); + if (MapillaryDownloader.DOWNLOAD_MODE.OSM_AREA + .equals(MapillaryDownloader.DOWNLOAD_MODE.fromPrefId(MapillaryProperties.DOWNLOAD_MODE.get()))) { + if (SwingUtilities.isEventDispatchThread()) { + MainApplication.worker.execute(() -> event.getAdded().forEach(this::getData)); + } else { + event.getAdded().forEach(this::getData); + } } + String name = trafficSigns ? NAMES[1] : NAMES[0]; + this.setName(name + ": " + followDataSet.getName()); + this.data.setName(name); } public void getData(DataSource dataSource) { if (dataSources.add(dataSource)) { try { data.unlock(); - realGetData(dataSource.bounds, data); + Bounds bound = dataSource.bounds; + realGetData(data, + trafficSigns ? MapillaryURL.APIv3.searchMapObjects(bound) : MapillaryURL.APIv3.searchMapPointObjects(bound)); data.addDataSource(dataSource); } catch (IllegalDataException | IOException e) { Logging.error(e); @@ -221,26 +238,26 @@ public void getData(DataSource dataSource) { } } - private static void realGetData(Bounds bound, DataSet data) throws IllegalDataException, IOException { - URL url = MapillaryURL.APIv3.searchMapPointObjects(bound); + private static void realGetData(DataSet data, URL url) throws IllegalDataException, IOException { + URL currentUrl = url; do { - HttpClient client = HttpClient.create(url); + HttpClient client = HttpClient.create(currentUrl); if (MapillaryUser.getUsername() != null) OAuthUtils.addAuthenticationHeader(client); client.connect(); try (InputStream stream = client.getResponse().getContent()) { DataSet ds = GeoJSONReader.parseDataSet(stream, NullProgressMonitor.INSTANCE); - ds.allPrimitives().parallelStream().filter(p -> p.hasKey("detections")) - .forEach(p -> p.put("detections_num", Integer.toString(p.get("detections").split("detection_key").length))); + ds.allPrimitives().parallelStream().filter(p -> p.hasKey(DETECTIONS)) + .forEach(p -> p.put("detections_num", Integer.toString(p.get(DETECTIONS).split("detection_key").length))); ds.allPrimitives().forEach(p -> p.setModified(false)); synchronized (PointObjectLayer.class) { data.mergeFrom(ds); } - url = MapillaryURL.APIv3.parseNextFromLinkHeaderValue(client.getResponse().getHeaderField("Link")); + currentUrl = MapillaryURL.APIv3.parseNextFromLinkHeaderValue(client.getResponse().getHeaderField("Link")); } finally { client.disconnect(); } - } while (url != null); + } while (currentUrl != null); } @Override @@ -278,7 +295,7 @@ public void paint(final Graphics2D g, final MapView mv, Bounds box) { // paint remainder MapViewPoint anchor = mv.getState().getPointFor(new EastNorth(0, 0)); Rectangle2D anchorRect = new Rectangle2D.Double(anchor.getInView().getX() % HATCHED_SIZE, - anchor.getInView().getY() % HATCHED_SIZE, HATCHED_SIZE, HATCHED_SIZE); + anchor.getInView().getY() % HATCHED_SIZE, HATCHED_SIZE, HATCHED_SIZE); if (hatched != null) { g.setPaint(new TexturePaint(hatched, anchorRect)); } @@ -292,22 +309,22 @@ public void paint(final Graphics2D g, final MapView mv, Bounds box) { AbstractMapRenderer painter = MapRendererFactory.getInstance().createActiveRenderer(g, mv, inactive); painter.enableSlowOperations(mv.getMapMover() == null || !mv.getMapMover().movementInProgress() - || !OsmDataLayer.PROPERTY_HIDE_LABELS_WHILE_DRAGGING.get()); + || !OsmDataLayer.PROPERTY_HIDE_LABELS_WHILE_DRAGGING.get()); painter.render(data, virtual, box); MainApplication.getMap().conflictDialog.paintConflicts(g, mv); } @Override public void selectionChanged(SelectionChangeEvent event) { - OsmPrimitive prim = event.getSelection().parallelStream().filter(p -> p.hasKey("detections")).findFirst() - .orElse(null); + OsmPrimitive prim = event.getSelection().parallelStream().filter(p -> p.hasKey(DETECTIONS)).findFirst() + .orElse(null); if (prim != null && MapillaryLayer.hasInstance()) { - List<Map<String, String>> detections = parseDetections(prim.get("detections")); + List<Map<String, String>> detections = parseDetections(prim.get(DETECTIONS)); MapillaryData mapillaryData = MapillaryLayer.getInstance().getData(); MapillaryImage selectedImage = mapillaryData.getSelectedImage() instanceof MapillaryImage - ? (MapillaryImage) mapillaryData.getSelectedImage() - : null; + ? (MapillaryImage) mapillaryData.getSelectedImage() + : null; List<MapillaryImage> images = getImagesForDetections(mapillaryData, detections); MapillaryImage toSelect = images.isEmpty() ? null : images.get(0); boolean inDetections = selectedImage != null && images.contains(selectedImage); @@ -334,7 +351,7 @@ public void hookUpMapView() { public static List<Map<String, String>> parseDetections(String detectionsValue) { List<Map<String, String>> detections = new ArrayList<>(); try (JsonParser parser = Json - .createParser(new ByteArrayInputStream(detectionsValue.getBytes(StandardCharsets.UTF_8)))) { + .createParser(new ByteArrayInputStream(detectionsValue.getBytes(StandardCharsets.UTF_8)))) { while (parser.hasNext() && JsonParser.Event.START_ARRAY == parser.next()) { JsonArray array = parser.getArray(); for (JsonObject obj : array.getValuesAs(JsonObject.class)) { @@ -357,18 +374,19 @@ public static List<Map<String, String>> parseDetections(String detectionsValue) private static List<MapillaryImage> getImagesForDetections(MapillaryData data, List<Map<String, String>> detections) { return detections.stream().filter(m -> m.containsKey("image_key")).map(m -> m.get("image_key")).map(data::getImage) - .collect(Collectors.toList()); + .collect(Collectors.toList()); } @Override public Action[] getMenuEntries() { List<Action> actions = new ArrayList<>(); actions.addAll(Arrays.asList(LayerListDialog.getInstance().createActivateLayerAction(this), - LayerListDialog.getInstance().createShowHideLayerAction(), - LayerListDialog.getInstance().createDeleteLayerAction(), SeparatorLayerAction.INSTANCE, - LayerListDialog.getInstance().createMergeLayerAction(this))); + LayerListDialog.getInstance().createShowHideLayerAction(), + LayerListDialog.getInstance().createDeleteLayerAction(), SeparatorLayerAction.INSTANCE, + LayerListDialog.getInstance().createMergeLayerAction(this))); actions.addAll(Arrays.asList(SeparatorLayerAction.INSTANCE, new RenameLayerAction(getAssociatedFile(), this), - SeparatorLayerAction.INSTANCE, new RequestDataAction(followDataSet))); + SeparatorLayerAction.INSTANCE, new RequestDataAction(followDataSet), SeparatorLayerAction.INSTANCE, + new LayerListPopup.InfoAction(this))); return actions.toArray(new Action[0]); } @@ -387,7 +405,7 @@ public void actionPerformed(ActionEvent e) { String bbox = "?bbox=" + String.join(";", data.getDataSourceBounds().stream() - .map(Bounds::toBBox).map(b -> b.toStringCSV(",")).collect(Collectors.toList())); + .map(Bounds::toBBox).map(b -> b.toStringCSV(",")).collect(Collectors.toList())); OpenBrowser.displayUrl("https://mapillary.github.io/mapillary_solutions/data-request" + bbox); } } @@ -433,8 +451,8 @@ public String getToolTipText() { int rels = counter.relations - counter.deletedRelations; StringBuilder tooltip = new StringBuilder("<html>").append(trn("{0} node", "{0} nodes", nodes, nodes)) - .append("<br>").append(trn("{0} way", "{0} ways", ways, ways)).append("<br>") - .append(trn("{0} relation", "{0} relations", rels, rels)); + .append("<br>").append(trn("{0} way", "{0} ways", ways, ways)).append("<br>") + .append(trn("{0} relation", "{0} relations", rels, rels)); File f = getAssociatedFile(); if (f != null) { @@ -450,16 +468,22 @@ public void mergeFrom(Layer from) { DataSet fromData = ((PointObjectLayer) from).getDataSet(); final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Merging layers")); monitor.setCancelable(false); - fromData.unlock(); - data.mergeFrom(fromData, monitor); - fromData.lock(); - monitor.close(); + try { + fromData.unlock(); + data.unlock(); + data.mergeFrom(fromData, monitor); + } finally { + fromData.lock(); + data.lock(); + monitor.close(); + ((PointObjectLayer) from).destroy(); + } } } @Override public boolean isMergable(Layer other) { - return other instanceof PointObjectLayer; + return other instanceof PointObjectLayer && this.trafficSigns == ((PointObjectLayer) other).trafficSigns; } @Override @@ -476,11 +500,11 @@ public Object getInfoComponent() { p.add(new JLabel(tr("{0} consists of:", getName())), GBC.eol()); p.add(new JLabel(nodeText, ImageProvider.get("data", "node"), SwingConstants.HORIZONTAL), - GBC.eop().insets(15, 0, 0, 0)); + GBC.eop().insets(15, 0, 0, 0)); p.add(new JLabel(wayText, ImageProvider.get("data", "way"), SwingConstants.HORIZONTAL), - GBC.eop().insets(15, 0, 0, 0)); + GBC.eop().insets(15, 0, 0, 0)); p.add(new JLabel(relationText, ImageProvider.get("data", "relation"), SwingConstants.HORIZONTAL), - GBC.eop().insets(15, 0, 0, 0)); + GBC.eop().insets(15, 0, 0, 0)); return p; } @@ -582,10 +606,23 @@ public void selectedImageChanged(MapillaryAbstractImage oldImage, MapillaryAbstr if (newImage instanceof MapillaryImage) { MapillaryImage image = (MapillaryImage) newImage; Collection<INode> nodes = image.getDetections().parallelStream().map(ImageDetection::getKey).flatMap( - d -> data.getNodes().parallelStream().filter(n -> n.hasKey("detections") && n.get("detections").contains(d)) - ).collect(Collectors.toList()); + d -> data.getNodes().parallelStream().filter(n -> n.hasKey(DETECTIONS) && n.get(DETECTIONS).contains(d))) + .collect(Collectors.toList()); data.setSelected(nodes); } } + /** + * @return true if this layer has traffic signs + */ + public boolean hasTrafficSigns() { + return this.trafficSigns; + } + + /** + * @return true if this layer has point features (does not include traffic signs) + */ + public boolean hasPointFeatures() { + return !this.trafficSigns; + } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryURL.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryURL.java index a37e1da94..cacca053e 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryURL.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryURL.java @@ -106,7 +106,7 @@ public static URL searchMapPointObjects(final Bounds bounds) { } private static String getEnabledLayers() { - return String.join(",", Arrays.asList(TRAFFIC_SIGN_LAYER, POINT_FEATURES_LAYER, LINE_FEATURES_LAYER)); + return String.join(",", Arrays.asList(POINT_FEATURES_LAYER, LINE_FEATURES_LAYER)); } private static String getDetectionLayers() { diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerActionTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerActionTest.java index 7c47ffc0f..bb1a999e7 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerActionTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/actions/MapObjectLayerActionTest.java @@ -3,30 +3,34 @@ import static org.junit.Assert.assertEquals; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.gui.MainApplication; +import org.openstreetmap.josm.gui.layer.OsmDataLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil.MapillaryTestRules; import org.openstreetmap.josm.testutils.JOSMTestRules; public class MapObjectLayerActionTest { @Rule - public JOSMTestRules rules = new MapillaryTestRules(); - - @Before - public void resetLayers() { - MainApplication.getLayerManager().getLayers().parallelStream().forEach(l -> MainApplication.getLayerManager().removeLayer(l)); - } + public JOSMTestRules rules = new MapillaryTestRules().main().projection(); @Test public void testAction() { assertEquals(0, MainApplication.getLayerManager().getLayers().size()); new MapObjectLayerAction().actionPerformed(null); - assertEquals(1, MainApplication.getLayerManager().getLayers().size()); + assertEquals(0, MainApplication.getLayerManager().getLayers().size()); + MainApplication.getLayerManager().addLayer(new OsmDataLayer(new DataSet(), "Test", null)); + new MapObjectLayerAction().actionPerformed(null); + assertEquals(2, MainApplication.getLayerManager().getLayers().size()); + new MapObjectLayerAction().actionPerformed(null); + assertEquals(2, MainApplication.getLayerManager().getLayers().size()); + MainApplication.getLayerManager() + .setActiveLayer(MainApplication.getLayerManager().getLayersOfType(PointObjectLayer.class).get(0)); new MapObjectLayerAction().actionPerformed(null); - assertEquals(1, MainApplication.getLayerManager().getLayers().size()); + assertEquals(2, MainApplication.getLayerManager().getLayers().size()); } } From e055443d23441b02be771327031cb33e1e205e58 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 10:20:12 -0600 Subject: [PATCH 03/20] Remove previous map object layer implementation. This is due to PointObjectLayer being a bit more performant when images are missing. Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../plugins/mapillary/MapillaryPlugin.java | 4 +- .../mapillary/gui/layer/MapObjectLayer.java | 241 ------------------ .../download/MapObjectDownloadRunnable.java | 94 ------- ...yerTest.java => PointObjectLayerTest.java} | 53 ++-- 4 files changed, 27 insertions(+), 365 deletions(-) delete mode 100644 src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayer.java delete mode 100644 src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapObjectDownloadRunnable.java rename test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/{MapObjectLayerTest.java => PointObjectLayerTest.java} (65%) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java index bb2814f47..4e06499ef 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java @@ -40,7 +40,6 @@ import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryExpertFilterDialog; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoHelpPopup; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoPanel; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapObjectLayer; import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; @@ -185,8 +184,7 @@ public void destroy() { menu.editMenu, menu.fileMenu, menu.windowMenu)) { clearMenues(jmenu); } - for (Class<? extends Layer> layerClazz : Arrays.asList(MapillaryLayer.class, MapObjectLayer.class, - PointObjectLayer.class)) { + for (Class<? extends Layer> layerClazz : Arrays.asList(MapillaryLayer.class, PointObjectLayer.class)) { MainApplication.getLayerManager().getLayersOfType(layerClazz) .forEach(layer -> MainApplication.getLayerManager().removeLayer(layer)); } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayer.java deleted file mode 100644 index c27eeaf29..000000000 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayer.java +++ /dev/null @@ -1,241 +0,0 @@ -// License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui.layer; - -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.ImageIcon; - -import org.openstreetmap.josm.data.Bounds; -import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; -import org.openstreetmap.josm.gui.MapView; -import org.openstreetmap.josm.gui.NavigatableComponent; -import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener; -import org.openstreetmap.josm.gui.layer.Layer; -import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; -import org.openstreetmap.josm.plugins.mapillary.io.download.MapObjectDownloadRunnable; -import org.openstreetmap.josm.plugins.mapillary.model.MapObject; -import org.openstreetmap.josm.plugins.mapillary.utils.ImageUtil; -import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; -import org.openstreetmap.josm.tools.I18n; -import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; -import org.openstreetmap.josm.tools.Logging; - -public final class MapObjectLayer extends Layer implements ZoomChangeListener { - - public enum STATUS { - DOWNLOADING(I18n.marktr("Downloading map objects…"), Color.YELLOW), - COMPLETE(I18n.marktr("All map objects loaded."), Color.GREEN), - INCOMPLETE(I18n.marktr("Too many map objects, zoom in to see all."), Color.ORANGE), - FAILED(I18n.marktr("Downloading map objects failed!"), Color.RED); - - private final int colorValue; - public final String message; - - STATUS(final String message, final Color color) { - this.colorValue = color.getRGB(); - this.message = message; - } - - /** - * Note: The color is stored as int and each time returned as new {@link Color} instance, - * because the class {@link Color} is not strictly immutable. - * @return the color associated with the current status - */ - public Color getColor() { - return new Color(colorValue, true); - } - } - - private static MapObjectLayer instance; - - private STATUS status = STATUS.COMPLETE; - private MapObjectDownloadRunnable downloadRunnable; - private MapObjectDownloadRunnable nextDownloadRunnable; - private final Collection<MapObject> objects = new HashSet<>(); - - private final Map<String, ImageIcon> scaledIcons = new HashMap<>(); - - private MapObjectLayer() { - super(I18n.tr("Mapillary objects")); - NavigatableComponent.addZoomChangeListener(this); - MapillaryProperties.MAPOBJECT_ICON_SIZE.addListener(val -> { - scaledIcons.clear(); - finishDownload(false); - }); - zoomChanged(); - } - - private static void clearInstance() { - synchronized (MapObjectLayer.class) { - instance = null; - } - } - - public static MapObjectLayer getInstance() { - synchronized (MapObjectLayer.class) { - if (instance == null) { - instance = new MapObjectLayer(); - } - return instance; - } - } - - public boolean isDownloadRunnableScheduled() { - synchronized (this) { - return nextDownloadRunnable != null; - } - } - - public void finishDownload(boolean replaceMapObjects) { - synchronized (this) { - final MapObjectDownloadRunnable currentRunnable = downloadRunnable; - if (currentRunnable != null) { - synchronized (objects) { - if (replaceMapObjects) { - objects.clear(); - } - objects.addAll(currentRunnable.getMapObjects()); - } - } - downloadRunnable = null; - if (nextDownloadRunnable != null) { - downloadRunnable = nextDownloadRunnable; - nextDownloadRunnable = null; - new Thread(downloadRunnable, "downloadMapObjects").start(); - } - } - new Thread(() -> { - synchronized (objects) { - for (MapObject object : objects) { - if (!scaledIcons.containsKey(object.getValue())) { - ImageIcon icon = MapObject.getIcon(object.getValue()); - if (icon != null) { - scaledIcons.put( - object.getValue(), - ImageUtil.scaleImageIcon(icon, MapillaryProperties.MAPOBJECT_ICON_SIZE.get()) - ); - } - } - } - } - invalidate(); - }, "downloadMapObjectIcons").start(); - } - - public int getObjectCount() { - return objects.size(); - } - - public void setStatus(STATUS status) { - this.status = status; - invalidate(); - } - - @Override - public void paint(Graphics2D g, MapView mv, Bounds bbox) { - final long startTime = System.currentTimeMillis(); - final Collection<MapObject> displayedObjects = new HashSet<>(); - synchronized (this) { - final MapObjectDownloadRunnable currentRunnable = downloadRunnable; - if (currentRunnable != null) { - displayedObjects.addAll(currentRunnable.getMapObjects()); - } - } - displayedObjects.addAll(objects); - - for (MapObject object : displayedObjects) { - final ImageIcon icon = scaledIcons.get(object.getValue()); - if (icon != null) { - final Point p = mv.getPoint(object.getCoordinate()); - g.drawImage( - icon.getImage(), - p.x - icon.getIconWidth() / 2, - p.y - icon.getIconHeight() / 2, - null - ); - } - } - - final STATUS currentStatus = status; - g.setFont(g.getFont().deriveFont(Font.PLAIN).deriveFont(12f)); - g.setColor(currentStatus.getColor()); - final FontMetrics fm = g.getFontMetrics(); - g.fillRect(0, mv.getHeight() - fm.getAscent() - fm.getDescent(), fm.stringWidth(I18n.tr(currentStatus.message)), fm.getAscent() + fm.getDescent()); - g.setColor(Color.BLACK); - g.drawString(I18n.tr(currentStatus.message), 0, mv.getHeight() - fm.getDescent()); - Logging.debug("{0} painted in {1} milliseconds.", MapObjectLayer.class.getName(), System.currentTimeMillis() - startTime); - } - - @Override - public Icon getIcon() { - return MapillaryPlugin.LOGO.setSize(ImageSizes.LAYER).get(); - } - - @Override - public String getToolTipText() { - return I18n.tr("Displays objects detected by Mapillary from their street view imagery"); - } - - @Override - public void mergeFrom(Layer from) { - // Not mergeable - } - - @Override - public boolean isMergable(Layer other) { - return false; - } - - @Override - public void visitBoundingBox(BoundingXYVisitor v) { - // Unused method enforced by the Layer class - } - - @Override - public Object getInfoComponent() { - return null; - } - - @Override - public Action[] getMenuEntries() { - return new Action[0]; - } - - public void scheduleDownload(final Bounds bounds) { - synchronized(this) { - if (downloadRunnable == null) { - downloadRunnable = new MapObjectDownloadRunnable(this, bounds); - new Thread(downloadRunnable).start(); - } else { - nextDownloadRunnable = new MapObjectDownloadRunnable(this, bounds); - } - } - } - - /* (non-Javadoc) - * @see org.openstreetmap.josm.gui.layer.Layer#destroy() - */ - @Override - public synchronized void destroy() { - clearInstance(); - super.destroy(); - } - - @Override - public void zoomChanged() { - MapView mv = MapillaryPlugin.getMapView(); - if (mv != null) { - scheduleDownload(mv.getState().getViewArea().getLatLonBoundsBox()); - } - } -} diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapObjectDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapObjectDownloadRunnable.java deleted file mode 100644 index fa6440ffc..000000000 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapObjectDownloadRunnable.java +++ /dev/null @@ -1,94 +0,0 @@ -// License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.io.download; - -import java.io.IOException; -import java.net.URL; -import java.util.Collection; -import java.util.HashSet; -import java.util.function.Function; - -import javax.json.Json; -import javax.json.JsonException; -import javax.json.JsonReader; - -import org.openstreetmap.josm.data.Bounds; -import org.openstreetmap.josm.gui.Notification; -import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapObjectLayer; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapObjectLayer.STATUS; -import org.openstreetmap.josm.plugins.mapillary.model.MapObject; -import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; -import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL.APIv3; -import org.openstreetmap.josm.plugins.mapillary.utils.api.JsonDecoder; -import org.openstreetmap.josm.plugins.mapillary.utils.api.JsonMapObjectDecoder; -import org.openstreetmap.josm.tools.HttpClient; -import org.openstreetmap.josm.tools.I18n; -import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; -import org.openstreetmap.josm.tools.Logging; - -public class MapObjectDownloadRunnable implements Runnable { - private final Bounds bounds; - private final MapObjectLayer layer; - private static final Function<Bounds, URL> URL_GEN = APIv3::searchMapObjects; - - private final Collection<MapObject> result = new HashSet<>(); - - public MapObjectDownloadRunnable(final MapObjectLayer layer, final Bounds bounds) { - this.bounds = bounds; - this.layer = layer; - } - - public Collection<MapObject> getMapObjects() { - return result; - } - - @Override - public void run() { - layer.setStatus(MapObjectLayer.STATUS.DOWNLOADING); - URL nextURL = URL_GEN.apply(bounds); - try { - while (nextURL != null && result.size() < MapillaryProperties.MAX_MAPOBJECTS.get() && !layer.isDownloadRunnableScheduled()) { - final int prevResultSize = result.size(); - final long startTime = System.currentTimeMillis(); - final HttpClient client = HttpClient.create(nextURL); - client.connect(); - try (JsonReader reader = Json.createReader(client.getResponse().getContentReader())) { - result.addAll(JsonDecoder.decodeFeatureCollection( - reader.readObject(), - JsonMapObjectDecoder::decodeMapObject - )); - } - layer.invalidate(); - BoundsDownloadRunnable.logConnectionInfo(client, String.format( - "%d map objects in %.2f s", - result.size() - prevResultSize, - (System.currentTimeMillis() - startTime) / 1000f - )); - nextURL = APIv3.parseNextFromLinkHeaderValue(client.getResponse().getHeaderField("Link")); - } - } catch (IOException | JsonException e) { - String message = I18n.tr("{0}\nCould not read map objects from URL\n{1}!", e.getLocalizedMessage(), nextURL.toString()); - Logging.log(Logging.LEVEL_WARN, message, e); - new Notification(message) - .setIcon(MapillaryPlugin.LOGO.setSize(ImageSizes.LARGEICON).get()) - .setDuration(Notification.TIME_LONG) - .show(); - layer.setStatus(STATUS.FAILED); - layer.finishDownload(false); - return; - } - if (nextURL == null) { - layer.setStatus(STATUS.COMPLETE); - } else { - layer.setStatus(result.size() >= MapillaryProperties.MAX_MAPOBJECTS.get() ? STATUS.INCOMPLETE : STATUS.DOWNLOADING); - } - layer.finishDownload(nextURL == null || result.size() >= MapillaryProperties.MAX_MAPOBJECTS.get()); - try { - Thread.sleep(1000); // Buffer between downloads to avoid too many downloads when e.g. panning around - } catch (InterruptedException e) { - Logging.debug(e); - Thread.currentThread().interrupt(); - } - } - -} diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayerTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayerTest.java similarity index 65% rename from test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayerTest.java rename to test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayerTest.java index df6b533f4..e7adb141f 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapObjectLayerTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayerTest.java @@ -9,7 +9,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import java.io.IOException; import java.net.URISyntaxException; @@ -20,32 +19,43 @@ import com.github.tomakehurst.wiremock.junit.WireMockRule; import com.github.tomakehurst.wiremock.matching.EqualToPattern; +import org.awaitility.Awaitility; +import org.awaitility.Durations; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.openstreetmap.josm.data.Bounds; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapObjectLayer.STATUS; +import org.openstreetmap.josm.data.DataSource; +import org.openstreetmap.josm.data.osm.DataSet; +import org.openstreetmap.josm.gui.MainApplication; +import org.openstreetmap.josm.gui.layer.OsmDataLayer; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil.MapillaryTestRules; import org.openstreetmap.josm.testutils.JOSMTestRules; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; -public class MapObjectLayerTest { +public class PointObjectLayerTest { @Rule public WireMockRule wmRule = new WireMockRule(wireMockConfig().dynamicPort()); @Rule - public JOSMTestRules rules = new MapillaryTestRules().timeout(20000); + public JOSMTestRules rules = new MapillaryTestRules().timeout(20000).projection().main(); private static String oldBaseUrl; + private PointObjectLayer instance; + private OsmDataLayer osm; + @Before public void setUp() { oldBaseUrl = TestUtil.getApiV3BaseUrl(); TestUtil.setAPIv3BaseUrl("http://localhost:" + wmRule.port() + "/"); + osm = new OsmDataLayer(new DataSet(), "Test", null); + MainApplication.getLayerManager().addLayer(osm); + instance = new PointObjectLayer(false); } @After @@ -54,13 +64,7 @@ public void cleanUp() throws IllegalArgumentException { } @Test - public void testStatusEnum() { - assertEquals(4, STATUS.values().length); - assertEquals(STATUS.COMPLETE, STATUS.valueOf("COMPLETE")); - } - - @Test - public void testScheduleDownload() throws InterruptedException, URISyntaxException, IOException { + public void testScheduleDownload() throws URISyntaxException, IOException { stubFor( get(urlMatching("/map_features\\?.+")) .withQueryParam("client_id", new EqualToPattern("UTZhSnNFdGpxSEFFREUwb01GYzlXZzpjNGViMzQxMTIzMjY0MjZm")) @@ -69,41 +73,36 @@ public void testScheduleDownload() throws InterruptedException, URISyntaxExcepti aResponse() .withStatus(200) .withBody(Files.readAllBytes( - Paths.get(MapObjectLayerTest.class.getResource("/api/v3/responses/searchMapObjects.json").toURI()) - )) - ) - ); + Paths.get(PointObjectLayerTest.class.getResource("/api/v3/responses/searchMapObjects.json").toURI()))))); - MapObjectLayer.getInstance().scheduleDownload(new Bounds(1,1,1,1)); + osm.getDataSet().addDataSource(new DataSource(new Bounds(1, 1, 1, 1), "1/1/1/1")); // Wait for a maximum of 5 sec for a result - for (int i = 0; MapObjectLayer.getInstance().getObjectCount() <= 0 && i < 50; i++) { - Thread.sleep(100); - } - assertEquals(1, MapObjectLayer.getInstance().getObjectCount()); + Awaitility.await().atMost(Durations.FIVE_SECONDS).until(() -> instance.getDataSet().allPrimitives().size() != 0); + assertEquals(1, instance.getDataSet().allPrimitives().size()); } @Test public void testGetIcon() { - Icon i = MapObjectLayer.getInstance().getIcon(); + Icon i = instance.getIcon(); assertEquals(ImageSizes.LAYER.getAdjustedHeight(), i.getIconHeight()); assertEquals(ImageSizes.LAYER.getAdjustedWidth(), i.getIconWidth()); } @Test public void testMergable() { - assertFalse(MapObjectLayer.getInstance().isMergable(null)); - MapObjectLayer.getInstance().mergeFrom(null); + assertFalse(instance.isMergable(null)); + instance.mergeFrom(null); } @Test public void testInfoComponent() { - assertNull(MapObjectLayer.getInstance().getInfoComponent()); + assertNotNull(instance.getInfoComponent()); } @Test public void testTrivialMethods() { - assertNotNull(MapObjectLayer.getInstance().getToolTipText()); - MapObjectLayer.getInstance().visitBoundingBox(null); - assertEquals(0, MapObjectLayer.getInstance().getMenuEntries().length); + assertNotNull(instance.getToolTipText()); + instance.visitBoundingBox(null); + assertEquals(11, instance.getMenuEntries().length); } } From 823573c411b36b5e25adf1fc31644341d106442b Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 10:28:42 -0600 Subject: [PATCH 04/20] Move most dialogs into `mapillary/gui/dialog` Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../josm/plugins/mapillary/MapillaryLayer.java | 4 ++-- .../josm/plugins/mapillary/MapillaryPlugin.java | 6 +++--- .../plugins/mapillary/actions/MapillaryExportAction.java | 2 +- .../actions/MapillarySubmitCurrentChangesetAction.java | 2 +- .../plugins/mapillary/actions/MapillaryUploadAction.java | 2 +- .../josm/plugins/mapillary/actions/MapillaryWalkAction.java | 2 +- .../gui/{ => dialog}/MapillaryChangesetDialog.java | 3 ++- .../mapillary/gui/{ => dialog}/MapillaryExportDialog.java | 2 +- .../mapillary/gui/{ => dialog}/MapillaryFilterDialog.java | 6 ++++-- .../mapillary/gui/{ => dialog}/MapillaryHistoryDialog.java | 4 +++- .../mapillary/gui/{ => dialog}/MapillaryUploadDialog.java | 2 +- .../mapillary/gui/{ => dialog}/MapillaryWalkDialog.java | 2 +- .../io/download/MapillarySquareDownloadRunnable.java | 2 +- 13 files changed, 22 insertions(+), 17 deletions(-) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryChangesetDialog.java (97%) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryExportDialog.java (98%) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryFilterDialog.java (98%) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryHistoryDialog.java (97%) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryUploadDialog.java (97%) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/{ => dialog}/MapillaryWalkDialog.java (96%) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java index d5880a4dc..1ff947da0 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java @@ -59,9 +59,9 @@ import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; import org.openstreetmap.josm.gui.layer.OsmDataLayer; import org.openstreetmap.josm.plugins.mapillary.cache.CacheUtils; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryChangesetDialog; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterDialog; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryChangesetDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryFilterDialog; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandDelete; import org.openstreetmap.josm.plugins.mapillary.io.download.MapillaryDownloader; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java index 4e06499ef..acdc11531 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java @@ -32,12 +32,12 @@ import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryUploadAction; import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryWalkAction; import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryZoomAction; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryChangesetDialog; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterDialog; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryHistoryDialog; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryPreferenceSetting; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryChangesetDialog; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryExpertFilterDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryFilterDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryHistoryDialog; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoHelpPopup; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoPanel; import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java index edf990aaf..ed3ec93e0 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java @@ -22,7 +22,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryExportDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryExportDialog; import org.openstreetmap.josm.plugins.mapillary.io.export.MapillaryExportManager; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java index c020a7a30..233a3d016 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java @@ -20,7 +20,7 @@ import org.openstreetmap.josm.gui.Notification; import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryLocationChangeset; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryChangesetDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryChangesetDialog; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL.APIv3; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryUtils; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java index fa8af0abc..a23986ec0 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java @@ -13,7 +13,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryUploadDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryUploadDialog; import org.openstreetmap.josm.plugins.mapillary.oauth.UploadUtils; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.ImageProvider; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java index 55de425ae..61123621c 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java @@ -18,7 +18,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryWalkDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryWalkDialog; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryChangesetDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java similarity index 97% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryChangesetDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java index e413ffb03..fd9d9af83 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryChangesetDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; @@ -30,6 +30,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryLocationChangeset; import org.openstreetmap.josm.plugins.mapillary.actions.MapillarySubmitCurrentChangesetAction; +import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryImageTreeCellRenderer; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.MapillaryCommand; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryChangesetListener; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java similarity index 98% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java index 10d43d986..0647af825 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java similarity index 98% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java index b891ec7cd..d00b42bff 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; @@ -45,7 +45,9 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.data.mapillary.OrganizationRecord; import org.openstreetmap.josm.plugins.mapillary.data.mapillary.OrganizationRecord.OrganizationRecordListener; -import org.openstreetmap.josm.plugins.mapillary.gui.dialog.TrafficSignFilter; +import org.openstreetmap.josm.plugins.mapillary.gui.IDatePicker; +import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterChooseSigns; +import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryPreferenceSetting; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryLoginListener; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryHistoryDialog.java similarity index 97% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryHistoryDialog.java index ec12a24e3..6caea3f7f 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryHistoryDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; @@ -31,6 +31,8 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.SideButton; import org.openstreetmap.josm.gui.dialogs.ToggleDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryImageTreeCellRenderer; +import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryPreferenceSetting; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecordListener; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandDelete; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryUploadDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java similarity index 97% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryUploadDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java index ec2c8d68b..7b4dc9b30 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryUploadDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryWalkDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryWalkDialog.java similarity index 96% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryWalkDialog.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryWalkDialog.java index 64085993e..bb3bc4c03 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryWalkDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryWalkDialog.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary.gui; +package org.openstreetmap.josm.plugins.mapillary.gui.dialog; import static org.openstreetmap.josm.tools.I18n.tr; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java index 74b357734..89397cc58 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java @@ -7,8 +7,8 @@ import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; -import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterDialog; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryFilterDialog; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryUtils; import org.openstreetmap.josm.plugins.mapillary.utils.PluginState; import org.openstreetmap.josm.tools.Logging; From 1a78c8318a92e39ddc523c6f8e9aef6e264d3c16 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 10:41:04 -0600 Subject: [PATCH 05/20] Remove minimum detections UI component Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../gui/dialog/TrafficSignFilter.java | 47 ++++--------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/TrafficSignFilter.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/TrafficSignFilter.java index e8f17865e..82a1df142 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/TrafficSignFilter.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/TrafficSignFilter.java @@ -74,8 +74,8 @@ public TrafficSignFilter() { layers.setLayout(new FlowLayout(FlowLayout.LEFT)); layers.add(new JLabel(I18n.tr("Layer"))); for (String[] layer : Arrays.asList( - new String[] { "trafficsigns", I18n.marktr("Traffic Signs") }, new String[] { "points", I18n.marktr("Point Objects") } - )) { + new String[] { "trafficsigns", I18n.marktr("Traffic Signs") }, + new String[] { "points", I18n.marktr("Point Objects") })) { JCheckBox lbox = new JCheckBox(I18n.tr(layer[1])); layers.add(lbox); lbox.addItemListener(TrafficSignFilter::updateLayers); @@ -84,23 +84,6 @@ public TrafficSignFilter() { } add(layers); - /* Filter minimum detections */ - add(new JLabel(I18n.tr("Minimum object detections"))); - JSpinner minDetections = new JSpinner(); - minDetections.setModel(new SpinnerNumberModel(0, 0, 100, 1)); - add(minDetections, GBC.eol()); - Filter minDetectionFilter = MapillaryExpertFilterDialog.getInstance().getFilterModel().getFilters().parallelStream() - .filter(p -> p.text.contains("min_detections")).findFirst().orElseGet(() -> { - Filter filter = new Filter(); - filter.enable = false; - filter.hiding = true; - filter.text = "min_detections < 0"; - MapillaryExpertFilterDialog.getInstance().getFilterModel().addFilter(filter); - return filter; - }); - minDetections.addChangeListener(l -> updateMinDetectionFilter(minDetections, minDetectionFilter)); - /* End filter minimum detections */ - /* Filter signs */ filterField = new FilterField().filter(this::filterButtons); filterField.setToolTipText(I18n.tr("Filter Mapillary Detections")); @@ -169,9 +152,8 @@ private void updateDetectionPage(int difference) { private void updateShown(SpinnerNumberModel model) { buttons.parallelStream().forEach(i -> SwingUtilities.invokeLater(() -> i.setVisible(false))); buttons.stream().filter(i -> i.isFiltered(filterField.getText())).skip( - detectionPage * model.getNumber().longValue() - ).limit(model.getNumber().longValue() - ).forEach(i -> SwingUtilities.invokeLater(() -> i.setVisible(true))); + detectionPage * model.getNumber().longValue()).limit(model.getNumber().longValue()) + .forEach(i -> SwingUtilities.invokeLater(() -> i.setVisible(true))); long notSelected = buttons.parallelStream().filter(Component::isVisible).filter(i -> !i.isSelected()).count(); long selected = buttons.parallelStream().filter(Component::isVisible).filter(ImageCheckBoxButton::isSelected) .count(); @@ -201,8 +183,7 @@ private static void createFirstLastSeen(JPanel panel, String firstLast) { } private static void updateDates( - String position, IDatePicker<?> modified, IDatePicker<?> firstSeen, IDatePicker<?> lastSeen - ) { + String position, IDatePicker<?> modified, IDatePicker<?> firstSeen, IDatePicker<?> lastSeen) { LocalDate start = firstSeen.getDate(); LocalDate end = lastSeen.getDate(); if (start != null && end != null) { @@ -237,17 +218,6 @@ private static void updateDates( } } - private static void updateMinDetectionFilter(JSpinner minDetections, Filter filter) { - if (minDetections.getModel() instanceof SpinnerNumberModel) { - SpinnerNumberModel model = (SpinnerNumberModel) minDetections.getModel(); - filter.enable = !Integer.valueOf(0).equals(model.getNumber()); - if (filter.enable && model.getNumber() != null) { - filter.text = "detections_num < " + model.getNumber(); - } - doFilterAddRemoveWork(filter); - } - } - private static void doFilterAddRemoveWork(Filter filter) { int index = MapillaryExpertFilterDialog.getInstance().getFilterModel().getFilters().indexOf(filter); if (index < 0 && filter.enable && !filter.text.isEmpty()) { @@ -273,7 +243,7 @@ private void toggleVisible(boolean check) { } MapillaryExpertFilterDialog.getInstance().getFilterModel().pauseUpdates(); List<Future<?>> futures = buttons.stream().filter(ImageCheckBoxButton::isVisible) - .map(b -> b.setSelected(check)).filter(Objects::nonNull).collect(Collectors.toList()); + .map(b -> b.setSelected(check)).filter(Objects::nonNull).collect(Collectors.toList()); for (Future<?> future : futures) { try { @@ -297,8 +267,7 @@ private void addButtons() { private void filterButtons(String expr) { SwingUtilities.invokeLater( - () -> buttons.stream().forEach(b -> b.setVisible(b.isFiltered(expr) && (!showRelevant || b.isRelevant()))) - ); + () -> buttons.stream().forEach(b -> b.setVisible(b.isFiltered(expr) && (!showRelevant || b.isRelevant())))); } public void getIcons(JComponent panel, String type) { @@ -309,7 +278,7 @@ public void getIcons(JComponent panel, String type) { String directory = "mapillary_sprite_source/package_" + type; try { List<String> files = IOUtils.readLines(ResourceProvider.getResourceAsStream("/images/" + directory), - Charsets.UTF_8.name()); + Charsets.UTF_8.name()); Collections.sort(files); for (String file : files) { try { From 7c106c15e4cba6fa2a5d33fd5d03b016f3214507 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 13:13:39 -0600 Subject: [PATCH 06/20] Move MapillaryLayer to appropriate package Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../josm/plugins/mapillary/MapillaryData.java | 3 ++- .../josm/plugins/mapillary/MapillaryImage.java | 1 + .../josm/plugins/mapillary/MapillaryPlugin.java | 1 + .../mapillary/actions/MapillaryDownloadAction.java | 2 +- .../mapillary/actions/MapillaryDownloadViewAction.java | 2 +- .../mapillary/actions/MapillaryExportAction.java | 2 +- .../plugins/mapillary/actions/MapillaryJoinAction.java | 2 +- .../actions/MapillarySubmitCurrentChangesetAction.java | 2 +- .../mapillary/actions/MapillaryUploadAction.java | 2 +- .../plugins/mapillary/actions/MapillaryWalkAction.java | 2 +- .../plugins/mapillary/actions/MapillaryZoomAction.java | 2 +- .../mapillary/actions/SelectNextImageAction.java | 2 +- .../josm/plugins/mapillary/actions/WalkThread.java | 2 +- .../josm/plugins/mapillary/actions/package-info.java | 2 +- .../plugins/mapillary/gui/MapillaryImageDisplay.java | 2 +- .../plugins/mapillary/gui/MapillaryMainDialog.java | 2 +- .../gui/dialog/ChooseGeoImageLayersDialog.java | 2 +- .../mapillary/gui/dialog/ImportMethodDialog.java | 2 +- .../mapillary/gui/dialog/MapillaryChangesetDialog.java | 2 +- .../mapillary/gui/dialog/MapillaryExportDialog.java | 2 +- .../mapillary/gui/dialog/MapillaryFilterDialog.java | 2 +- .../mapillary/gui/dialog/MapillaryUploadDialog.java | 2 +- .../mapillary/{ => gui/layer}/MapillaryLayer.java | 10 +++++++++- .../plugins/mapillary/gui/layer/PointObjectLayer.java | 1 - .../mapillary/history/commands/CommandDelete.java | 2 +- .../mapillary/history/commands/CommandImport.java | 2 +- .../mapillary/history/commands/CommandMove.java | 2 +- .../mapillary/history/commands/CommandTurn.java | 2 +- .../io/download/DetectionsDownloadRunnable.java | 2 +- .../mapillary/io/download/MapillaryDownloader.java | 2 +- .../io/download/MapillarySquareDownloadRunnable.java | 2 +- .../io/download/SequenceDownloadRunnable.java | 2 +- .../josm/plugins/mapillary/mode/AbstractMode.java | 2 +- .../josm/plugins/mapillary/mode/JoinMode.java | 2 +- .../josm/plugins/mapillary/mode/SelectMode.java | 2 +- .../josm/plugins/mapillary/mode/package-info.java | 2 +- .../josm/plugins/mapillary/utils/MapillaryUtils.java | 2 +- .../mapillary/{ => gui/layer}/MapillaryLayerTest.java | 6 +++++- .../plugins/mapillary/history/MapillaryRecordTest.java | 2 +- .../io/download/SequenceDownloadRunnableTest.java | 2 +- 40 files changed, 52 insertions(+), 38 deletions(-) rename src/main/java/org/openstreetmap/josm/plugins/mapillary/{ => gui/layer}/MapillaryLayer.java (97%) rename test/unit/org/openstreetmap/josm/plugins/mapillary/{ => gui/layer}/MapillaryLayerTest.java (93%) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java index ba1caecb9..89de5c96a 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java @@ -33,6 +33,7 @@ import org.openstreetmap.josm.plugins.mapillary.cache.Caches; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoPanel; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; @@ -85,7 +86,7 @@ public class MapillaryData implements Data { /** * Creates a new object and adds the initial set of listeners. */ - protected MapillaryData() { + public MapillaryData() { this.selectedImage = null; this.dataSources = new ArrayList<>(); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java index 23d1e4586..858065c82 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java @@ -9,6 +9,7 @@ import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.gpx.GpxImageEntry; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryColorScheme; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java index acdc11531..f87b96682 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java @@ -40,6 +40,7 @@ import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryHistoryDialog; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoHelpPopup; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoPanel; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java index 1a63e8796..0fbcbeea1 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java @@ -13,8 +13,8 @@ import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.gui.layer.OsmDataLayer; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; import org.openstreetmap.josm.tools.Logging; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java index b79798be2..409337292 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java @@ -7,8 +7,8 @@ import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeEvent; import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeListener; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.io.download.MapillaryDownloader; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.I18n; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java index ed3ec93e0..0e6eabcac 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java @@ -20,9 +20,9 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryExportDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.io.export.MapillaryExportManager; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryJoinAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryJoinAction.java index 37c01e6e7..cd245e694 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryJoinAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryJoinAction.java @@ -7,7 +7,7 @@ import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.gui.MainApplication; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.mode.JoinMode; import org.openstreetmap.josm.plugins.mapillary.mode.SelectMode; import org.openstreetmap.josm.tools.ImageProvider; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java index 233a3d016..1bdadb49b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySubmitCurrentChangesetAction.java @@ -18,9 +18,9 @@ import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.gui.Notification; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryLocationChangeset; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryChangesetDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL.APIv3; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryUtils; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java index a23986ec0..8784a70b6 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryUploadAction.java @@ -11,9 +11,9 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryUploadDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.oauth.UploadUtils; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.ImageProvider; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java index 61123621c..d82d1da6d 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryWalkAction.java @@ -15,10 +15,10 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryWalkDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java index 4181c063f..b07854b85 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java @@ -9,8 +9,8 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/SelectNextImageAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/SelectNextImageAction.java index b5447eb9e..e7a67e428 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/SelectNextImageAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/SelectNextImageAction.java @@ -9,7 +9,7 @@ import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.Shortcut; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/WalkThread.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/WalkThread.java index ce0ba3273..94e376a98 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/WalkThread.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/WalkThread.java @@ -8,11 +8,11 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.cache.CacheUtils; import org.openstreetmap.josm.plugins.mapillary.cache.MapillaryCache; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.Logging; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/package-info.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/package-info.java index ff82ba55b..8dd706f60 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/package-info.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/package-info.java @@ -1,7 +1,7 @@ // License: GPL. For details, see LICENSE file. /** * Actions that are normally attached to a button or a menu item and are then executed - * to manipulate the {@link org.openstreetmap.josm.plugins.mapillary.MapillaryLayer} when + * to manipulate the {@link org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer} when * the button is clicked. */ package org.openstreetmap.josm.plugins.mapillary.actions; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java index 78043c06c..b528f97e3 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java @@ -36,8 +36,8 @@ import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.layer.LayerManager; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryDownloadAction; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.layer.PointObjectLayer; import org.openstreetmap.josm.plugins.mapillary.gui.panorama.CameraPlane; import org.openstreetmap.josm.plugins.mapillary.gui.panorama.UVMapping; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java index d757e2312..33d6eeff7 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java @@ -38,13 +38,13 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.actions.SelectNextImageAction; import org.openstreetmap.josm.plugins.mapillary.actions.WalkListener; import org.openstreetmap.josm.plugins.mapillary.actions.WalkThread; import org.openstreetmap.josm.plugins.mapillary.cache.MapillaryCache; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoHelpPopup; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.ImageProvider; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ChooseGeoImageLayersDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ChooseGeoImageLayersDialog.java index 0e2393b53..619dd8f02 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ChooseGeoImageLayersDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ChooseGeoImageLayersDialog.java @@ -28,10 +28,10 @@ import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer; import org.openstreetmap.josm.gui.util.GuiHelper; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.MapillarySequence; import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryImportAction; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.Logging; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ImportMethodDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ImportMethodDialog.java index bbec0c1be..26c77b4d9 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ImportMethodDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/ImportMethodDialog.java @@ -25,10 +25,10 @@ import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer; import org.openstreetmap.josm.gui.util.GuiHelper; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.MapillarySequence; import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryImportAction; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.ImageImportUtil; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.I18n; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java index fd9d9af83..40fa042bb 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryChangesetDialog.java @@ -27,10 +27,10 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.SideButton; import org.openstreetmap.josm.gui.dialogs.ToggleDialog; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryLocationChangeset; import org.openstreetmap.josm.plugins.mapillary.actions.MapillarySubmitCurrentChangesetAction; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryImageTreeCellRenderer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.MapillaryCommand; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryChangesetListener; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java index 0647af825..7b6d0036c 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryExportDialog.java @@ -18,7 +18,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; /** * GUI for exporting images. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java index d00b42bff..d181ba351 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java @@ -42,12 +42,12 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.data.mapillary.OrganizationRecord; import org.openstreetmap.josm.plugins.mapillary.data.mapillary.OrganizationRecord.OrganizationRecordListener; import org.openstreetmap.josm.plugins.mapillary.gui.IDatePicker; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterChooseSigns; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryPreferenceSetting; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryLoginListener; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java index 7b4dc9b30..6d8046469 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryUploadDialog.java @@ -11,7 +11,7 @@ import javax.swing.JRadioButton; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java similarity index 97% rename from src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java rename to src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index 1ff947da0..4940012ae 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary; +package org.openstreetmap.josm.plugins.mapillary.gui.layer; import java.awt.AlphaComposite; import java.awt.BasicStroke; @@ -58,6 +58,14 @@ import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; import org.openstreetmap.josm.gui.layer.OsmDataLayer; +import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; +import org.openstreetmap.josm.plugins.mapillary.MapillaryData; +import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; +import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; +import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; +import org.openstreetmap.josm.plugins.mapillary.MapillaryLocationChangeset; +import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; +import org.openstreetmap.josm.plugins.mapillary.MapillarySequence; import org.openstreetmap.josm.plugins.mapillary.cache.CacheUtils; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryChangesetDialog; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java index 472ea8232..cd2a0df3b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/PointObjectLayer.java @@ -97,7 +97,6 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.data.osm.event.FilterEventListener; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandDelete.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandDelete.java index d81848a18..bc9deb6b3 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandDelete.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandDelete.java @@ -8,7 +8,7 @@ import java.util.Set; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; /** * Command used to delete a set of images. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandImport.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandImport.java index 3371c97f6..7e123076a 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandImport.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandImport.java @@ -6,7 +6,7 @@ import java.util.Set; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; /** * Imports a set of images stored locally. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandMove.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandMove.java index 33d2cc63b..30456a39b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandMove.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandMove.java @@ -6,7 +6,7 @@ import java.util.Set; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; /** * Command created when an image's position is changed. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandTurn.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandTurn.java index 858a4d4dc..329a2f4f0 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandTurn.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/history/commands/CommandTurn.java @@ -6,7 +6,7 @@ import java.util.Set; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; /** * Command created when an image's direction is changed. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/DetectionsDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/DetectionsDownloadRunnable.java index 4dfe56fd4..ec7098c15 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/DetectionsDownloadRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/DetectionsDownloadRunnable.java @@ -17,8 +17,8 @@ import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL.APIv3; import org.openstreetmap.josm.plugins.mapillary.utils.api.JsonDecoder; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillaryDownloader.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillaryDownloader.java index 372c17ae8..4f9e0a3ec 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillaryDownloader.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillaryDownloader.java @@ -10,8 +10,8 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.Notification; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.I18n; import org.openstreetmap.josm.tools.Logging; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java index 89397cc58..8de7094ef 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/MapillarySquareDownloadRunnable.java @@ -6,9 +6,9 @@ import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.gui.MainApplication; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.dialog.MapillaryFilterDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryUtils; import org.openstreetmap.josm.plugins.mapillary.utils.PluginState; import org.openstreetmap.josm.tools.Logging; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnable.java index 88376b6dc..f73935a23 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnable.java @@ -14,8 +14,8 @@ import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryData; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillarySequence; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryURL.APIv3; import org.openstreetmap.josm.plugins.mapillary.utils.api.JsonDecoder; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java index 852769ad0..e592d273e 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java @@ -12,7 +12,7 @@ import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.io.download.MapillaryDownloader; /** diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java index ffab687bb..8fee86c1c 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java @@ -15,7 +15,7 @@ import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandJoin; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandUnjoin; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java index 86760da0f..5ab8957be 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java @@ -21,8 +21,8 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandMove; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandTurn; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/package-info.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/package-info.java index d30d28b92..1279f1d0b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/package-info.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/package-info.java @@ -1,6 +1,6 @@ // License: GPL. For details, see LICENSE file. /** - * The different modes that the {@link org.openstreetmap.josm.plugins.mapillary.MapillaryLayer} can be in. + * The different modes that the {@link org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer} can be in. * <br> * Currently there are two of them: * <ul> diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryUtils.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryUtils.java index cc755c812..3930cb816 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryUtils.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryUtils.java @@ -16,8 +16,8 @@ import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.MapillarySequence; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.tools.I18n; /** diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/MapillaryLayerTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java similarity index 93% rename from test/unit/org/openstreetmap/josm/plugins/mapillary/MapillaryLayerTest.java rename to test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java index e029ca344..3715696bd 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/MapillaryLayerTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java @@ -1,5 +1,5 @@ // License: GPL. For details, see LICENSE file. -package org.openstreetmap.josm.plugins.mapillary; +package org.openstreetmap.josm.plugins.mapillary.gui.layer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -20,6 +20,10 @@ import org.openstreetmap.josm.gui.layer.ImageryLayer; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.gui.layer.OsmDataLayer; +import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; +import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; +import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil.MapillaryTestRules; import org.openstreetmap.josm.testutils.JOSMTestRules; diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/history/MapillaryRecordTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/history/MapillaryRecordTest.java index 5e89002b1..efdc13680 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/history/MapillaryRecordTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/history/MapillaryRecordTest.java @@ -19,7 +19,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandDelete; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandImport; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandJoin; diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnableTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnableTest.java index 448463ece..87c6a1e23 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnableTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/io/download/SequenceDownloadRunnableTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.openstreetmap.josm.data.Bounds; -import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer; +import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil; From 21642ec0d47d499027ddf9a943aad9c323b37b1c Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 15:10:41 -0600 Subject: [PATCH 07/20] Revert "Add preference to change number of clicks for deselection" This reverts commit a286f3bb25739c97a3ded20214e37ce9b6a5aeea. --- .../openstreetmap/josm/plugins/mapillary/mode/SelectMode.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java index 5ab8957be..b110ac084 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java @@ -27,7 +27,6 @@ import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandMove; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandTurn; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; -import org.openstreetmap.josm.spi.preferences.Config; /** * Handles the input event related with the layer. Mainly clicks. @@ -62,7 +61,7 @@ public void mousePressed(MouseEvent e) { } if (MainApplication.getLayerManager().getActiveLayer() instanceof MapillaryLayer) { - if (e.getClickCount() == Config.getPref().getInt("mapillary.image.deselect.click.count", 3)) { // Triple click + if (e.getClickCount() == 2) { // Double click if (e.getButton() == MouseEvent.BUTTON1 && MapillaryLayer.getInstance().getData().getSelectedImage() != null) { MapillaryLayer.getInstance().getData().addMultiSelectedImage(closest.getSequence().getImages()); } From 43da6ee6a5c3a036e4dfa4cabea355c8ca00aa0a Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 15:14:26 -0600 Subject: [PATCH 08/20] Modify Mapillary image layer to reduce lag * Mapillary Image layer no longer draws circle + angle at low zoom levels (0-17), instead drawing a line * Modify JoinMode/SelectMode to implement MapMode (through AbstractMode). This partially fixes #21. * Actually fix #115 (I replaced the wrong double-click initially) Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../mapillary/gui/layer/MapillaryLayer.java | 153 +++++++++++------- .../plugins/mapillary/mode/AbstractMode.java | 37 ++++- .../josm/plugins/mapillary/mode/JoinMode.java | 20 +-- .../plugins/mapillary/mode/SelectMode.java | 40 +++-- .../gui/layer/MapillaryLayerTest.java | 1 - 5 files changed, 155 insertions(+), 96 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index 4940012ae..01b568f7b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -12,6 +12,7 @@ import java.awt.RenderingHints; import java.awt.TexturePaint; import java.awt.event.ActionEvent; +import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.image.BufferedImage; @@ -30,6 +31,7 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; +import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; @@ -58,6 +60,8 @@ import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; import org.openstreetmap.josm.gui.layer.OsmDataLayer; +import org.openstreetmap.josm.gui.mappaint.Range; +import org.openstreetmap.josm.gui.mappaint.mapcss.Selector; import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryData; import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener; @@ -84,6 +88,7 @@ import org.openstreetmap.josm.spi.preferences.Config; import org.openstreetmap.josm.tools.Geometry; import org.openstreetmap.josm.tools.I18n; +import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; import org.openstreetmap.josm.tools.Logging; @@ -106,8 +111,22 @@ public final class MapillaryLayer extends AbstractModifiableLayer implements private static final int TRAFFIC_SIGN_SIZE = 6; /** A third of the height of the sign, for easier calculations */ private static final double TRAFFIC_SIGN_HEIGHT_3RD = Math.sqrt( - Math.pow(TRAFFIC_SIGN_SIZE, 2) - Math.pow(TRAFFIC_SIGN_SIZE / 2d, 2) - ) / 3; + Math.pow(TRAFFIC_SIGN_SIZE, 2) - Math.pow(TRAFFIC_SIGN_SIZE / 2d, 2)) / 3; + /** The range to paint the full detection image at */ + private static final Range IMAGE_CA_PAINT_RANGE = Selector.GeneralSelector.fromLevel(18, Integer.MAX_VALUE); + /** A shape to avoid many calculations */ + private static final Ellipse2D.Double IMAGE_CIRCLE = new Ellipse2D.Double(0, 0, 2 * IMG_MARKER_RADIUS, + 2 * IMG_MARKER_RADIUS); + + /** The default sprite for a Mapillary image */ + public static final ImageIcon DEFAULT_SPRITE = ImageProvider.get("mapillary_sprite_source/package_ui", "regular-0", + ImageProvider.ImageSizes.MAPMAX); + /** The sprite to use for the active Mapillary sequence */ + public static final ImageIcon ACTIVE_SEQUENCE_SPRITE = ImageProvider.get("mapillary_sprite_source/package_ui", + "active-ca-0", ImageProvider.ImageSizes.MAPMAX); + /** The sprite to use for the currently selected image */ + public static final ImageIcon SELECTED_IMAGE = ImageProvider.get("mapillary_sprite_source/package_ui", "cur-ca-0", + ImageProvider.ImageSizes.MAPMAX); private static class DataSetSourceListener implements DataSourceListener { @Override @@ -195,11 +214,12 @@ public void setMode(AbstractMode mode) { if (this.mode != null && mv != null) { mv.removeMouseListener(this.mode); mv.removeMouseMotionListener(this.mode); + this.mode.exitMode(); NavigatableComponent.removeZoomChangeListener(this.mode); } this.mode = mode; if (mode != null && mv != null) { - mv.setNewCursor(mode.cursor, this); + mode.enterMode(); mv.addMouseListener(mode); mv.addMouseMotionListener(mode); NavigatableComponent.addZoomChangeListener(mode); @@ -239,7 +259,7 @@ public static boolean hasInstance() { * * @return The {@link MapillaryData} object that stores the database. */ - //@Override Depends upon #18801 for the override + // @Override Depends upon #18801 for the override public MapillaryData getData() { return this.data; } @@ -258,6 +278,7 @@ public MapillaryLocationChangeset getLocationChangeset() { * Returns the n-nearest image, for n=1 the nearest one is returned, for n=2 the second nearest one and so on. * The "n-nearest image" is picked from the list of one image from every sequence that is nearest to the currently * selected image, excluding the sequence to which the selected image belongs. + * * @param n the index for picking from the list of "nearest images", beginning from 1 * @return the n-nearest image to the currently selected image, or null if no such image can be found */ @@ -304,7 +325,8 @@ public synchronized void destroy() { MainApplication.getLayerManager().getEditDataSet().removeDataSourceListener(DATASET_LISTENER); } } catch (IllegalArgumentException e) { - // TODO: It would be ideal, to fix this properly. But for the moment let's catch this, for when a listener has already been removed. + // TODO: It would be ideal, to fix this properly. But for the moment let's catch this, for when a listener has + // already been removed. } UploadAction.unregisterUploadHook(this); super.destroy(); @@ -372,16 +394,13 @@ public synchronized void paint(final Graphics2D g, final MapView mv, final Bound for (MapillarySequence seq : getData().getSequences()) { if (seq.getImages().contains(selectedImage)) { g.setColor( - seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_SELECTED : MapillaryColorScheme.SEQ_SELECTED - ); + seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_SELECTED : MapillaryColorScheme.SEQ_SELECTED); } else if (selectedImage == null) { g.setColor( - seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED : MapillaryColorScheme.SEQ_UNSELECTED - ); + seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED : MapillaryColorScheme.SEQ_UNSELECTED); } else { g.setColor( - seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED : MapillaryColorScheme.SEQ_UNSELECTED - ); + seq.getKey() == null ? MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED : MapillaryColorScheme.SEQ_UNSELECTED); g.setComposite(fadeComposite); } g.draw(MapViewGeometryUtil.getSequencePath(mv, seq)); @@ -399,7 +418,8 @@ public synchronized void paint(final Graphics2D g, final MapView mv, final Bound /** * Draws an image marker onto the given Graphics context. - * @param g the Graphics context + * + * @param g the Graphics context * @param img the image to be drawn onto the Graphics context */ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage img) { @@ -419,7 +439,8 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im if (selectedImg != null && getData().getMultiSelectedImages().contains(img)) { markerC = img.paintHighlightedColour(); directionC = img.paintHighlightedAngleColour(); - } else if (selectedImg != null && selectedImg.getSequence() != null && selectedImg.getSequence().equals(img.getSequence())) { + } else if (selectedImg != null && selectedImg.getSequence() != null + && selectedImg.getSequence().equals(img.getSequence())) { markerC = img.paintSelectedColour(); directionC = img.paintSelectedAngleColour(); } else { @@ -428,35 +449,45 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im } // Paint direction indicator - g.setColor(directionC); - if (img.isPanorama()) { - g.fillOval(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS); - } else { - g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, (int) (90 - img.getMovingCa() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); - } - // Paint image marker - g.setColor(markerC); - g.fillOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); - - // Paint highlight for selected or highlighted images - if (getData().getHighlightedImages().contains(img) || img.equals(getData().getHighlightedImage()) - || getData().getMultiSelectedImages().contains(img)) { - g.setColor(Color.WHITE); - g.setStroke(new BasicStroke(2)); - g.drawOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); - } - - if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { - Path2D trafficSign = new Path2D.Double(); - trafficSign.moveTo(p.getX() - TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.lineTo(p.getX() + TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.lineTo(p.getX(), p.getY() + 2 * TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.closePath(); - g.setColor(Color.WHITE); - g.fill(trafficSign); - g.setStroke(new BasicStroke(1)); - g.setColor(Color.RED); - g.draw(trafficSign); + if (IMAGE_CA_PAINT_RANGE.contains(MainApplication.getMap().mapView.getDist100Pixel())) { + g.setColor(directionC); + if (img.isPanorama()) { + g.fillOval(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, + 2 * CA_INDICATOR_RADIUS); + } else { + g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, + 2 * CA_INDICATOR_RADIUS, + (int) (90 - img.getMovingCa() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); + } + // Paint image marker + g.setColor(markerC); + g.setPaint(markerC); + synchronized (IMAGE_CIRCLE) { + IMAGE_CIRCLE.x = (double) p.x - IMG_MARKER_RADIUS; + IMAGE_CIRCLE.y = (double) p.y - IMG_MARKER_RADIUS; + g.fill(IMAGE_CIRCLE); + } + + // Paint highlight for selected or highlighted images + if (getData().getHighlightedImages().contains(img) || img.equals(getData().getHighlightedImage()) + || getData().getMultiSelectedImages().contains(img)) { + g.setColor(Color.WHITE); + g.setStroke(new BasicStroke(2)); + g.drawOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); + } + + if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { + Path2D trafficSign = new Path2D.Double(); + trafficSign.moveTo(p.getX() - TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); + trafficSign.lineTo(p.getX() + TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); + trafficSign.lineTo(p.getX(), p.getY() + 2 * TRAFFIC_SIGN_HEIGHT_3RD); + trafficSign.closePath(); + g.setColor(Color.WHITE); + g.fill(trafficSign); + g.setStroke(new BasicStroke(1)); + g.setColor(Color.RED); + g.draw(trafficSign); + } } g.setComposite(composite); } @@ -485,8 +516,8 @@ private boolean isApplicable() { // 0) List<OsmPrimitive> searchPrimitives = ds.searchPrimitives(bbox); if (primitives.parallelStream().filter(searchPrimitives::contains) - .mapToDouble(prim -> Geometry.getDistance(prim, new Node(image.getLatLon()))) - .anyMatch(d -> d < maxDistance)) { + .mapToDouble(prim -> Geometry.getDistance(prim, new Node(image.getLatLon()))) + .anyMatch(d -> d < maxDistance)) { isApplicable = true; break; } @@ -514,7 +545,7 @@ public void mergeFrom(Layer from) { @Override public Action[] getMenuEntries() { - return new Action[]{ + return new Action[] { LayerListDialog.getInstance().createShowHideLayerAction(), LayerListDialog.getInstance().createDeleteLayerAction(), new LayerListPopup.InfoAction(this) @@ -523,7 +554,8 @@ public Action[] getMenuEntries() { @Override public Object getInfoComponent() { - IntSummaryStatistics seqSizeStats = getData().getSequences().stream().mapToInt(seq -> seq.getImages().size()).summaryStatistics(); + IntSummaryStatistics seqSizeStats = getData().getSequences().stream().mapToInt(seq -> seq.getImages().size()) + .summaryStatistics(); final long numImported = getData().getImages().stream().filter(i -> i instanceof MapillaryImportedImage).count(); final long numDownloaded = getData().getImages().stream().filter(i -> i instanceof MapillaryImage).count(); final int numTotal = getData().getImages().size(); @@ -536,8 +568,7 @@ public Object getInfoComponent() { getData().getSequences().size(), seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMin(), seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMax(), - seqSizeStats.getAverage() - )) + seqSizeStats.getAverage())) .append("\n\n") .append(I18n.trn("{0} imported image", "{0} imported images", numImported, numImported)) .append("\n+ ") @@ -599,7 +630,8 @@ public void visitBoundingBox(BoundingXYVisitor v) { // Don't care about this } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener#imagesAdded() */ @Override @@ -607,8 +639,11 @@ public void imagesAdded() { updateNearestImages(); } - /* (non-Javadoc) - * @see org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener#selectedImageChanged(org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage, org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage) + /* + * (non-Javadoc) + * @see + * org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener#selectedImageChanged(org.openstreetmap.josm.plugins. + * mapillary.MapillaryAbstractImage, org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage) */ @Override public void selectedImageChanged(MapillaryAbstractImage oldImage, MapillaryAbstractImage newImage) { @@ -620,7 +655,7 @@ public void selectedImageChanged(MapillaryAbstractImage oldImage, MapillaryAbstr * different from the specified target image. * * @param target the image for which you want to find the nearest other images - * @param limit the maximum length of the returned array + * @param limit the maximum length of the returned array * @return An array containing the closest images belonging to different sequences sorted by distance from target. */ private MapillaryImage[] getNearestImagesFromDifferentSequences(MapillaryAbstractImage target, int limit) { @@ -633,10 +668,9 @@ private MapillaryImage[] getNearestImagesFromDifferentSequences(MapillaryAbstrac return resImg.orElse(null); }) .filter(img -> // Filters out images too far away from target - img != null && - img.getMovingLatLon().greatCircleDistance(target.getMovingLatLon()) - < MapillaryProperties.SEQUENCE_MAX_JUMP_DISTANCE.get() - ) + img != null && + img.getMovingLatLon() + .greatCircleDistance(target.getMovingLatLon()) < MapillaryProperties.SEQUENCE_MAX_JUMP_DISTANCE.get()) .sorted(new NearestImgToTargetComparator(target)) .limit(limit) .toArray(MapillaryImage[]::new); @@ -692,15 +726,16 @@ private static class NearestImgToTargetComparator implements Comparator<Mapillar public NearestImgToTargetComparator(MapillaryAbstractImage target) { this.target = target; } - /* (non-Javadoc) + + /* + * (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(MapillaryAbstractImage img1, MapillaryAbstractImage img2) { return (int) Math.signum( img1.getMovingLatLon().greatCircleDistance(target.getMovingLatLon()) - - img2.getMovingLatLon().greatCircleDistance(target.getMovingLatLon()) - ); + img2.getMovingLatLon().greatCircleDistance(target.getMovingLatLon())); } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java index e592d273e..0213da63a 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java @@ -4,9 +4,9 @@ import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.Point; -import java.awt.event.MouseAdapter; import java.util.Calendar; +import org.openstreetmap.josm.actions.mapmode.MapMode; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.MapView; @@ -14,6 +14,7 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.io.download.MapillaryDownloader; +import org.openstreetmap.josm.tools.Shortcut; /** * Superclass for all the mode of the {@link MapillaryLayer}. @@ -21,16 +22,36 @@ * @author nokutu * @see MapillaryLayer */ -public abstract class AbstractMode extends MouseAdapter implements +public abstract class AbstractMode extends MapMode implements ZoomChangeListener { - private static final int DOWNLOAD_COOLDOWN = 2000; - private static SemiautomaticThread semiautomaticThread = new SemiautomaticThread(); + /** + * Constructor for mapmodes with a menu (no shortcut will be registered) + * + * @param name the action's text + * @param iconName icon filename in {@code mapmode} directory + * @param tooltip a longer description of the action that will be displayed in the tooltip. + * @param cursor cursor displayed when map mode is active + */ + public AbstractMode(String name, String iconName, String tooltip, Cursor cursor) { + super(name, iconName, tooltip, cursor); + } /** - * Cursor that should become active when this mode is activated. + * Constructor for mapmodes without a menu + * + * @param name the action's text + * @param iconName icon filename in {@code mapmode} directory + * @param tooltip a longer description of the action that will be displayed in the tooltip. + * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. + * @param cursor cursor displayed when map mode is active */ - public int cursor = Cursor.DEFAULT_CURSOR; + public AbstractMode(String name, String iconName, String tooltip, Shortcut shortcut, Cursor cursor) { + super(name, iconName, tooltip, shortcut, cursor); + } + + private static final int DOWNLOAD_COOLDOWN = 2000; + private static SemiautomaticThread semiautomaticThread = new SemiautomaticThread(); protected MapillaryAbstractImage getClosest(Point clickPoint) { double snapDistance = 10; @@ -52,8 +73,8 @@ protected MapillaryAbstractImage getClosest(Point clickPoint) { /** * Paint the dataset using the engine set. * - * @param g {@link Graphics2D} used for painting - * @param mv The object that can translate GeoPoints to screen coordinates. + * @param g {@link Graphics2D} used for painting + * @param mv The object that can translate GeoPoints to screen coordinates. * @param box Area where painting is going to be performed */ public abstract void paint(Graphics2D g, MapView mv, Bounds box); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java index 8fee86c1c..fe5a73687 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/JoinMode.java @@ -4,7 +4,6 @@ import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.Color; -import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.MouseEvent; @@ -19,6 +18,7 @@ import org.openstreetmap.josm.plugins.mapillary.history.MapillaryRecord; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandJoin; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandUnjoin; +import org.openstreetmap.josm.tools.ImageProvider; /** * In this mode the user can join pictures to make sequences or unjoin them. @@ -35,7 +35,8 @@ public class JoinMode extends AbstractMode { * Main constructor. */ public JoinMode() { - this.cursor = Cursor.CROSSHAIR_CURSOR; + super(tr("Mapillary Join Mode"), "mapillary-join", tr("Join images into sequences in the Mapillary Layer"), + ImageProvider.getCursor("crosshair", null)); } @Override @@ -47,19 +48,14 @@ public void mousePressed(MouseEvent e) { if (this.lastClick == null && highlighted instanceof MapillaryImportedImage) { this.lastClick = (MapillaryImportedImage) highlighted; } else if (this.lastClick != null - && highlighted instanceof MapillaryImportedImage) { - if ( - ( - (highlighted.previous() == null && this.lastClick.next() == null) || - (highlighted.next() == null && this.lastClick.previous() == null) - ) - && !highlighted.getSequence().equals(this.lastClick.getSequence()) - ) { + && highlighted instanceof MapillaryImportedImage) { + if (((highlighted.previous() == null && this.lastClick.next() == null) || + (highlighted.next() == null && this.lastClick.previous() == null)) + && !highlighted.getSequence().equals(this.lastClick.getSequence())) { MapillaryRecord.getInstance().addCommand(new CommandJoin(this.lastClick, highlighted)); } else if (highlighted.equals(this.lastClick.next()) || highlighted.equals(this.lastClick.previous())) { MapillaryRecord.getInstance().addCommand( - new CommandUnjoin(Arrays.asList(this.lastClick, highlighted)) - ); + new CommandUnjoin(Arrays.asList(this.lastClick, highlighted))); } this.lastClick = null; } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java index b110ac084..42b4ba597 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/mode/SelectMode.java @@ -27,6 +27,8 @@ import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandMove; import org.openstreetmap.josm.plugins.mapillary.history.commands.CommandTurn; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; +import org.openstreetmap.josm.spi.preferences.Config; +import org.openstreetmap.josm.tools.ImageProvider; /** * Handles the input event related with the layer. Mainly clicks. @@ -44,6 +46,8 @@ public class SelectMode extends AbstractMode { * Main constructor. */ public SelectMode() { + super(tr("Mapillary Select Mode"), "mapillary-select", tr("Select images in the Mapillary Layer"), + ImageProvider.getCursor("normal", null)); this.record = MapillaryRecord.getInstance(); } @@ -54,7 +58,9 @@ public void mousePressed(MouseEvent e) { } final MapillaryAbstractImage closest = getClosest(e.getPoint()); if (closest == null) { - if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 && MapillaryLayer.hasInstance()) { + if (e.getButton() == MouseEvent.BUTTON1 + && e.getClickCount() == Config.getPref().getInt("mapillary.image.deselect.click.count", 3) + && MapillaryLayer.hasInstance()) { // Triple click MapillaryLayer.getInstance().getData().setSelectedImage(null); } return; @@ -74,9 +80,7 @@ public void mousePressed(MouseEvent e) { MapillaryLayer.getInstance().getData().addMultiSelectedImage( new ConcurrentSkipListSet<>(closest.getSequence().getImages().subList( Math.min(i, j), - Math.max(i, j) + 1 - )) - ); + Math.max(i, j) + 1))); } } else { // click MapillaryLayer.getInstance().getData().setSelectedImage(closest); @@ -93,20 +97,23 @@ public void mousePressed(MouseEvent e) { @Override public void mouseDragged(MouseEvent e) { MapillaryAbstractImage highlightImg = MapillaryLayer.getInstance().getData().getHighlightedImage(); - if ( - MainApplication.getLayerManager().getActiveLayer() == MapillaryLayer.getInstance() - && SwingUtilities.isLeftMouseButton(e) - && highlightImg != null && highlightImg.getLatLon() != null - ) { + if (MainApplication.getLayerManager().getActiveLayer() == MapillaryLayer.getInstance() + && SwingUtilities.isLeftMouseButton(e) + && highlightImg != null && highlightImg.getLatLon() != null) { Point highlightImgPoint = MainApplication.getMap().mapView.getPoint(highlightImg.getTempLatLon()); if (e.isShiftDown()) { // turn - MapillaryLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof MapillaryImage) || MapillaryProperties.DEVELOPER.get()) - .forEach(img -> img.turn(Math.toDegrees(Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) - highlightImg.getTempCa())); + MapillaryLayer.getInstance().getData().getMultiSelectedImages().parallelStream() + .filter(img -> !(img instanceof MapillaryImage) || MapillaryProperties.DEVELOPER.get()) + .forEach(img -> img + .turn(Math.toDegrees(Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) + - highlightImg.getTempCa())); } else { // move LatLon eventLatLon = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY()); - LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), highlightImgPoint.getY()); - MapillaryLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof MapillaryImage) || MapillaryProperties.DEVELOPER.get()) - .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), eventLatLon.getY() - imgLatLon.getY())); + LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), + highlightImgPoint.getY()); + MapillaryLayer.getInstance().getData().getMultiSelectedImages().parallelStream() + .filter(img -> !(img instanceof MapillaryImage) || MapillaryProperties.DEVELOPER.get()) + .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), eventLatLon.getY() - imgLatLon.getY())); } MapillaryLayer.invalidateInstance(); } @@ -125,7 +132,8 @@ public void mouseReleased(MouseEvent e) { } else if (!Objects.equals(data.getSelectedImage().getTempLatLon(), data.getSelectedImage().getMovingLatLon())) { LatLon from = data.getSelectedImage().getTempLatLon(); LatLon to = data.getSelectedImage().getMovingLatLon(); - record.addCommand(new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY())); + record + .addCommand(new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY())); } data.getMultiSelectedImages().parallelStream().filter(Objects::nonNull).forEach(MapillaryAbstractImage::stopMoving); MapillaryLayer.invalidateInstance(); @@ -137,7 +145,7 @@ public void mouseReleased(MouseEvent e) { @Override public void mouseMoved(MouseEvent e) { if (MainApplication.getLayerManager().getActiveLayer() instanceof OsmDataLayer - && MainApplication.getMap().mapMode != MainApplication.getMap().mapModeSelect) { + && MainApplication.getMap().mapMode != MainApplication.getMap().mapModeSelect) { return; } if (!MapillaryProperties.HOVER_ENABLED.get()) { diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java index 3715696bd..4cd31eea7 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayerTest.java @@ -23,7 +23,6 @@ import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImage; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; -import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil.MapillaryTestRules; import org.openstreetmap.josm.testutils.JOSMTestRules; From 2958ee5d4a13496bd41d7953ebd7ea23b5d6f2a3 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 15:52:50 -0600 Subject: [PATCH 09/20] Use a sprite for the traffic sign detections hint Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../mapillary/gui/layer/MapillaryLayer.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index 01b568f7b..ce0d84a74 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -7,6 +7,7 @@ import java.awt.Composite; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; +import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; @@ -14,7 +15,6 @@ import java.awt.event.ActionEvent; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; -import java.awt.geom.Path2D; import java.awt.image.BufferedImage; import java.util.Collection; import java.util.Collections; @@ -127,6 +127,11 @@ public final class MapillaryLayer extends AbstractModifiableLayer implements /** The sprite to use for the currently selected image */ public static final ImageIcon SELECTED_IMAGE = ImageProvider.get("mapillary_sprite_source/package_ui", "cur-ca-0", ImageProvider.ImageSizes.MAPMAX); + /** The sprite to use to indicate that there are sign detections in the image */ + private static final Image YIELD_SIGN = new ImageProvider("mapillary_sprite_source/package_signs", + "regulatory--yield--g1") + .setMaxSize(TRAFFIC_SIGN_SIZE).get() + .getImage(); private static class DataSetSourceListener implements DataSourceListener { @Override @@ -477,16 +482,8 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im } if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { - Path2D trafficSign = new Path2D.Double(); - trafficSign.moveTo(p.getX() - TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.lineTo(p.getX() + TRAFFIC_SIGN_SIZE / 2d, p.getY() - TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.lineTo(p.getX(), p.getY() + 2 * TRAFFIC_SIGN_HEIGHT_3RD); - trafficSign.closePath(); - g.setColor(Color.WHITE); - g.fill(trafficSign); - g.setStroke(new BasicStroke(1)); - g.setColor(Color.RED); - g.draw(trafficSign); + g.drawImage(YIELD_SIGN, (int) (p.getX() - TRAFFIC_SIGN_SIZE / 2d), (int) (p.getY() - TRAFFIC_SIGN_SIZE / 2d), + null); } } g.setComposite(composite); From d103dd61a01a1c025115d4e85dde528c23015d22 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Tue, 28 Apr 2020 16:02:51 -0600 Subject: [PATCH 10/20] FIXUP: Keep painting selected sequence Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../mapillary/gui/layer/MapillaryLayer.java | 66 ++++++++++--------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index ce0d84a74..c8152cd12 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -433,6 +433,12 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im return; } final MapillaryAbstractImage selectedImg = getData().getSelectedImage(); + if (!IMAGE_CA_PAINT_RANGE.contains(MainApplication.getMap().mapView.getDist100Pixel()) && !img.equals(selectedImg) + && !getData().getMultiSelectedImages().contains(img) + && (selectedImg == null || !img.getSequence().equals(selectedImg.getSequence()))) { + Logging.trace("An image was not painted due to a high zoom level, and not being the selected image/sequence"); + return; + } final Point p = MainApplication.getMap().mapView.getPoint(img.getMovingLatLon()); Composite composite = g.getComposite(); if (selectedImg != null && !selectedImg.getSequence().equals(img.getSequence())) { @@ -454,37 +460,35 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im } // Paint direction indicator - if (IMAGE_CA_PAINT_RANGE.contains(MainApplication.getMap().mapView.getDist100Pixel())) { - g.setColor(directionC); - if (img.isPanorama()) { - g.fillOval(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, - 2 * CA_INDICATOR_RADIUS); - } else { - g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, - 2 * CA_INDICATOR_RADIUS, - (int) (90 - img.getMovingCa() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); - } - // Paint image marker - g.setColor(markerC); - g.setPaint(markerC); - synchronized (IMAGE_CIRCLE) { - IMAGE_CIRCLE.x = (double) p.x - IMG_MARKER_RADIUS; - IMAGE_CIRCLE.y = (double) p.y - IMG_MARKER_RADIUS; - g.fill(IMAGE_CIRCLE); - } - - // Paint highlight for selected or highlighted images - if (getData().getHighlightedImages().contains(img) || img.equals(getData().getHighlightedImage()) - || getData().getMultiSelectedImages().contains(img)) { - g.setColor(Color.WHITE); - g.setStroke(new BasicStroke(2)); - g.drawOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); - } - - if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { - g.drawImage(YIELD_SIGN, (int) (p.getX() - TRAFFIC_SIGN_SIZE / 2d), (int) (p.getY() - TRAFFIC_SIGN_SIZE / 2d), - null); - } + g.setColor(directionC); + if (img.isPanorama()) { + g.fillOval(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, + 2 * CA_INDICATOR_RADIUS); + } else { + g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, + 2 * CA_INDICATOR_RADIUS, + (int) (90 - img.getMovingCa() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); + } + // Paint image marker + g.setColor(markerC); + g.setPaint(markerC); + synchronized (IMAGE_CIRCLE) { + IMAGE_CIRCLE.x = (double) p.x - IMG_MARKER_RADIUS; + IMAGE_CIRCLE.y = (double) p.y - IMG_MARKER_RADIUS; + g.fill(IMAGE_CIRCLE); + } + + // Paint highlight for selected or highlighted images + if (getData().getHighlightedImages().contains(img) || img.equals(getData().getHighlightedImage()) + || getData().getMultiSelectedImages().contains(img)) { + g.setColor(Color.WHITE); + g.setStroke(new BasicStroke(2)); + g.drawOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); + } + + if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { + g.drawImage(YIELD_SIGN, (int) (p.getX() - TRAFFIC_SIGN_SIZE / 2d), (int) (p.getY() - TRAFFIC_SIGN_SIZE / 2d), + null); } g.setComposite(composite); } From d25e6ff2bcac02072270ce4ef67d1f8d0b01afff Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Thu, 30 Apr 2020 16:46:40 -0600 Subject: [PATCH 11/20] Fix JOSM-19175 Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../plugins/mapillary/MapillaryPlugin.java | 7 ++++++- .../actions/MapillaryDownloadAction.java | 18 +++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java index f87b96682..3cdeecc13 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java @@ -65,6 +65,8 @@ public class MapillaryPlugin extends Plugin implements Destroyable { private final List<Destroyable> destroyables = new ArrayList<>(); + private MapillaryDownloadAction mapillaryDownloadAction; + /** * Main constructor. * @@ -84,7 +86,8 @@ public MapillaryPlugin(PluginInformation info) { MainMenu.add(menu.fileMenu, mapillaryExportAction, false, 14); destroyables.add(mapillaryExportAction); - MapillaryDownloadAction mapillaryDownloadAction = new MapillaryDownloadAction(); + mapillaryDownloadAction = new MapillaryDownloadAction(); + mapillaryDownloadAction.setEnabled(false); MainMenu.add(menu.imagerySubMenu, mapillaryDownloadAction, false); destroyables.add(mapillaryDownloadAction); @@ -152,6 +155,7 @@ public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { newFrame.addToggleDialog(MapillaryFilterDialog.getInstance(), false); newFrame.addToggleDialog(MapillaryExpertFilterDialog.getInstance(), true); toggleDialog.add(MapillaryExpertFilterDialog.getInstance()); + mapillaryDownloadAction.setEnabled(true); // This fixes a UI issue -- for whatever reason, the tab pane is occasionally unusable when the expert filter // dialog is added. newFrame.conflictDialog.getToggleAction().actionPerformed(null); @@ -159,6 +163,7 @@ public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { } else if (oldFrame != null && newFrame == null) { // map frame removed toggleDialog.forEach(ToggleDialog::destroy); toggleDialog.clear(); + mapillaryDownloadAction.setEnabled(false); } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java index 0fbcbeea1..faead9518 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java @@ -37,19 +37,19 @@ public class MapillaryDownloadAction extends JosmAction { */ public MapillaryDownloadAction() { super( - tr("Mapillary"), - new ImageProvider(MapillaryPlugin.LOGO).setSize(ImageSizes.DEFAULT), - tr("Open Mapillary layer"), - SHORTCUT, - false, - "mapillaryDownload", - false - ); + tr("Mapillary"), + new ImageProvider(MapillaryPlugin.LOGO).setSize(ImageSizes.DEFAULT), + tr("Open Mapillary layer"), + SHORTCUT, + false, + "mapillaryDownload", + false); } @Override public void actionPerformed(ActionEvent ae) { - if (!MapillaryLayer.hasInstance() || !MainApplication.getLayerManager().containsLayer(MapillaryLayer.getInstance())) { + if ((!MapillaryLayer.hasInstance() + || !MainApplication.getLayerManager().containsLayer(MapillaryLayer.getInstance()))) { LayerListModel model = LayerListDialog.getInstance().getModel(); model.getLayerManager().addLayer(MapillaryLayer.getInstance()); List<Layer> selected = model.getSelectedLayers(); From 9a5d3cb67208538e1d044dca0be92bb34e746ab2 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Thu, 7 May 2020 08:06:10 -0600 Subject: [PATCH 12/20] FIXUP: EDT violation Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../mapillary/io/download/BoundsDownloadRunnable.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/BoundsDownloadRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/BoundsDownloadRunnable.java index 1c1c5d16e..86cac40f4 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/BoundsDownloadRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/io/download/BoundsDownloadRunnable.java @@ -13,10 +13,9 @@ import java.util.concurrent.RecursiveAction; import java.util.function.Function; -import javax.swing.SwingUtilities; - import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.gui.Notification; +import org.openstreetmap.josm.gui.util.GuiHelper; import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; import org.openstreetmap.josm.plugins.mapillary.oauth.OAuthUtils; @@ -70,18 +69,14 @@ private void realRun(URL currentUrl) { String message = I18n.tr("Could not read from URL {0}!", currentUrl.toString()); Logging.log(Logging.LEVEL_WARN, message, e); if (!GraphicsEnvironment.isHeadless()) { - if (SwingUtilities.isEventDispatchThread()) { - showNotification(message); - } else { - SwingUtilities.invokeLater(() -> showNotification(message)); - } + GuiHelper.runInEDT(() -> showNotification(message)); } } } private static void showNotification(String message) { new Notification(message).setIcon(MapillaryPlugin.LOGO.setSize(ImageSizes.LARGEICON).get()) - .setDuration(Notification.TIME_LONG).show(); + .setDuration(Notification.TIME_LONG).show(); } /** From 53bdf5831f4895c53bb0ac8a8e3eff0b6faf3f1c Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Wed, 6 May 2020 07:38:13 -0600 Subject: [PATCH 13/20] Attempt to avoid caching too many images into memory Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../josm/plugins/mapillary/MapillaryData.java | 27 +++++++++++++---- .../josm/plugins/mapillary/cache/Caches.java | 23 ++++++++++----- .../mapillary/cache/MapillaryCache.java | 29 +++++++++++++++---- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java index 89de5c96a..ee32057f2 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java @@ -15,6 +15,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.json.Json; import javax.json.JsonException; @@ -31,6 +32,7 @@ import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.plugins.mapillary.cache.CacheUtils; import org.openstreetmap.josm.plugins.mapillary.cache.Caches; +import org.openstreetmap.josm.plugins.mapillary.cache.MapillaryCache; import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryMainDialog; import org.openstreetmap.josm.plugins.mapillary.gui.imageinfo.ImageInfoPanel; import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; @@ -353,25 +355,35 @@ public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) { */ public static boolean inCurrentlySelectedDetection(MapillaryImage image) { return MainApplication.getLayerManager().getLayersOfType(PointObjectLayer.class).parallelStream() - .map(PointObjectLayer::getDataSet).flatMap(d -> d.getSelected().parallelStream()) - .filter(p -> p.hasTag("detections")) - .flatMap(p -> PointObjectLayer.parseDetections(p.get("detections")).parallelStream()) - .anyMatch(p -> image.getKey().equals(p.getOrDefault("image_key", null))); + .map(PointObjectLayer::getDataSet).flatMap(d -> d.getSelected().parallelStream()) + .filter(p -> p.hasTag("detections")) + .flatMap(p -> PointObjectLayer.parseDetections(p.get("detections")).parallelStream()) + .anyMatch(p -> image.getKey().equals(p.getOrDefault("image_key", null))); } /** * Downloads surrounding images of this mapillary image in background threads + * * @param mapillaryImage the image for which the surrounding images should be downloaded */ private static void downloadSurroundingImages(MapillaryImage mapillaryImage) { MainApplication.worker.execute(() -> { final int prefetchCount = MapillaryProperties.PRE_FETCH_IMAGE_COUNT.get(); - CacheAccess<String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache(); + CacheAccess<String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance() + .getCache(MapillaryCache.Type.FULL_IMAGE); MapillaryAbstractImage nextImage = mapillaryImage.next(); MapillaryAbstractImage prevImage = mapillaryImage.previous(); + long freeMemory = Runtime.getRuntime().freeMemory(); + // 3 bytes for RGB (jpg doesn't support the Alpha channel). I'm using 4 bytes instead of 3 for a buffer. + long estimatedImageSize = Stream.of(MapillaryCache.Type.values()).mapToLong(v -> v.getHeight() * v.getWidth() * 4) + .sum(); + for (int i = 0; i < prefetchCount; i++) { + if (freeMemory - estimatedImageSize < 0) { + break; // It doesn't make sense to try to cache images that won't be kept. + } if (nextImage != null) { if ((nextImage instanceof MapillaryImage) && (imageCache.get(((MapillaryImage) nextImage).getKey()) == null)) { @@ -386,6 +398,11 @@ private static void downloadSurroundingImages(MapillaryImage mapillaryImage) { } prevImage = prevImage.previous(); } + imageCache.getCacheControl(); + imageCache.get(mapillaryImage.getKey()); + if (mapillaryImage.next() != null) { + imageCache.get(mapillaryImage.getKey()); + } } }); } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java index f1ddb0910..70a33adf1 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java @@ -12,7 +12,9 @@ import org.openstreetmap.josm.data.Preferences; import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; import org.openstreetmap.josm.data.cache.JCSCacheManager; +import org.openstreetmap.josm.plugins.mapillary.cache.MapillaryCache.Type; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; +import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; public final class Caches { @@ -50,11 +52,18 @@ public void put(final K key, final V value) { public static class ImageCache { private static ImageCache instance; - private final CacheAccess<String, BufferedImageCacheEntry> cache = - JCSCacheManager.getCache("mapillary", 10, 10000, getCacheDirectory().getPath()); - - public CacheAccess<String, BufferedImageCacheEntry> getCache() { - return cache; + private final CacheAccess<String, BufferedImageCacheEntry> thumbnailCache = JCSCacheManager.getCache( + "mapillary:thumbnailImage", + Math.max(3 * MapillaryProperties.PRE_FETCH_IMAGE_COUNT.get(), 10), 10000, getCacheDirectory().getPath()); + private final CacheAccess<String, BufferedImageCacheEntry> imageCache = JCSCacheManager + .getCache("mapillary:fullImage", Math.max(2 * MapillaryProperties.PRE_FETCH_IMAGE_COUNT.get() + 4, 10), 10_000, + getCacheDirectory().getPath()); + + public CacheAccess<String, BufferedImageCacheEntry> getCache(Type type) { + if (Type.THUMBNAIL.equals(type)) { + return thumbnailCache; + } + return imageCache; } public static ImageCache getInstance() { @@ -99,8 +108,8 @@ public static CacheProxy<String, UserProfile> getInstance() { @Override protected CacheAccess<String, UserProfile> createNewCache() { - CacheAccess<String, UserProfile> cache = - JCSCacheManager.getCache("userProfile", 100, 1000, getCacheDirectory().getPath()); + CacheAccess<String, UserProfile> cache = JCSCacheManager.getCache("userProfile", 100, 1000, + getCacheDirectory().getPath()); IElementAttributes atts = cache.getDefaultElementAttributes(); atts.setMaxLife(604_800_000); // Sets lifetime to 7 days (604800000=1000*60*60*24*7) cache.setDefaultElementAttributes(atts); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java index 79ae7193b..6208f721d 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java @@ -28,22 +28,39 @@ public class MapillaryCache extends JCSCachedTileLoaderJob<String, BufferedImage */ public enum Type { /** Full quality image */ - FULL_IMAGE, + FULL_IMAGE(2048), /** Low quality image */ - THUMBNAIL + THUMBNAIL(320); + + private int width; + + private Type(int dimension) { + this.width = dimension; + } + + /** Get the anticipated width for the image */ + public int getWidth() { + return width; + } + + /** Get the anticipated height for the image */ + public int getHeight() { + return width; + } } /** * Main constructor. * * @param key - * The key of the image. + * The key of the image. * @param type - * The type of image that must be downloaded (THUMBNAIL or - * FULL_IMAGE). + * The type of image that must be downloaded (THUMBNAIL or + * FULL_IMAGE). */ public MapillaryCache(final String key, final Type type) { - super(Caches.ImageCache.getInstance().getCache(), new TileJobOptions(50_000, 50_000, new HashMap<>(), TimeUnit.HOURS.toSeconds(4))); + super(Caches.ImageCache.getInstance().getCache(type), + new TileJobOptions(50_000, 50_000, new HashMap<>(), TimeUnit.HOURS.toSeconds(4))); if (key == null || type == null) { this.key = null; this.url = null; From b43b6d7f66c51ee6a180938748fc997924cdf657 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Wed, 6 May 2020 07:43:09 -0600 Subject: [PATCH 14/20] Modify datepicker to catch a (potential) exception from JavaFX (depends upon JOSM-19169) Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../josm/plugins/mapillary/gui/DatePickerFx.java | 3 ++- .../josm/plugins/mapillary/gui/IDatePicker.java | 12 ++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/DatePickerFx.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/DatePickerFx.java index 0dbe635d1..f2c6e0ebf 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/DatePickerFx.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/DatePickerFx.java @@ -3,6 +3,7 @@ import java.awt.Dimension; import java.time.LocalDate; +import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import javafx.event.ActionEvent; @@ -34,7 +35,7 @@ public LocalDate fromString(String date) { } - public DatePickerFx() { + public DatePickerFx() throws ExecutionException { super(DatePicker.class); this.getNode().setConverter(new LocalDateConverterJavaFX()); GuiHelper.runInEDT(() -> { diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/IDatePicker.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/IDatePicker.java index 45df18318..45c0159d8 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/IDatePicker.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/IDatePicker.java @@ -2,6 +2,7 @@ package org.openstreetmap.josm.plugins.mapillary.gui; import java.time.LocalDate; +import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import javax.swing.JComponent; @@ -23,20 +24,15 @@ public interface IDatePicker<T extends JComponent> { void addEventHandler(Consumer<IDatePicker<?>> function); - public static IDatePicker<? extends JComponent> getNewDatePicker() { - boolean fx = false; + static IDatePicker<? extends JComponent> getNewDatePicker() { boolean useFx = MapillaryProperties.JAVA_FX.get(); if (useFx) { try { - new DatePickerFx(); - fx = true; - } catch (UnsupportedClassVersionError e) { + return new DatePickerFx(); + } catch (NoClassDefFoundError | UnsupportedClassVersionError | ExecutionException e) { Logging.error(e); } } - if (fx) { - return new DatePickerFx(); - } return new DatePickerSwing(); } } From 0cebfa4e27b401955dc9704c7c8caad119a9bb5c Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Thu, 7 May 2020 08:02:54 -0600 Subject: [PATCH 15/20] Use Mapillary-provided images for sprites Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../mapillary/MapillaryAbstractImage.java | 41 ++++++++-- .../plugins/mapillary/MapillaryImage.java | 26 +++--- .../mapillary/MapillaryImportedImage.java | 28 +++---- .../mapillary/gui/layer/MapillaryLayer.java | 80 +++++++++---------- .../resources/images/josm-ca/current-ca.svg | 73 +++++++++++++++++ .../images/josm-ca/default-ca-hover.svg | 73 +++++++++++++++++ .../resources/images/josm-ca/default-ca.svg | 73 +++++++++++++++++ .../images/josm-ca/private-ca-hover.svg | 73 +++++++++++++++++ .../resources/images/josm-ca/private-ca.svg | 72 +++++++++++++++++ .../images/josm-ca/sequence-ca-hover.svg | 73 +++++++++++++++++ .../resources/images/josm-ca/sequence-ca.svg | 72 +++++++++++++++++ .../images/josm-ca/sign-detection.svg | 63 +++++++++++++++ .../plugins/mapillary/oauth/UploadTest.java | 4 + 13 files changed, 672 insertions(+), 79 deletions(-) create mode 100644 src/main/resources/images/josm-ca/current-ca.svg create mode 100644 src/main/resources/images/josm-ca/default-ca-hover.svg create mode 100644 src/main/resources/images/josm-ca/default-ca.svg create mode 100644 src/main/resources/images/josm-ca/private-ca-hover.svg create mode 100644 src/main/resources/images/josm-ca/private-ca.svg create mode 100644 src/main/resources/images/josm-ca/sequence-ca-hover.svg create mode 100644 src/main/resources/images/josm-ca/sequence-ca.svg create mode 100644 src/main/resources/images/josm-ca/sign-detection.svg diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java index 8e2c0e071..919233134 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java @@ -2,15 +2,19 @@ package org.openstreetmap.josm.plugins.mapillary; import java.awt.Color; +import java.awt.Image; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; +import javax.swing.ImageIcon; + import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.gpx.GpxImageEntry; import org.openstreetmap.josm.plugins.mapillary.utils.LocalDateConverter; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; +import org.openstreetmap.josm.tools.ImageProvider; /** * Abstract superclass for all image objects. At the moment there are just 2, @@ -20,6 +24,18 @@ * */ public abstract class MapillaryAbstractImage extends GpxImageEntry { + /** The common directory for the Mapillary image sprites (for Mapillary Images) */ + protected static final String IMAGE_SPRITE_DIR = "josm-ca"; + /** The default sprite for a Mapillary image */ + protected static final ImageIcon DEFAULT_SPRITE = new ImageProvider(IMAGE_SPRITE_DIR, "default-ca") + .setMaxWidth(ImageProvider.ImageSizes.MAP.getAdjustedHeight()).get(); + /** The sprite to use for the active Mapillary sequence */ + public static final ImageIcon ACTIVE_SEQUENCE_SPRITE = new ImageProvider(IMAGE_SPRITE_DIR, "sequence-ca") + .setMaxWidth(ImageProvider.ImageSizes.MAP.getAdjustedHeight()).get(); + /** The sprite to use for the currently selected image */ + public static final ImageIcon SELECTED_IMAGE = new ImageProvider(IMAGE_SPRITE_DIR, "current-ca") + .setMaxWidth(ImageProvider.ImageSizes.MAP.getAdjustedHeight()).get(); + /** * If two values for field ca differ by less than EPSILON both values are considered equal. */ @@ -314,15 +330,28 @@ public void turn(final double ca) { this.movingCa = this.tempCa + ca; } - public abstract Color paintHighlightedColour(); - public abstract Color paintHighlightedAngleColour(); - public abstract Color paintSelectedColour(); - public abstract Color paintSelectedAngleColour(); - public abstract Color paintUnselectedColour(); - public abstract Color paintUnselectedAngleColour(); + + /** + * @return The default image to represent this particular type of image + */ + public abstract Image getDefaultImage(); + + /** + * @return The default image to indicate that this particular image is selected + */ + public Image getSelectedImage() { + return SELECTED_IMAGE.getImage(); + } + + /** + * @return The image to indicate that the current sequence is active + */ + public Image getActiveSequenceImage() { + return ACTIVE_SEQUENCE_SPRITE.getImage(); + } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java index 858065c82..e5ad1e808 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java @@ -2,17 +2,21 @@ package org.openstreetmap.josm.plugins.mapillary; import java.awt.Color; +import java.awt.Image; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import javax.swing.ImageIcon; + import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.gpx.GpxImageEntry; import org.openstreetmap.josm.plugins.mapillary.gui.layer.MapillaryLayer; import org.openstreetmap.josm.plugins.mapillary.model.ImageDetection; import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryColorScheme; +import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.Logging; /** @@ -36,6 +40,10 @@ public class MapillaryImage extends MapillaryAbstractImage { */ private final boolean privateImage; + /** The default sprite for a private Mapillary image */ + public static final ImageIcon PRIVATE_SPRITE = new ImageProvider(IMAGE_SPRITE_DIR, "private-ca") + .setMaxWidth(ImageProvider.ImageSizes.MAP.getAdjustedHeight()).get(); + /** * Main constructor of the class MapillaryImage * @@ -125,33 +133,23 @@ public void turn(double ca) { checkModified(); } - @Override - public Color paintHighlightedColour() { - return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_HIGHLIGHTED : MapillaryColorScheme.SEQ_HIGHLIGHTED; - } - @Override public Color paintHighlightedAngleColour() { return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_HIGHLIGHTED_CA : MapillaryColorScheme.SEQ_HIGHLIGHTED_CA; } - @Override - public Color paintSelectedColour() { - return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_SELECTED : MapillaryColorScheme.SEQ_SELECTED; - } - @Override public Color paintSelectedAngleColour() { return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_SELECTED_CA : MapillaryColorScheme.SEQ_SELECTED_CA; } @Override - public Color paintUnselectedColour() { - return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_UNSELECTED : MapillaryColorScheme.SEQ_UNSELECTED; + public Color paintUnselectedAngleColour() { + return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_UNSELECTED_CA : MapillaryColorScheme.SEQ_UNSELECTED_CA; } @Override - public Color paintUnselectedAngleColour() { - return privateImage ? MapillaryColorScheme.SEQ_PRIVATE_UNSELECTED_CA : MapillaryColorScheme.SEQ_UNSELECTED_CA; + public Image getDefaultImage() { + return privateImage ? PRIVATE_SPRITE.getImage() : DEFAULT_SPRITE.getImage(); } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java index cc165eb70..7b0753df2 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java @@ -2,6 +2,7 @@ package org.openstreetmap.josm.plugins.mapillary; import java.awt.Color; +import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; @@ -52,12 +53,14 @@ public MapillaryImportedImage(final LatLon latLon, final double ca, final File f * @param datetimeOriginal The date the picture was taken. * @param pano The property to indicate whether image is panorama or not. */ - public MapillaryImportedImage(final LatLon latLon, final double ca, final File file, final boolean pano, final String datetimeOriginal) { + public MapillaryImportedImage(final LatLon latLon, final double ca, final File file, final boolean pano, + final String datetimeOriginal) { this(latLon, ca, file, pano, parseTimestampElseCurrentTime(datetimeOriginal)); } /** * Constructs a new image from an image entry of a {@link GeoImageLayer}. + * * @param geoImage the {@link ImageEntry}, from which the corresponding fields are taken * @return new image */ @@ -81,7 +84,7 @@ public static MapillaryImportedImage createInstance(final ImageEntry geoImage) { boolean pano = false; try (FileInputStream fis = new FileInputStream(geoImage.getFile())) { pano = ImageMetaDataUtil.isPanorama(fis); - } catch(IOException ex) { + } catch (IOException ex) { Logging.trace(ex); } return new MapillaryImportedImage(coord, ca, geoImage.getFile(), pano, time); @@ -99,7 +102,8 @@ private static long parseTimestampElseCurrentTime(final String timestamp) { } } - public MapillaryImportedImage(final LatLon latLon, final double ca, final File file, final boolean pano, final long capturedAt) { + public MapillaryImportedImage(final LatLon latLon, final double ca, final File file, final boolean pano, + final long capturedAt) { super(latLon, ca, pano); super.setFile(file); this.capturedAt = capturedAt; @@ -156,34 +160,24 @@ public boolean equals(Object obj) { return true; } - @Override - public Color paintHighlightedColour() { - return MapillaryColorScheme.SEQ_IMPORTED_HIGHLIGHTED; - } - @Override public Color paintHighlightedAngleColour() { return MapillaryColorScheme.SEQ_IMPORTED_HIGHLIGHTED_CA; } - @Override - public Color paintSelectedColour() { - return MapillaryColorScheme.SEQ_IMPORTED_SELECTED; - } - @Override public Color paintSelectedAngleColour() { return MapillaryColorScheme.SEQ_IMPORTED_SELECTED_CA; } @Override - public Color paintUnselectedColour() { - return MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED; + public Color paintUnselectedAngleColour() { + return MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED_CA; } @Override - public Color paintUnselectedAngleColour() { - return MapillaryColorScheme.SEQ_IMPORTED_UNSELECTED_CA; + public Image getDefaultImage() { + return DEFAULT_SPRITE.getImage(); } } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index c8152cd12..5dda447a0 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -13,8 +13,9 @@ import java.awt.RenderingHints; import java.awt.TexturePaint; import java.awt.event.ActionEvent; -import java.awt.geom.Ellipse2D; +import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; +import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.util.Collection; import java.util.Collections; @@ -31,7 +32,6 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; @@ -105,33 +105,15 @@ public final class MapillaryLayer extends AbstractModifiableLayer implements private static final int IMG_MARKER_RADIUS = 7; /** The radius of the circular sector that indicates the camera angle */ private static final int CA_INDICATOR_RADIUS = 15; - /** The angle of the circular sector that indicates the camera angle */ - private static final int CA_INDICATOR_ANGLE = 40; /** Length of the edge of the small sign, which indicates that traffic signs have been found in an image. */ - private static final int TRAFFIC_SIGN_SIZE = 6; - /** A third of the height of the sign, for easier calculations */ - private static final double TRAFFIC_SIGN_HEIGHT_3RD = Math.sqrt( - Math.pow(TRAFFIC_SIGN_SIZE, 2) - Math.pow(TRAFFIC_SIGN_SIZE / 2d, 2)) / 3; + private static final int TRAFFIC_SIGN_SIZE = ImageProvider.ImageSizes.MAP.getAdjustedWidth(); /** The range to paint the full detection image at */ private static final Range IMAGE_CA_PAINT_RANGE = Selector.GeneralSelector.fromLevel(18, Integer.MAX_VALUE); - /** A shape to avoid many calculations */ - private static final Ellipse2D.Double IMAGE_CIRCLE = new Ellipse2D.Double(0, 0, 2 * IMG_MARKER_RADIUS, - 2 * IMG_MARKER_RADIUS); - - /** The default sprite for a Mapillary image */ - public static final ImageIcon DEFAULT_SPRITE = ImageProvider.get("mapillary_sprite_source/package_ui", "regular-0", - ImageProvider.ImageSizes.MAPMAX); - /** The sprite to use for the active Mapillary sequence */ - public static final ImageIcon ACTIVE_SEQUENCE_SPRITE = ImageProvider.get("mapillary_sprite_source/package_ui", - "active-ca-0", ImageProvider.ImageSizes.MAPMAX); - /** The sprite to use for the currently selected image */ - public static final ImageIcon SELECTED_IMAGE = ImageProvider.get("mapillary_sprite_source/package_ui", "cur-ca-0", - ImageProvider.ImageSizes.MAPMAX); + /** The sprite to use to indicate that there are sign detections in the image */ - private static final Image YIELD_SIGN = new ImageProvider("mapillary_sprite_source/package_signs", - "regulatory--yield--g1") - .setMaxSize(TRAFFIC_SIGN_SIZE).get() - .getImage(); + private static final Image YIELD_SIGN = new ImageProvider("josm-ca", "sign-detection") + .setMaxSize(TRAFFIC_SIGN_SIZE).get() + .getImage(); private static class DataSetSourceListener implements DataSourceListener { @Override @@ -159,6 +141,7 @@ public void dataSourceChange(DataSourceChangeEvent event) { private final MapillaryLocationChangeset locationChangeset = new MapillaryLocationChangeset(); private static AlphaComposite fadeComposite = AlphaComposite .getInstance(AlphaComposite.SRC_OVER, MapillaryProperties.UNSELECTED_OPACITY.get().floatValue()); + private static Point2D standardImageCentroid = null; private MapillaryLayer() { super(I18n.tr("Mapillary Images")); @@ -445,39 +428,41 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im g.setComposite(fadeComposite); } // Determine colors - final Color markerC; final Color directionC; + final Image i; if (selectedImg != null && getData().getMultiSelectedImages().contains(img)) { - markerC = img.paintHighlightedColour(); + i = img.getSelectedImage(); directionC = img.paintHighlightedAngleColour(); } else if (selectedImg != null && selectedImg.getSequence() != null && selectedImg.getSequence().equals(img.getSequence())) { - markerC = img.paintSelectedColour(); directionC = img.paintSelectedAngleColour(); + i = img.getActiveSequenceImage(); } else { - markerC = img.paintUnselectedColour(); + i = img.getDefaultImage(); directionC = img.paintUnselectedAngleColour(); } - // Paint direction indicator g.setColor(directionC); if (img.isPanorama()) { + Composite currentComposit = g.getComposite(); + g.setComposite(fadeComposite); g.fillOval(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS); - } else { - g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, - 2 * CA_INDICATOR_RADIUS, - (int) (90 - img.getMovingCa() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); - } - // Paint image marker - g.setColor(markerC); - g.setPaint(markerC); - synchronized (IMAGE_CIRCLE) { - IMAGE_CIRCLE.x = (double) p.x - IMG_MARKER_RADIUS; - IMAGE_CIRCLE.y = (double) p.y - IMG_MARKER_RADIUS; - g.fill(IMAGE_CIRCLE); + g.setComposite(currentComposit); } + double angle = Math.toRadians(img.getMovingCa()); + AffineTransform backup = g.getTransform(); + Point2D originalCentroid = getOriginalCentroid(i); + AffineTransform move = AffineTransform.getRotateInstance(angle, p.getX(), p.getY()); + move.translate(-originalCentroid.getX(), -originalCentroid.getY()); + Point2D.Double d2 = new Point2D.Double(p.x + originalCentroid.getX(), p.y + originalCentroid.getY()); + move.transform(d2, d2); + g.setTransform(move); + + g.drawImage(i, p.x, p.y, null); + g.setTransform(backup); + // Paint highlight for selected or highlighted images if (getData().getHighlightedImages().contains(img) || img.equals(getData().getHighlightedImage()) || getData().getMultiSelectedImages().contains(img)) { @@ -493,6 +478,17 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im g.setComposite(composite); } + private static Point2D getOriginalCentroid(Image i) { + if (standardImageCentroid == null) { + int width = i.getWidth(null); + int height = i.getHeight(null); + double originalCentroidX = width / 2d; + double originalCentroidY = 2 * height / 3d; + standardImageCentroid = new Point2D.Double(originalCentroidX, originalCentroidY); + } + return standardImageCentroid; + } + @Override public Icon getIcon() { return MapillaryPlugin.LOGO.setSize(ImageSizes.LAYER).get(); diff --git a/src/main/resources/images/josm-ca/current-ca.svg b/src/main/resources/images/josm-ca/current-ca.svg new file mode 100644 index 000000000..75923fbb6 --- /dev/null +++ b/src/main/resources/images/josm-ca/current-ca.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="4.2333288mm" + height="6.0854163mm" + viewBox="0 0 4.2333288 6.0854163" + version="1.1" + id="svg2725" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + sodipodi:docname="current-ca.svg"> + <defs + id="defs2719" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="9.0390037" + inkscape:cx="1.8530716" + inkscape:cy="12.440369" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="907" + inkscape:window-x="204" + inkscape:window-y="123" + inkscape:window-maximized="0" /> + <metadata + id="metadata2722"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-93.124201,-86.88786)"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 93.766609,87.170726 1.474259,3.685884 1.474258,-3.685884 c -0.455612,-0.182483 -0.953294,-0.282866 -1.474258,-0.282866 -0.520965,0 -1.018646,0.100383 -1.474259,0.282866 z" + fill="#F5B81A" + id="path859" /> + <path + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 95.240868,92.708693 c 1.022879,0 1.852078,-0.829204 1.852078,-1.852083 0,-1.022879 -0.829199,-1.852083 -1.852078,-1.852083 -1.022879,0 -1.852084,0.829204 -1.852084,1.852083 0,1.022879 0.829205,1.852083 1.852084,1.852083 z" + fill="#F5811A" + stroke="white" + stroke-width="1" + id="path861" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/default-ca-hover.svg b/src/main/resources/images/josm-ca/default-ca-hover.svg new file mode 100644 index 000000000..624ec32b4 --- /dev/null +++ b/src/main/resources/images/josm-ca/default-ca-hover.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="default-ca-hover.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg2081" + version="1.1" + viewBox="0 0 4.2333336 6.0854235" + height="6.0854235mm" + width="4.2333336mm"> + <defs + id="defs2075" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="61" + inkscape:window-x="2100" + inkscape:window-height="907" + inkscape:window-width="1600" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="11.500013" + inkscape:cx="8.0000005" + inkscape:zoom="30.39127" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata2078"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-84.817857,-165.53467)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 85.460186,165.81754 1.474364,3.68588 1.474338,-3.68588 c -0.455798,-0.18248 -0.953347,-0.28287 -1.474338,-0.28287 -0.520991,0 -1.01854,0.10039 -1.474364,0.28287 z" + fill="#187A45" + id="path875" /> + <path + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 86.934524,171.35551 c 1.022879,0 1.852083,-0.82921 1.852083,-1.85209 0,-1.02288 -0.829204,-1.85208 -1.852083,-1.85208 -1.022879,0 -1.852084,0.8292 -1.852084,1.85208 0,1.02288 0.829205,1.85209 1.852084,1.85209 z" + fill="#05CB63" + stroke="white" + stroke-width="2" + id="path877" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/default-ca.svg b/src/main/resources/images/josm-ca/default-ca.svg new file mode 100644 index 000000000..c04a86db3 --- /dev/null +++ b/src/main/resources/images/josm-ca/default-ca.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="3.7041659mm" + height="5.8208399mm" + viewBox="0 0 3.7041659 5.8208399" + version="1.1" + id="svg1476" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + sodipodi:docname="default-ca.svg"> + <defs + id="defs1470" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.772691" + inkscape:cx="6.8408291" + inkscape:cy="11.818325" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="907" + inkscape:window-x="0" + inkscape:window-y="23" + inkscape:window-maximized="0" /> + <metadata + id="metadata1473"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-93.397917,-101.41101)"> + <path + id="path871" + fill="#187A45" + d="m 93.775662,101.69389 1.474364,3.68587 1.474338,-3.68587 c -0.455798,-0.18249 -0.953347,-0.28288 -1.474338,-0.28288 -0.520991,0 -1.01854,0.10039 -1.474364,0.28288 z" + clip-rule="evenodd" + fill-rule="evenodd" + inkscape:connector-curvature="0" + style="stroke-width:0.264583" /> + <circle + clip-rule="evenodd" + fill-rule="evenodd" + id="circle873" + fill="#05CB63" + style="stroke-width:0.264583" + r="1.8669461" + cy="105.37702" + cx="95.253685" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/private-ca-hover.svg b/src/main/resources/images/josm-ca/private-ca-hover.svg new file mode 100644 index 000000000..418484843 --- /dev/null +++ b/src/main/resources/images/josm-ca/private-ca-hover.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="private-ca-hover.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg1492" + version="1.1" + viewBox="0 0 4.2333336 6.0854135" + height="6.0854135mm" + width="4.2333336mm"> + <defs + id="defs1486" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="100" + inkscape:window-x="297" + inkscape:window-height="907" + inkscape:window-width="1600" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="11.499994" + inkscape:cx="8.0000006" + inkscape:zoom="30.391321" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata1489"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-87.841667,-120.17753)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 88.483996,120.4604 1.474364,3.68588 1.474337,-3.68588 c -0.455797,-0.18249 -0.953346,-0.28287 -1.474337,-0.28287 -0.520991,0 -1.01854,0.10038 -1.474364,0.28287 z" + fill="#6236FF" + id="path855" /> + <path + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 89.958333,125.99836 c 1.022879,0 1.852084,-0.8292 1.852084,-1.85208 0,-1.02288 -0.829205,-1.85208 -1.852084,-1.85208 -1.022879,0 -1.852083,0.8292 -1.852083,1.85208 0,1.02288 0.829204,1.85208 1.852083,1.85208 z" + fill="#8F89F5" + stroke="white" + stroke-width="2" + id="path857" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/private-ca.svg b/src/main/resources/images/josm-ca/private-ca.svg new file mode 100644 index 000000000..56f87410d --- /dev/null +++ b/src/main/resources/images/josm-ca/private-ca.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="private-ca.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg887" + version="1.1" + viewBox="0 0 3.70417 5.8208332" + height="5.8208332mm" + width="3.70417mm"> + <defs + id="defs881" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="23" + inkscape:window-x="0" + inkscape:window-height="907" + inkscape:window-width="1600" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="10.999999" + inkscape:cx="7.0000063" + inkscape:zoom="31.772729" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata884"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-119.85625,-65.88125)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 120.234,66.164129 1.47436,3.685871 1.47434,-3.685871 c -0.4558,-0.182491 -0.95335,-0.282879 -1.47434,-0.282879 -0.52099,0 -1.01854,0.100388 -1.47436,0.282879 z" + fill="#6236FF" + id="path851" /> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 121.70833,71.702083 c 1.02288,0 1.85209,-0.829204 1.85209,-1.852083 0,-1.022879 -0.82921,-1.852083 -1.85209,-1.852083 -1.02288,0 -1.85208,0.829204 -1.85208,1.852083 0,1.022879 0.8292,1.852083 1.85208,1.852083 z" + fill="#8F89F5" + id="path853" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/sequence-ca-hover.svg b/src/main/resources/images/josm-ca/sequence-ca-hover.svg new file mode 100644 index 000000000..4fc032b4f --- /dev/null +++ b/src/main/resources/images/josm-ca/sequence-ca-hover.svg @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="sequence-ca-hover.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg3316" + version="1.1" + viewBox="0 0 4.2333326 6.0854235" + height="6.0854235mm" + width="4.2333326mm"> + <defs + id="defs3310" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="103" + inkscape:window-x="2057" + inkscape:window-height="907" + inkscape:window-width="1690" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="11.500013" + inkscape:cx="7.9999987" + inkscape:zoom="30.39127" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata3313"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-95.401191,-149.65967)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 96.043519,149.94254 1.474365,3.68588 1.474337,-3.68588 c -0.455797,-0.18248 -0.953346,-0.28287 -1.474337,-0.28287 -0.520991,0 -1.01854,0.10039 -1.474365,0.28287 z" + fill="#00769D" + id="path885" /> + <path + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 97.517857,155.48051 c 1.022879,0 1.852083,-0.82921 1.852083,-1.85209 0,-1.02288 -0.829204,-1.85208 -1.852083,-1.85208 -1.022879,0 -1.852083,0.8292 -1.852083,1.85208 0,1.02288 0.829204,1.85209 1.852083,1.85209 z" + fill="#00B5F5" + stroke="white" + stroke-width="2" + id="path887" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/sequence-ca.svg b/src/main/resources/images/josm-ca/sequence-ca.svg new file mode 100644 index 000000000..cbd6b31bf --- /dev/null +++ b/src/main/resources/images/josm-ca/sequence-ca.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="sequence-ca.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg2711" + version="1.1" + viewBox="0 0 3.7041659 5.8208342" + height="5.8208342mm" + width="3.7041659mm"> + <defs + id="defs2705" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="80" + inkscape:window-x="2095" + inkscape:window-height="907" + inkscape:window-width="1600" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="11.000002" + inkscape:cx="6.9999986" + inkscape:zoom="31.772723" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata2708"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-77.522917,-90.071726)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 77.900662,90.354605 1.474364,3.685871 1.474338,-3.685871 c -0.455798,-0.182491 -0.953347,-0.282879 -1.474338,-0.282879 -0.520991,0 -1.01854,0.100388 -1.474364,0.282879 z" + fill="#00769D" + id="path881" /> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + fill-rule="evenodd" + clip-rule="evenodd" + d="m 79.375,95.89256 c 1.022879,0 1.852083,-0.829205 1.852083,-1.852084 0,-1.022879 -0.829204,-1.852083 -1.852083,-1.852083 -1.022879,0 -1.852083,0.829204 -1.852083,1.852083 0,1.022879 0.829204,1.852084 1.852083,1.852084 z" + fill="#00B5F5" + id="path883" /> + </g> +</svg> diff --git a/src/main/resources/images/josm-ca/sign-detection.svg b/src/main/resources/images/josm-ca/sign-detection.svg new file mode 100644 index 000000000..8676a565b --- /dev/null +++ b/src/main/resources/images/josm-ca/sign-detection.svg @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="sign-detection.svg" + inkscape:version="1.0beta1 (32d4812, 2019-09-19)" + id="svg2121" + version="1.1" + viewBox="0 0 2.116426 1.8521025" + height="1.8521025mm" + width="2.116426mm"> + <defs + id="defs2115" /> + <sodipodi:namedview + inkscape:window-maximized="0" + inkscape:window-y="23" + inkscape:window-x="0" + inkscape:window-height="907" + inkscape:window-width="1600" + showgrid="false" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="3.5000343" + inkscape:cx="3.9995502" + inkscape:zoom="99.856111" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> + <metadata + id="metadata2118"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-140.30488,-92.812044)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <path + style="stroke-width:0.264583" + inkscape:connector-curvature="0" + d="m 141.3631,94.397479 -0.83027,-1.453144 h 1.66053 z" + fill="white" + stroke="#D40000" + id="path841" /> + </g> +</svg> diff --git a/test/unit/org/openstreetmap/josm/plugins/mapillary/oauth/UploadTest.java b/test/unit/org/openstreetmap/josm/plugins/mapillary/oauth/UploadTest.java index 2bb1284f6..6a9ad3599 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapillary/oauth/UploadTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapillary/oauth/UploadTest.java @@ -16,12 +16,14 @@ import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants; import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants; +import org.junit.Rule; import org.junit.Test; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage; import org.openstreetmap.josm.plugins.mapillary.utils.ImageImportUtil; import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryUtils; +import org.openstreetmap.josm.testutils.JOSMTestRules; /** * Tests the {@link UploadUtils} class. @@ -30,6 +32,8 @@ * @see UploadUtils */ public class UploadTest { + @Rule + public JOSMTestRules rule = new JOSMTestRules().projection(); /** * Tests the {@link UploadUtils#updateFile(MapillaryImportedImage)} method. From 4f99847a49d5372f3276a3c1a5f0ed5481e1d7b5 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Thu, 7 May 2020 08:05:40 -0600 Subject: [PATCH 16/20] Fix an issue where Mapillary servers being down would crash the plugin Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../data/mapillary/OrganizationRecord.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/data/mapillary/OrganizationRecord.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/data/mapillary/OrganizationRecord.java index f16c1eb39..c161d29ac 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/data/mapillary/OrganizationRecord.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/data/mapillary/OrganizationRecord.java @@ -41,8 +41,7 @@ public final class OrganizationRecord { private OrganizationRecord( String avatar, String description, String key, String name, String niceName, boolean privateRepository, - boolean publicRepository - ) { + boolean publicRepository) { this.avatar = createAvatarIcon(avatar, key); this.description = description; this.key = key; @@ -57,10 +56,9 @@ private static ImageIcon createAvatarIcon(String avatar, String organizationKey) return ImageProvider.get(avatar, ImageProvider.ImageSizes.DEFAULT); } else if (organizationKey != null && !organizationKey.isEmpty()) { try (CachedFile possibleAvatar = new CachedFile( - MapillaryURL.APIv3.retrieveOrganizationAvatar(organizationKey).toExternalForm() - )) { + MapillaryURL.APIv3.retrieveOrganizationAvatar(organizationKey).toExternalForm())) { OAuthUtils.addAuthenticationHeader(possibleAvatar); - return ImageProvider.get(possibleAvatar.getFile().getAbsolutePath(), ImageProvider.ImageSizes.DEFAULT); + return ImageProvider.getIfAvailable(possibleAvatar.getFile().getAbsolutePath()); } catch (IOException e) { Logging.error(e); } @@ -70,12 +68,10 @@ private static ImageIcon createAvatarIcon(String avatar, String organizationKey) public static OrganizationRecord getOrganization( String avatar, String description, String key, String name, String niceName, boolean privateRepository, - boolean publicRepository - ) { + boolean publicRepository) { boolean newRecord = !CACHE.containsKey(key); OrganizationRecord record = CACHE.computeIfAbsent( - key, k -> new OrganizationRecord(avatar, description, key, name, niceName, privateRepository, publicRepository) - ); + key, k -> new OrganizationRecord(avatar, description, key, name, niceName, privateRepository, publicRepository)); // TODO remove when getNewOrganization is done, and make vars final again record.avatar = createAvatarIcon(avatar, key); record.description = description; From 109c374038a36afe440b924940e46b8dfe0b2124 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Fri, 8 May 2020 09:39:00 -0600 Subject: [PATCH 17/20] Disable point features (again). Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../plugins/mapillary/MapillaryPlugin.java | 15 +++-- .../mapillary/gui/MapillaryMainDialog.java | 58 ++++++++++--------- .../gui/dialog/MapillaryFilterDialog.java | 34 +++++++---- .../mapillary/utils/MapillaryProperties.java | 2 + 4 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java index 3cdeecc13..580fe2e5b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java @@ -12,6 +12,7 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; +import org.openstreetmap.josm.actions.ExpertToggleAction; import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.MainMenu; @@ -116,9 +117,11 @@ public MapillaryPlugin(PluginInformation info) { MainMenu.add(menu.imagerySubMenu, mapObjectLayerAction, false); destroyables.add(mapObjectLayerAction); - MapPointObjectLayerAction mapPointObjectLayerAction = new MapPointObjectLayerAction(); - MainMenu.add(menu.imagerySubMenu, mapPointObjectLayerAction, false); - destroyables.add(mapPointObjectLayerAction); + if (ExpertToggleAction.isExpert() && Boolean.TRUE.equals(MapillaryProperties.DEVELOPER_BROKEN.get())) { + MapPointObjectLayerAction mapPointObjectLayerAction = new MapPointObjectLayerAction(); + MainMenu.add(menu.imagerySubMenu, mapPointObjectLayerAction, false); + destroyables.add(mapPointObjectLayerAction); + } mapFrameInitialized(null, MainApplication.getMap()); } @@ -153,8 +156,10 @@ public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { newFrame.addToggleDialog(MapillaryChangesetDialog.getInstance(), false); toggleDialog.add(MapillaryFilterDialog.getInstance()); newFrame.addToggleDialog(MapillaryFilterDialog.getInstance(), false); - newFrame.addToggleDialog(MapillaryExpertFilterDialog.getInstance(), true); - toggleDialog.add(MapillaryExpertFilterDialog.getInstance()); + if (ExpertToggleAction.isExpert() && Boolean.TRUE.equals(MapillaryProperties.DEVELOPER_BROKEN.get())) { + newFrame.addToggleDialog(MapillaryExpertFilterDialog.getInstance(), true); + toggleDialog.add(MapillaryExpertFilterDialog.getInstance()); + } mapillaryDownloadAction.setEnabled(true); // This fixes a UI issue -- for whatever reason, the tab pane is occasionally unusable when the expert filter // dialog is added. diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java index 33d6eeff7..5fa1d9e15 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryMainDialog.java @@ -14,8 +14,10 @@ import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.imageio.ImageIO; import javax.swing.AbstractAction; @@ -24,6 +26,7 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import org.openstreetmap.josm.actions.ExpertToggleAction; import org.openstreetmap.josm.actions.JosmAction; import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; import org.openstreetmap.josm.data.cache.CacheEntry; @@ -125,22 +128,6 @@ private MapillaryMainDialog() { panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); panel.add(mapillaryImageDisplay); - JPanel buttons = new JPanel(); - buttons.setLayout(new BoxLayout(buttons, BoxLayout.LINE_AXIS)); - Dimension buttonDim = new Dimension(52, 34); - JButton toggleSigns = new JButton(showSignDetectionsAction); - JButton toggleDetections = new JButton(showDetectionOutlinesAction); - showDetectionOutlinesAction.setButton(toggleDetections); - showSignDetectionsAction.setButton(toggleSigns); - toggleDetections.setPreferredSize(buttonDim); - toggleSigns.setPreferredSize(buttonDim); - // Mac OS X won't show background colors if buttons aren't opaque. - toggleSigns.setOpaque(true); - toggleDetections.setOpaque(true); - buttons.add(toggleSigns); - buttons.add(toggleDetections); - panel.add(buttons); - setMode(MODE.NORMAL); } @@ -150,8 +137,7 @@ private static abstract class JosmButtonAction extends JosmAction { public JosmButtonAction( String name, ImageProvider icon, String tooltip, Shortcut shortcut, boolean registerInToolbar, String toolbarId, - boolean installAdapters - ) { + boolean installAdapters) { super(name, icon, tooltip, shortcut, registerInToolbar, toolbarId, installAdapters); } @@ -181,8 +167,10 @@ private static class ShowDetectionOutlinesAction extends JosmButtonAction { ShowDetectionOutlinesAction() { super( - null, new ImageProvider("mapillary_sprite_source/package_objects", "object--traffic-light--other"), tr("Toggle detection outlines"), Shortcut.registerShortcut("mapillary:showdetections", tr("Mapillary: toggle detections"), KeyEvent.VK_UNDEFINED, Shortcut.NONE), false, null, false - ); + null, new ImageProvider("mapillary_sprite_source/package_objects", "object--traffic-light--other"), + tr("Toggle detection outlines"), Shortcut.registerShortcut("mapillary:showdetections", + tr("Mapillary: toggle detections"), KeyEvent.VK_UNDEFINED, Shortcut.NONE), + false, null, false); } @Override @@ -202,8 +190,10 @@ private static class ShowSignDetectionsAction extends JosmButtonAction { ShowSignDetectionsAction() { super( - null, new ImageProvider("mapillary_sprite_source/package_signs", "regulatory--go-straight-or-turn-left--g2"), tr("Toggle sign detection outlines"), Shortcut.registerShortcut("mapillary:showsigndetections", tr("Mapillary: toggle sign detections"), KeyEvent.VK_UNDEFINED, Shortcut.NONE), false, null, false - ); + null, new ImageProvider("mapillary_sprite_source/package_signs", "regulatory--go-straight-or-turn-left--g2"), + tr("Toggle sign detection outlines"), Shortcut.registerShortcut("mapillary:showsigndetections", + tr("Mapillary: toggle sign detections"), KeyEvent.VK_UNDEFINED, Shortcut.NONE), + false, null, false); } @Override @@ -244,16 +234,32 @@ public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) { * Sets a new mode for the dialog. * * @param mode - * The mode to be set. Must not be {@code null}. + * The mode to be set. Must not be {@code null}. */ public void setMode(MODE mode) { + Dimension buttonDim = new Dimension(52, 34); + SideButton toggleSigns = new SideButton(showSignDetectionsAction); + showSignDetectionsAction.setButton(toggleSigns); + toggleSigns.setPreferredSize(buttonDim); + // Mac OS X won't show background colors if buttons aren't opaque. + toggleSigns.setOpaque(true); + SideButton toggleDetections = null; + if (ExpertToggleAction.isExpert() && Boolean.TRUE.equals(MapillaryProperties.DEVELOPER_BROKEN.get())) { + toggleDetections = new SideButton(showDetectionOutlinesAction); + showDetectionOutlinesAction.setButton(toggleDetections); + toggleDetections.setPreferredSize(buttonDim); + toggleDetections.setOpaque(true); + } switch (mode) { case WALK: - createLayout(this.panel, Arrays.asList(playButton, pauseButton, stopButton)); + createLayout(this.panel, Stream.of(toggleSigns, toggleDetections, playButton, pauseButton, stopButton) + .filter(Objects::nonNull).collect(Collectors.toList())); break; case NORMAL: default: - createLayout(this.panel, Arrays.asList(blueButton, previousButton, nextButton, redButton)); + createLayout(this.panel, + Stream.of(blueButton, previousButton, toggleSigns, toggleDetections, nextButton, redButton) + .filter(Objects::nonNull).collect(Collectors.toList())); break; } disableAllButtons(); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java index d181ba351..b585767da 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/dialog/MapillaryFilterDialog.java @@ -33,6 +33,7 @@ import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; +import org.openstreetmap.josm.actions.ExpertToggleAction; import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.SideButton; import org.openstreetmap.josm.gui.dialogs.ToggleDialog; @@ -52,6 +53,7 @@ import org.openstreetmap.josm.plugins.mapillary.model.UserProfile; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryLoginListener; import org.openstreetmap.josm.plugins.mapillary.oauth.MapillaryUser; +import org.openstreetmap.josm.plugins.mapillary.utils.MapillaryProperties; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.ImageProvider; @@ -61,15 +63,16 @@ * @author nokutu * @see MapillaryFilterChooseSigns */ -public final class MapillaryFilterDialog extends ToggleDialog implements MapillaryDataListener, MapillaryLoginListener, OrganizationRecordListener { +public final class MapillaryFilterDialog extends ToggleDialog + implements MapillaryDataListener, MapillaryLoginListener, OrganizationRecordListener { private static final long serialVersionUID = -4192029663670922103L; private static MapillaryFilterDialog instance; - private static final String[] TIME_LIST = {tr("Years"), tr("Months"), tr("Days")}; + private static final String[] TIME_LIST = { tr("Years"), tr("Months"), tr("Days") }; - private static final long[] TIME_FACTOR = new long[]{ + private static final long[] TIME_FACTOR = new long[] { 31_536_000_000L, // = 365 * 24 * 60 * 60 * 1000 = number of ms in a year 2_592_000_000L, // = 30 * 24 * 60 * 60 * 1000 = number of ms in a month 86_400_000 // = 24 * 60 * 60 * 1000 = number of ms in a day @@ -101,8 +104,8 @@ public final class MapillaryFilterDialog extends ToggleDialog implements Mapilla private MapillaryFilterDialog() { super( - tr("Mapillary filter"), "mapillary-filter", tr("Open Mapillary filter dialog"), null, 200, false, MapillaryPreferenceSetting.class - ); + tr("Mapillary filter"), "mapillary-filter", tr("Open Mapillary filter dialog"), null, 200, false, + MapillaryPreferenceSetting.class); MapillaryUser.addListener(this); this.signChooser.setEnabled(false); @@ -166,7 +169,8 @@ private MapillaryFilterDialog() { private static final long serialVersionUID = -1650696801628131389L; @Override - public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof OrganizationRecord) { OrganizationRecord organization = (OrganizationRecord) value; @@ -206,10 +210,13 @@ public Component getListCellRendererComponent(JList<?> list, Object value, int i signs.add(signChooserPanel, GBC.eol().anchor(GridBagConstraints.LINE_START)); panel.add(signs, GBC.eol().anchor(GridBagConstraints.LINE_START)); - panel.add(new JSeparator(), GBC.eol().fill(GridBagConstraints.HORIZONTAL)); - objectFilter = new TrafficSignFilter(); - panel.add(objectFilter, GBC.eol().fill().anchor(GridBagConstraints.WEST)); - + if (ExpertToggleAction.isExpert() && Boolean.TRUE.equals(MapillaryProperties.DEVELOPER_BROKEN.get())) { + panel.add(new JSeparator(), GBC.eol().fill(GridBagConstraints.HORIZONTAL)); + objectFilter = new TrafficSignFilter(); + panel.add(objectFilter, GBC.eol().fill().anchor(GridBagConstraints.WEST)); + } else { + objectFilter = null; + } createLayout(panel, true, Arrays.asList(new SideButton(new UpdateAction()), new SideButton(new ResetAction()))); } @@ -280,7 +287,8 @@ public void reset() { this.time.setSelectedItem(TIME_LIST[0]); this.signChooser.setEnabled(false); this.spinnerModel.setValue(1); - this.objectFilter.reset(); + if (this.objectFilter != null) + this.objectFilter.reset(); if (this.endDate != null && this.startDate != null) { this.endDate.reset(); this.startDate.reset(); @@ -509,7 +517,9 @@ public void actionPerformed(ActionEvent arg0) { public void destroy() { if (!destroyed) { super.destroy(); - objectFilter.destroy(); + if (objectFilter != null) { + objectFilter.destroy(); + } MainApplication.getMap().removeToggleDialog(this); // OrganizationRecord.removeOrganizationListener(this); // TODO uncomment when API for orgs is available MapillaryUser.removeListener(this); diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryProperties.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryProperties.java index bf5801f76..5e3d27c22 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryProperties.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/utils/MapillaryProperties.java @@ -16,6 +16,8 @@ public final class MapillaryProperties { public static final BooleanProperty DELETE_AFTER_UPLOAD = new BooleanProperty("mapillary.delete-after-upload", true); public static final BooleanProperty DEVELOPER = new BooleanProperty("mapillary.developer", false); + /** This is for WIP items that may be very broken */ + public static final BooleanProperty DEVELOPER_BROKEN = new BooleanProperty("mapillary.developer.broken", false); public static final BooleanProperty DISPLAY_HOUR = new BooleanProperty("mapillary.display-hour", true); public static final BooleanProperty HOVER_ENABLED = new BooleanProperty("mapillary.hover-enabled", true); public static final BooleanProperty DARK_MODE = new BooleanProperty("mapillary.dark-mode", true); From 9628284699d3864994a3daf2d2ed2ea07a599f05 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Fri, 8 May 2020 09:39:48 -0600 Subject: [PATCH 18/20] Finish up switch to sprites (360 halo is still drawn) Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- .../josm/plugins/mapillary/gui/layer/MapillaryLayer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java index 5dda447a0..76d4a5f3b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/gui/layer/MapillaryLayer.java @@ -106,7 +106,7 @@ public final class MapillaryLayer extends AbstractModifiableLayer implements /** The radius of the circular sector that indicates the camera angle */ private static final int CA_INDICATOR_RADIUS = 15; /** Length of the edge of the small sign, which indicates that traffic signs have been found in an image. */ - private static final int TRAFFIC_SIGN_SIZE = ImageProvider.ImageSizes.MAP.getAdjustedWidth(); + private static final int TRAFFIC_SIGN_SIZE = (int) (ImageProvider.ImageSizes.MAP.getAdjustedWidth() / 1.5); /** The range to paint the full detection image at */ private static final Range IMAGE_CA_PAINT_RANGE = Selector.GeneralSelector.fromLevel(18, Integer.MAX_VALUE); @@ -472,7 +472,7 @@ private void drawImageMarker(final Graphics2D g, final MapillaryAbstractImage im } if (img instanceof MapillaryImage && !((MapillaryImage) img).getDetections().isEmpty()) { - g.drawImage(YIELD_SIGN, (int) (p.getX() - TRAFFIC_SIGN_SIZE / 2d), (int) (p.getY() - TRAFFIC_SIGN_SIZE / 2d), + g.drawImage(YIELD_SIGN, (int) (p.getX() - TRAFFIC_SIGN_SIZE / 3d), (int) (p.getY() - TRAFFIC_SIGN_SIZE / 3d), null); } g.setComposite(composite); From e6a9fb8a06a1b744d6b26e1e4156c20338a92268 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Fri, 8 May 2020 10:24:48 -0600 Subject: [PATCH 19/20] Drop stroke to indicate selection for the current image Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- src/main/resources/images/josm-ca/current-ca.svg | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/images/josm-ca/current-ca.svg b/src/main/resources/images/josm-ca/current-ca.svg index 75923fbb6..9d61ef91b 100644 --- a/src/main/resources/images/josm-ca/current-ca.svg +++ b/src/main/resources/images/josm-ca/current-ca.svg @@ -66,8 +66,6 @@ clip-rule="evenodd" d="m 95.240868,92.708693 c 1.022879,0 1.852078,-0.829204 1.852078,-1.852083 0,-1.022879 -0.829199,-1.852083 -1.852078,-1.852083 -1.022879,0 -1.852084,0.829204 -1.852084,1.852083 0,1.022879 0.829205,1.852083 1.852084,1.852083 z" fill="#F5811A" - stroke="white" - stroke-width="1" id="path861" /> </g> </svg> From 6f1fe9c5dca62cda82a01180bb2019b5cddbf438 Mon Sep 17 00:00:00 2001 From: Taylor Smock <taylor.smock@kaart.com> Date: Mon, 11 May 2020 07:54:40 -0600 Subject: [PATCH 20/20] Update minimum JOSM version to deal with JOSM-19208 This is due to updating JCS (the caching library we use). JCS changed the package name from "org.apache.commons.jcs" to "org.apache.commons.jcs3". Signed-off-by: Taylor Smock <taylor.smock@kaart.com> --- build.gradle.kts | 1 + gradle.properties | 4 ++-- .../openstreetmap/josm/plugins/mapillary/MapillaryData.java | 2 +- .../openstreetmap/josm/plugins/mapillary/cache/Caches.java | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9459ce66e..79a410c6b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -133,6 +133,7 @@ josm { debugPort = 7051 manifest { // See https://floscher.gitlab.io/gradle-josm-plugin/kdoc/latest/gradle-josm-plugin/org.openstreetmap.josm.gradle.plugin.config/-josm-manifest/old-version-download-link.html + oldVersionDownloadLink(16114, "v1.5.22", URL("https://github.com/JOSM/Mapillary/releases/download/v1.5.22/Mapillary.jar")) oldVersionDownloadLink(15909, "v1.5.20", URL("https://github.com/JOSM/Mapillary/releases/download/v1.5.20/Mapillary.jar")) oldVersionDownloadLink(14149, "v1.5.16", URL("https://github.com/JOSM/Mapillary/releases/download/v1.5.16/Mapillary.jar")) oldVersionDownloadLink(13733, "v1.5.15", URL("https://github.com/JOSM/Mapillary/releases/download/v1.5.15/Mapillary.jar")) diff --git a/gradle.properties b/gradle.properties index 5a2faaa3f..024b240e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,11 +6,11 @@ plugin.icon=images/mapillary-logo.svg plugin.link=https://wiki.openstreetmap.org/wiki/JOSM/Plugins/Mapillary # Minimum required JOSM version to run this plugin, choose the lowest version possible that is compatible. # You can check if the plugin compiles against this version by executing `./gradlew compileJava_minJosm`. -plugin.main.version=16114 +plugin.main.version=16402 # Version of JOSM against which the plugin is compiled # Please check, if the specified version is available for download from https://josm.openstreetmap.de/download/ . # If not, choose the next higher number that is available, or the gradle build will break. -plugin.compile.version=16114 +plugin.compile.version=16402 plugin.requires=apache-commons;apache-http;javafx # Character encoding of Gradle files diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java index ee32057f2..af0ddcd2f 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java @@ -22,7 +22,7 @@ import javax.json.JsonReader; import javax.swing.SwingUtilities; -import org.apache.commons.jcs.access.CacheAccess; +import org.apache.commons.jcs3.access.CacheAccess; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.Data; diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java index 70a33adf1..60ecb3f2a 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapillary/cache/Caches.java @@ -6,8 +6,8 @@ import javax.swing.ImageIcon; -import org.apache.commons.jcs.access.CacheAccess; -import org.apache.commons.jcs.engine.behavior.IElementAttributes; +import org.apache.commons.jcs3.access.CacheAccess; +import org.apache.commons.jcs3.engine.behavior.IElementAttributes; import org.openstreetmap.josm.data.Preferences; import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;