Commit eb6a0e4f authored by Florian Schäfer's avatar Florian Schäfer

Add a wiki layer, which displays the elements from the WikipediaToggleDialog

parent ebbeb060
// License: GPL. For details, see LICENSE file.
package org.wikipedia.actions;
import java.awt.event.ActionEvent;
import java.util.List;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.tools.I18n;
import org.openstreetmap.josm.tools.ImageProvider;
import org.wikipedia.gui.WikiLayer;
import org.wikipedia.gui.WikipediaToggleDialog;
public class ToggleWikiLayerAction extends JosmAction {
private static final ImageProvider ICON_ADDWIKI = new ImageProvider("layer", "addwiki").setMaxSize(ImageProvider.ImageSizes.SIDEBUTTON);
private static final ImageProvider ICON_REMOVEWIKI = new ImageProvider("layer", "removewiki").setMaxSize(ImageProvider.ImageSizes.SIDEBUTTON);
private final WikipediaToggleDialog dialog;
public ToggleWikiLayerAction(final WikipediaToggleDialog dialog) {
super(
I18n.tr("Wiki layer"),
ICON_ADDWIKI,
I18n.tr("Toggle the layer displaying Wikipedia articles or Wikidata items"),
null,
false,
null,
true
);
this.dialog = dialog;
}
@Override
public synchronized void actionPerformed(ActionEvent e) {
final List<WikiLayer> wikiLayers = MainApplication.getLayerManager().getLayersOfType(WikiLayer.class);
if (wikiLayers.size() <= 0) {
MainApplication.getLayerManager().addLayer(new WikiLayer(dialog));
} else {
for (WikiLayer layer : wikiLayers) {
MainApplication.getLayerManager().removeLayer(layer);
}
}
}
@Override
protected boolean listenToSelectionChange() {
return false;
}
@Override
public void updateEnabledState() {
final ImageProvider provider;
if (MainApplication.getLayerManager().getLayersOfType(WikiLayer.class).size() <= 0) {
provider = ICON_ADDWIKI;
} else {
provider = ICON_REMOVEWIKI;
}
provider.getResource().attachImageIcon(this, true);
}
}
// License: GPL. For details, see LICENSE file.
package org.wikipedia.gui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
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.dialogs.LayerListPopup;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.tools.I18n;
import org.openstreetmap.josm.tools.ImageProvider;
import org.wikipedia.data.WikipediaEntry;
import org.wikipedia.tools.WikiProperties;
public class WikiLayer extends Layer implements ListDataListener {
private static final Icon LAYER_ICON = new ImageProvider("w").setMaxSize(ImageProvider.ImageSizes.LAYER).get();
private static final Color MARKER_FILL_COLOR = new Color(153, 0, 0, 180);
private static final Color MARKER_STROKE_COLOR = new Color(255, 255, 255);
private static final double MIN_MARKER_HEIGHT = 10.0;
private static double markerHeight = Math.max(MIN_MARKER_HEIGHT, WikiProperties.WIKI_LAYER_MARKER_HEIGHT.get());
static {
WikiProperties.WIKI_LAYER_MARKER_HEIGHT.addListener(it -> markerHeight = Math.max(MIN_MARKER_HEIGHT, it.getProperty().get()));
}
private final WikipediaToggleDialog wikiDialog;
public WikiLayer(final WikipediaToggleDialog wikiDialog) {
super("WikiLayer");
this.wikiDialog = wikiDialog;
wikiDialog.model.addListDataListener(this);
}
@Override
public Icon getIcon() {
return LAYER_ICON;
}
@Override
public Object getInfoComponent() {
return MessageFormat.format("{0} elements with coordinates, {1} elements with missing coordinates are not displayed", wikiDialog.model.getSize(), Collections.list(wikiDialog.model.elements()).stream().filter(it -> it.coordinate == null).count());
}
@Override
public String getToolTipText() {
return I18n.tr("The Wikipedia/Wikidata layer");
}
@Override
public void mergeFrom(Layer from) {
throw new UnsupportedOperationException(MessageFormat.format("Layer of type {0} is not mergable!", WikiLayer.class.getSimpleName()));
}
@Override
public boolean isMergable(Layer other) {
return false;
}
@Override
public void visitBoundingBox(BoundingXYVisitor v) {
for (WikipediaEntry entry : Collections.list(wikiDialog.model.elements())) {
v.visit(entry.coordinate);
}
}
@Override
public Action[] getMenuEntries() {
return new Action[]{new LayerListPopup.InfoAction(this)};
}
@Override
public void paint(final Graphics2D g, final MapView mv, final Bounds bbox) {
// Expand bbox to also paint markers that are only partially visible (marker is centered above the location, 20px wide, 30px tall)
final Point maxPoint = mv.getPoint(bbox.getMax());
bbox.extend(mv.getLatLon(maxPoint.getX() + 10, maxPoint.getY() + 30));
final Point minPoint = mv.getPoint(bbox.getMin());
bbox.extend(mv.getLatLon(minPoint.getX() - 10, minPoint.getY() + 30));
final Collection<Point> entriesInBbox = Collections.list(wikiDialog.model.elements()).parallelStream()
.filter(it -> it.coordinate != null && bbox.contains(it.coordinate))
.map(it -> mv.getPoint(it.coordinate))
.collect(Collectors.toList());
paintWikiMarkers(g, entriesInBbox);
}
private static void paintWikiMarkers(final Graphics2D g, final Collection<Point> points) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g.setStroke(new BasicStroke(2));
for (final Point point: points) {
final Path2D path = new Path2D.Double();
path.moveTo(point.getX(), point.getY());
path.append(new Arc2D.Double(point.getX() - markerHeight / 3, point.getY() - markerHeight, markerHeight / 3 * 2, markerHeight / 3 * 2, -30, 240.0, Arc2D.OPEN), true);
path.closePath();
g.setColor(MARKER_FILL_COLOR);
g.fill(path);
g.setColor(MARKER_STROKE_COLOR);
g.draw(path);
}
}
@Override
public void intervalAdded(ListDataEvent e) {
invalidate();
}
@Override
public void intervalRemoved(ListDataEvent e) {
invalidate();
}
@Override
public void contentsChanged(ListDataEvent e) {
invalidate();
}
}
......@@ -48,6 +48,7 @@ import org.openstreetmap.josm.tools.Logging;
import org.openstreetmap.josm.tools.OpenBrowser;
import org.wikipedia.WikipediaApp;
import org.wikipedia.actions.FetchWikidataAction;
import org.wikipedia.actions.ToggleWikiLayerAction;
import org.wikipedia.data.WikipediaEntry;
import org.wikipedia.tools.ListUtil;
......@@ -56,12 +57,14 @@ public class WikipediaToggleDialog extends ToggleDialog implements ActiveLayerCh
public WikipediaToggleDialog() {
super(tr("Wikipedia"), "wikipedia", tr("Fetch Wikipedia articles with coordinates"), null, 150);
createLayout(list, true, Arrays.asList(
new SideButton(new ToggleWikiLayerAction(this)),
new SideButton(new WikipediaLoadCoordinatesAction(false)),
new SideButton(new WikipediaLoadCoordinatesAction(true)),
new SideButton(new WikipediaLoadCategoryAction()),
new SideButton(new PasteWikipediaArticlesAction()),
new SideButton(new AddWikipediaTagAction(list)),
new SideButton(new WikipediaSettingsAction(), false)));
new SideButton(new WikipediaSettingsAction(), false)
));
updateTitle();
}
......
// License: GPL. For details, see LICENSE file.
package org.wikipedia.tools;
import org.openstreetmap.josm.data.preferences.DoubleProperty;
public final class WikiProperties {
public static final DoubleProperty WIKI_LAYER_MARKER_HEIGHT = new DoubleProperty("wikipedia.layer.marker_height", 30.0);
private WikiProperties() {
// Private constructor to avoid instantiation
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 810 500">
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 810 500" width="810px" height="500px">
<path d="M 0,0 h 30 v 500 h -30 z M 60,0 h 90 v 500 h -90 z M 180,0 h 90 v 500 h -90 z" style="fill:#900"/>
<path d="M 300,0 h 30 v 500 h -30 z M 360,0 h 30 v 500 h -30 z M 720,0 h 30 v 500 h -30 z M 780,0 h 30 v 500 h -30 z" style="fill:#396"/>
<path d="M 420,0 h 90 v 500 h -90 z M 540,0 h 30 v 500 h -30 z M 600,0 h 90 v 500 h -90 z" style="fill:#069"/>
</svg>
\ No newline at end of file
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="24px" height="24px" viewBox="0 0 24 24">
<path d="m1.5,16.5h17l4,-10h-17z" fill="#ddd" stroke="#000"/>
<g transform="translate(7, 8) skewX(-22) scale(.4)">
<path d="M10.76 3.62l-.5-1C9.44.98 9.46.9 8.62.78 8.37.74 8.25.71 8.25.6V.07l.07-.05h4.91l.13.04v.52c0 .12-.08.18-.26.18l-.35.06c-.9.07-.76.43-.16 1.62l5.68 11.62.2.05L23.5 2.15c.18-.48.15-.82-.07-1.02-.23-.2-.39-.32-.97-.34l-.48-.02a.27.27 0 0 1-.16-.06.17.17 0 0 1-.08-.15v-.5l.07-.05h5.7l.05.05v.5c0 .14-.07.2-.23.2-.74.04-1.3.2-1.65.49-.36.29-.64.69-.84 1.21 0 0-4.64 10.6-6.22 14.14-.61 1.15-1.2 1.05-1.73-.04-1.11-2.28-4.24-9.21-4.24-9.21z"/>
<path d="M19.85.01h-4.63l-.07.05v.5c0 .06.03.1.08.14.05.04.1.06.17.06l.23.03c.58.02.85.17.93.27.14.17.2.35-.13 1.09l-5.98 11.93-.16-.04S6.01 5 4.77 1.97a2.04 2.04 0 0 1-.19-.69c0-.3.28-.47.83-.5l.65-.02c.17 0 .25-.07.25-.2v-.5L6.26.02H.06L.02.07V.6c0 .1.12.15.36.18.65.04 1.08.14 1.28.31.2.18.42.62.71 1.3C3.92 6.14 7.23 12.8 8.84 16.6c.46 1.04 1.04 1.2 1.75-.03 1.23-2.27 4.55-9.22 4.55-9.22l2.62-4.9c.3-.51.6-.97.75-1.19.27-.39.42-.46 1.17-.5.15 0 .23-.07.23-.2v-.5z"/>
</g>
<path d="m15.5,11.5h3v4h4v3h-4v4h-3v-4h-4v-3h4z" fill="#53f428" stroke="#419a28"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="24px" height="24px" viewBox="0 0 24 24">
<path d="m1.5,16.5h17l4,-10h-17z" fill="#ddd" stroke="#000"/>
<g transform="translate(7, 8) skewX(-22) scale(.4)">
<path d="M10.76 3.62l-.5-1C9.44.98 9.46.9 8.62.78 8.37.74 8.25.71 8.25.6V.07l.07-.05h4.91l.13.04v.52c0 .12-.08.18-.26.18l-.35.06c-.9.07-.76.43-.16 1.62l5.68 11.62.2.05L23.5 2.15c.18-.48.15-.82-.07-1.02-.23-.2-.39-.32-.97-.34l-.48-.02a.27.27 0 0 1-.16-.06.17.17 0 0 1-.08-.15v-.5l.07-.05h5.7l.05.05v.5c0 .14-.07.2-.23.2-.74.04-1.3.2-1.65.49-.36.29-.64.69-.84 1.21 0 0-4.64 10.6-6.22 14.14-.61 1.15-1.2 1.05-1.73-.04-1.11-2.28-4.24-9.21-4.24-9.21z"/>
<path d="M19.85.01h-4.63l-.07.05v.5c0 .06.03.1.08.14.05.04.1.06.17.06l.23.03c.58.02.85.17.93.27.14.17.2.35-.13 1.09l-5.98 11.93-.16-.04S6.01 5 4.77 1.97a2.04 2.04 0 0 1-.19-.69c0-.3.28-.47.83-.5l.65-.02c.17 0 .25-.07.25-.2v-.5L6.26.02H.06L.02.07V.6c0 .1.12.15.36.18.65.04 1.08.14 1.28.31.2.18.42.62.71 1.3C3.92 6.14 7.23 12.8 8.84 16.6c.46 1.04 1.04 1.2 1.75-.03 1.23-2.27 4.55-9.22 4.55-9.22l2.62-4.9c.3-.51.6-.97.75-1.19.27-.39.42-.46 1.17-.5.15 0 .23-.07.23-.2v-.5z"/>
</g>
<path d="m11.5,15.5h11v3h-11z" fill="#fa0d0d" stroke="#a41111"/>
</svg>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment