Skip to content

Commit

Permalink
Automatically open routing helper when selecting a route relation, ma…
Browse files Browse the repository at this point in the history
…ke forward/backward navigation work and show connectivity (very primitive check)
  • Loading branch information
floscher committed Nov 15, 2020
1 parent 023ec80 commit 08c2706
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.openstreetmap.josm.plugins.pt_assistant.actions.SortPTRouteMembersAction;
import org.openstreetmap.josm.plugins.pt_assistant.actions.SortPTRouteMembersMenuBar;
import org.openstreetmap.josm.plugins.pt_assistant.actions.SplitRoundaboutAction;
import org.openstreetmap.josm.plugins.pt_assistant.actions.routinghelper.RoutingHelperAction;
import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteSegment;
import org.openstreetmap.josm.plugins.pt_assistant.gui.PTAssistantLayerManager;
import org.openstreetmap.josm.plugins.pt_assistant.validation.BicycleFootRouteValidatorTest;
Expand Down Expand Up @@ -79,6 +80,7 @@ public PTAssistantPlugin(PluginInformation info) {
.addMenu("File", trc("menu", "Public Transport"), KeyEvent.VK_P, 5, ht("/Menu/Public Transport"));
addToMenu(PublicTransportMenu);

SelectionEventManager.getInstance().addSelectionListener(new RoutingHelperAction());
SelectionEventManager.getInstance().addSelectionListener(PTAssistantLayerManager.PTLM);
KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(PTAssistantLayerManager.PTLM);
initialiseWizard();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,78 +1,174 @@
package org.openstreetmap.josm.plugins.pt_assistant.actions.routinghelper;

import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Objects;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import javax.swing.JOptionPane;

import com.drew.lang.annotations.NotNull;
import com.drew.lang.annotations.Nullable;
import org.openstreetmap.josm.data.osm.AbstractPrimitive;
import org.openstreetmap.josm.data.osm.DataSelectionListener;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.MapFrame;
import org.openstreetmap.josm.gui.dialogs.relation.actions.AbstractRelationEditorAction;
import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionAccess;
import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorUpdateOn;
import org.openstreetmap.josm.plugins.pt_assistant.utils.BoundsUtils;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
import org.openstreetmap.josm.plugins.pt_assistant.utils.DialogUtils;
import org.openstreetmap.josm.plugins.pt_assistant.utils.RouteUtils;
import org.openstreetmap.josm.plugins.pt_assistant.utils.WayUtils;
import org.openstreetmap.josm.tools.I18n;
import org.openstreetmap.josm.tools.ImageProvider;

public class RoutingHelperAction extends AbstractRelationEditorAction {
public class RoutingHelperAction implements DataSelectionListener {
private static final Set<ITransportMode> TRANSPORT_MODES = Collections.singleton(new BusTransportMode());

private Optional<ITransportMode> activeTransportMode;

private final RoutingHelperPanel routingHelperPanel = new RoutingHelperPanel(this);

public RoutingHelperAction(IRelationEditorActionAccess editorAccess) {
super(editorAccess, IRelationEditorUpdateOn.TAG_CHANGE);
new ImageProvider("dialogs/relation", "routing_assistance.svg").getResource().attachImageIcon(this, true);
putValue(SHORT_DESCRIPTION, I18n.tr("Routing helper"));
}
@NotNull
private Optional<Relation> currentRelation = Optional.empty();

private Optional<RelationMember> currentMember = Optional.empty();

@Override
protected void updateEnabledState() {
final Relation currentRelation = getEditor().getRelation();
final Optional<ITransportMode> newActiveTransportMode = TRANSPORT_MODES.stream()
.filter(mode -> mode.canBeUsedForRelation(currentRelation))
.findFirst();
this.activeTransportMode = newActiveTransportMode;
setEnabled(newActiveTransportMode.isPresent() && MainApplication.getMap().getTopPanel(RoutingHelperPanel.class) == null);
public void selectionChanged(SelectionChangeEvent event) {
final MapFrame mapframe = MainApplication.getMap();
if (mapframe != null) {
final Optional<Relation> singleRelationSelection = Optional.of(event.getSelection())
.filter(selection -> selection.size() == 1)
.map(selection -> selection.iterator().next())
.map(selectedPrimitive -> selectedPrimitive instanceof Relation ? (Relation) selectedPrimitive : null)
.filter(RouteUtils::isRoute);
this.currentRelation = singleRelationSelection;
if (singleRelationSelection.isPresent()) {
routingHelperPanel.onRelationChange(singleRelationSelection.get());
if (mapframe.getTopPanel(RoutingHelperPanel.class) == null) {
mapframe.addTopPanel(routingHelperPanel);
}
} else {
mapframe.removeTopPanel(RoutingHelperPanel.class);
}
}
}

@Override
public void actionPerformed(@NotNull final ActionEvent actionEvent) {
final MapFrame mapFrame = MainApplication.getMap();
public void goToFirstWay() {
final Optional<Relation> currentRelation = this.currentRelation;
final long missingMembersCount = currentRelation
.map(it ->
it.getMembers().stream()
.filter(member -> member.getMember().isIncomplete())
.count()
)
.orElse(0L);
if (missingMembersCount > 0) {
if (
DialogUtils.showYesNoQuestion(
routingHelperPanel,
I18n.tr("Relation is incomplete"),
I18n.trn(
"The relations has {0} missing member. Would you like to download the missing member now?",
"The relations has {0} missing members. Would you like to download the missing members now?",
missingMembersCount,
missingMembersCount
)
)
) {
final Future<?> f = MainApplication.worker.submit(new DownloadRelationMemberTask(
currentRelation.get(),
currentRelation.get().getMembers().stream()
.map(RelationMember::getMember)
.filter(AbstractPrimitive::isIncomplete)
.collect(Collectors.toSet()),
MainApplication.getLayerManager().getActiveDataLayer()
));
new Thread(() -> {
try {
f.get();

if (mapFrame.getTopPanel(RoutingHelperPanel.class) == null) {
mapFrame.addTopPanel(routingHelperPanel);
updateEnabledState();
}
// try again, now the missingMembersCount should be 0, so we should go to the else-branch this time
goToFirstWay();
} catch (CancellationException | InterruptedException | ExecutionException e) {
JOptionPane.showMessageDialog(
routingHelperPanel,
I18n.tr("The download of missing members has failed!"),
I18n.tr("Download failed"),
JOptionPane.ERROR_MESSAGE
);
}

final Way currentWay = editorAccess.getEditor().getRelation().getMembers().stream().map(it -> it.isWay() ? it.getWay() : null).filter(Objects::nonNull).findFirst().orElse(null);
if (currentWay != null) {
MainApplication.getMap().mapView.zoomTo(BoundsUtils.fromBBox(currentWay.getBBox()));
}).start();
}
} else {
final List<RelationMember> wayMembers = currentRelation.map(relation -> relation.getMembers().stream().filter(RouteUtils::isRouteWayMember).collect(Collectors.toList())).orElse(Collections.emptyList());
this.currentMember = wayMembers.stream().findFirst();
if (wayMembers.isEmpty()) {
JOptionPane.showMessageDialog(routingHelperPanel, "No way found to traverse", "Could not find a way to traverse", JOptionPane.ERROR_MESSAGE);
} else {
routingHelperPanel.onCurrentWayChange(
currentRelation.get(),
wayMembers.get(0),
RoutingHelperPanel.ConnectionType.END,
wayMembers.size() == 1
? RoutingHelperPanel.ConnectionType.END
: (
WayUtils.isTouchingOtherWay(wayMembers.get(0).getWay(), wayMembers.get(1).getWay())
? RoutingHelperPanel.ConnectionType.CONNECTED
: RoutingHelperPanel.ConnectionType.NOT_CONNECTED
)
);
}
}
routingHelperPanel.onCurrentWayChange(currentWay);
}

public void goToPreviousGap() {
JOptionPane.showMessageDialog(routingHelperPanel, "Not implemented yet", "Not implemented", JOptionPane.ERROR_MESSAGE);
}

public void goToPreviousWay() {
JOptionPane.showMessageDialog(routingHelperPanel, "Not implemented yet", "Not implemented", JOptionPane.ERROR_MESSAGE);
goNWaysForward(-1);
}

public void goToNextWay() {
JOptionPane.showMessageDialog(routingHelperPanel, "Not implemented yet", "Not implemented", JOptionPane.ERROR_MESSAGE);
goNWaysForward(1);
}

private void goNWaysForward(final int n) {
currentRelation.ifPresent(relation ->
currentMember.ifPresent(member -> {
final List<RelationMember> wayMembers = relation.getMembers().stream().filter(RouteUtils::isRouteWayMember).collect(Collectors.toList());
final int targetIndex = wayMembers.indexOf(member) + n;
if (targetIndex < 0 || targetIndex >= wayMembers.size() - 1) {
new Notification(I18n.tr("You reached the end of the route")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
} else {
currentMember = Optional.of(wayMembers.get(targetIndex));
routingHelperPanel.onCurrentWayChange(
relation,
wayMembers.get(targetIndex),
targetIndex <= 0 ? RoutingHelperPanel.ConnectionType.END : (
WayUtils.isTouchingOtherWay(wayMembers.get(targetIndex).getWay(), wayMembers.get(targetIndex - 1).getWay())
? RoutingHelperPanel.ConnectionType.CONNECTED
: RoutingHelperPanel.ConnectionType.NOT_CONNECTED
),
targetIndex >= wayMembers.size() - 1 ? RoutingHelperPanel.ConnectionType.END : (
WayUtils.isTouchingOtherWay(wayMembers.get(targetIndex).getWay(), wayMembers.get(targetIndex + 1).getWay())
? RoutingHelperPanel.ConnectionType.CONNECTED
: RoutingHelperPanel.ConnectionType.NOT_CONNECTED
)
);
}
})
);
}

public void goToNextGap() {
JOptionPane.showMessageDialog(routingHelperPanel, "Not implemented yet", "Not implemented", JOptionPane.ERROR_MESSAGE);
}

}
Loading

0 comments on commit 08c2706

Please sign in to comment.