package com.tilusnet.josm.plugins.alignways;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Point;
import java.util.Collection;
import java.util.List;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.gui.MapView;
/**
* Should be a singleton class. The active alignee and reference objects
* manager. Can request alignee, reference segment updates and pivot updates on
* these.
*
* @author tilusnet <tilusnet@gmail.com>
*
*/
public class AlignWaysSegmentMgr {
private volatile static AlignWaysSegmentMgr singleton;
private AlignWaysRefSegment refSeg = null;
private AlignWaysAlgnSegment algnSeg = null;
private final MapView mv;
private AlignWaysSegmentMgr(MapView mapView) {
mv = mapView;
}
/**
* Get or creates the segment manager instance belonging to a given MapView.
*/
public static AlignWaysSegmentMgr getInstance(MapView mapView) {
synchronized (AlignWaysSegmentMgr.class) {
if (singleton == null || !singleton.getMapView().equals(mapView)) {
singleton = new AlignWaysSegmentMgr(mapView);
}
}
return singleton;
}
/**
* @return The MapView this segment manager belongs to.
*/
private MapView getMapView() {
return mv;
}
/**
* @param clickedPoint
* Point nearby where user probably clicked
* @return true, if alignee changed, false otherwise
*/
public boolean algnUpdate(Point clickedPoint) {
// Check first if there is a pivot point nearby that needs selection
if (algnSeg != null && algnSeg.updatePivot(clickedPoint)) {
// Updated pivot, alignee reference unchanged
return false;
}
// Previous attempt of pivot update unsuccessful, check alignee update
AlignWaysAlgnSegment tmpAlgnSeg = new AlignWaysAlgnSegment(mv, clickedPoint);
if (tmpAlgnSeg.getSegment() == null)
return false;
// Found a segment - it may happen that the new segment is identical with the already
// selected asignee or reference segment. This action is then ignored.
if (algnSeg != null && tmpAlgnSeg.equals(algnSeg)) {
return false;
}
else if (refSeg != null && tmpAlgnSeg.equals(refSeg)) {
JOptionPane.showMessageDialog(Main.parent,
tr("Segment to be aligned cannot be the same with the reference segment.\n" +
"Please choose a different segment to be aligned."),
tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE);
return false;
}
// This will be a new alignee, old alignee (if any) will be lost:
if (algnSeg != null) {
algnSeg.destroy();
}
// Update alignee
algnSeg = tmpAlgnSeg;
return true;
}
/**
* @param clickedPoint
* Point nearby where user probably clicked
* @return true, if reference changed, false otherwise
*/
public boolean refUpdate(Point clickedPoint) {
AlignWaysRefSegment tmpRefSeg = new AlignWaysRefSegment(mv, clickedPoint);
if (tmpRefSeg.getSegment() == null)
return false;
// Found a segment - it may happen that the new segment is identical with the already
// selected asignee or reference segment. This action is then ignored.
if (refSeg != null && refSeg.equals(tmpRefSeg)) {
return false;
}
else if (algnSeg != null && tmpRefSeg.equals(algnSeg)) {
JOptionPane.showMessageDialog(Main.parent,
tr("Reference segment cannot be the same with the segment to be aligned.\n" +
"Please choose a different reference segment."),
tr("AlignWayS message"), JOptionPane.WARNING_MESSAGE);
return false;
}
// This will be a new reference, old reference (if any) will be lost:
if (refSeg != null) {
refSeg.destroy();
}
// Update reference
refSeg = tmpRefSeg;
return true;
}
/**
* @return Collection of the nodes that belong to the selected alignee.
*/
public Collection<Node> getSelectedNodes() {
if (algnSeg != null)
return algnSeg.getSegmentEndPoints();
return null;
}
/**
* Performs "clean-up" on the initialised segments
*/
public void cleanupWays() {
if (algnSeg != null) {
algnSeg.destroy();
algnSeg = null;
}
if (refSeg != null) {
refSeg.destroy();
refSeg = null;
}
}
public AlignWaysAlgnSegment getAlgnSeg() {
return algnSeg;
}
/**
* @return the refSeg
*/
public AlignWaysRefSegment getRefSeg() {
return refSeg;
}
/**
* Handles the event that OSM primitives were removed and checks whether
* this invalidates the currently selected alignee or reference segment.
* @return Whether any of the selected segments were invalidated.
* @param primitives List of primitives that were removed.
*/
public boolean primitivesRemoved(List<? extends OsmPrimitive> primitives) {
boolean changed = false;
for (OsmPrimitive p : primitives) {
if (algnSeg != null && algnSeg.containsPrimitive(p)) {
algnSeg.destroy();
algnSeg = null;
changed = true;
}
if (refSeg != null && refSeg.containsPrimitive(p)) {
refSeg.destroy();
refSeg = null;
changed = true;
}
}
return changed;
}
}