// License: GPL. For details, see LICENSE file.
package ptl;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.TreeSet;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
import org.openstreetmap.josm.gui.MapView;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy;
import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel;
import org.openstreetmap.josm.tools.ColorHelper;
import org.openstreetmap.josm.tools.ImageProvider;
import org.openstreetmap.josm.tools.MultiMap;
import org.openstreetmap.josm.tools.Pair;
import org.openstreetmap.josm.tools.Utils;
public class PublicTransportLayer extends Layer {
private static final ImageProvider ICON = new ImageProvider("presets/misc", "route");
private boolean doDrawArrows = true;
private boolean doDrawRefLabels = true;
public PublicTransportLayer() {
super(tr("Public transport routes"));
}
@Override
public void paint(Graphics2D g, MapView mv, Bounds box) {
if (mv == null || mv.getLayerManager().getEditLayer() == null || mv.getLayerManager().getEditLayer().data.selectionEmpty()) {
return;
}
final StyledMapRenderer renderer = new StyledMapRenderer(g, mv, false);
final Collection<Relation> selectedRelations = mv.getLayerManager().getEditLayer().data.getSelectedRelations();
final MultiMap<Pair<Node, Node>, String> segmentRefs = new MultiMap<>();
for (final Relation relation : selectedRelations) {
if (relation.isIncomplete() || relation.hasIncompleteMembers()
|| !relation.hasTag("type", "route") || !relation.hasTag("public_transport:version", "2")) {
continue;
}
final Way way = new Way();
Node previousNode = null;
for (final RelationMember member : relation.getMembers()) {
if (OsmPrimitiveType.NODE.equals(member.getType()) && "stop".equals(member.getRole())) {
way.addNode(member.getNode());
if (previousNode != null) {
segmentRefs.put(Pair.create(previousNode, member.getNode()), relation.get("ref"));
}
previousNode = member.getNode();
}
}
Color color = Color.GREEN;
try {
color = ColorHelper.html2color(relation.get("colour"));
} catch (RuntimeException ignore) {
Main.trace(ignore);
}
renderer.drawWay(way, color, new BasicStroke(1), null, null, 0, doDrawArrows, false, false, false);
}
if (doDrawRefLabels) {
drawRefLabels(renderer, segmentRefs);
}
}
protected void drawRefLabels(StyledMapRenderer renderer, MultiMap<Pair<Node, Node>, String> segmentRefs) {
for (Pair<Node, Node> nodePair : segmentRefs.keySet()) {
final String label = Utils.join(tr(", "), new TreeSet<>(segmentRefs.get(nodePair)));
final TextLabel text = new TextLabel(new LabelCompositionStrategy.StaticLabelCompositionStrategy(label),
new Font("SansSerif", Font.PLAIN, 16), 0, 0, new Color(0x80FFFFFF, true), 0f, null);
final Way way = new Way();
way.addNode(nodePair.a);
way.addNode(nodePair.b);
renderer.drawTextOnPath(way, text);
}
}
@Override
public Icon getIcon() {
return ICON.setMaxSize(ImageProvider.ImageSizes.LAYER).get();
}
@Override
public String getToolTipText() {
return "";
}
@Override
public void mergeFrom(Layer from) {
}
@Override
public boolean isMergable(Layer other) {
return false;
}
@Override
public void visitBoundingBox(BoundingXYVisitor v) {
}
@Override
public Object getInfoComponent() {
return null;
}
@Override
public Action[] getMenuEntries() {
return new Action[]{
new AbstractAction(tr("Toggle direction arrows")) {
@Override
public void actionPerformed(ActionEvent e) {
doDrawArrows = !doDrawArrows;
Main.map.repaint();
}
},
new AbstractAction(tr("Toggle reference labels")) {
@Override
public void actionPerformed(ActionEvent e) {
doDrawRefLabels = !doDrawRefLabels;
Main.map.repaint();
}
}
};
}
public static class AddLayerAction extends JosmAction {
public AddLayerAction() {
super(tr("Visualize public transport routes"), ICON, tr("Displays stops of selected public transport routes as graph"),
null, false, null, false);
}
@Override
public void actionPerformed(ActionEvent e) {
Main.getLayerManager().addLayer(new PublicTransportLayer());
}
}
}