X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Ffunction%2FRearrangeWaypointsFunction.java;fp=src%2Ftim%2Fprune%2Ffunction%2FRearrangeWaypointsFunction.java;h=17e937027c2d021593979e7c54fefcdf4851f940;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/function/RearrangeWaypointsFunction.java b/src/tim/prune/function/RearrangeWaypointsFunction.java new file mode 100644 index 0000000..17e9370 --- /dev/null +++ b/src/tim/prune/function/RearrangeWaypointsFunction.java @@ -0,0 +1,189 @@ +package tim.prune.function; + +import java.util.Arrays; + +import javax.swing.JOptionPane; + +import tim.prune.App; +import tim.prune.I18nManager; +import tim.prune.data.Checker; +import tim.prune.data.DataPoint; +import tim.prune.data.Track; +import tim.prune.data.sort.SortMode; +import tim.prune.data.sort.WaypointComparer; +import tim.prune.undo.UndoRearrangeWaypoints; + +/** + * Class to provide the function for rearranging waypoints + */ +public class RearrangeWaypointsFunction extends RearrangeFunction +{ + + /** + * Constructor + * @param inApp app object + */ + public RearrangeWaypointsFunction(App inApp) + { + super(inApp, true); + } + + /** Get the name key */ + public String getNameKey() { + return "function.rearrangewaypoints"; + } + + /** Get whether sorting by time is allowed or not */ + protected boolean isSortByTimeAllowed() { + return Checker.haveWaypointsGotTimestamps(_app.getTrackInfo().getTrack()); + } + + /** Get the description key */ + public String getDescriptionKey() { + return "dialog.rearrangewaypoints.desc"; + } + + /** Sort by name key */ + protected String getSortNameKey() { + return "sortbyname"; + } + + /** + * Perform the rearrange and sort according to the radio buttons + */ + protected void finish() + { + Track track = _app.getTrackInfo().getTrack(); + // Figure out what is required from the radio buttons + Rearrange rearrangeOption = getRearrangeOption(); + SortMode sortOption = getSortMode(); + + UndoRearrangeWaypoints undo = new UndoRearrangeWaypoints(track); + boolean success = false; + if (rearrangeOption == Rearrange.TO_START || rearrangeOption == Rearrange.TO_END) + { + // Collect the waypoints to the start or end of the track + success = collectWaypoints(rearrangeOption, sortOption); + } + else + { + // Interleave the waypoints into track order + success = track.interleaveWaypoints(); + } + if (success) + { + _app.getTrackInfo().getSelection().clearAll(); // clear selected point and range + _app.completeFunction(undo, I18nManager.getText("confirm.rearrangewaypoints")); + } + else + { + JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.rearrange.noop"), + I18nManager.getText("error.function.noop.title"), JOptionPane.WARNING_MESSAGE); + } + } + + + /** + * Do the collection and sorting of the waypoints + * @param inRearrangeOption beginning or end + * @param inSortOption optional sort criterion + * @return true on success + */ + private boolean collectWaypoints(Rearrange inRearrangeOption, SortMode inSortOption) + { + // Check for mixed data, numbers of waypoints & nons + int numWaypoints = 0, numNonWaypoints = 0; + boolean wayAfterNon = false, nonAfterWay = false; + Track track = _app.getTrackInfo().getTrack(); + final int numPoints = track.getNumPoints(); + DataPoint[] waypoints = new DataPoint[numPoints]; + DataPoint[] nonWaypoints = new DataPoint[numPoints]; + DataPoint point = null; + for (int i=0; i 0); + } + else + { + nonWaypoints[numNonWaypoints] = point; + numNonWaypoints++; + nonAfterWay |= (numWaypoints > 0); + } + } + + // Exit if the data is already in the specified order + final boolean wpsToStart = (inRearrangeOption == Rearrange.TO_START); + final boolean doSort = (inSortOption != SortMode.DONT_SORT); + if (numWaypoints == 0 || numNonWaypoints == 0 + || (wpsToStart && !wayAfterNon && nonAfterWay && !doSort) + || (!wpsToStart && wayAfterNon && !nonAfterWay && !doSort) + || inRearrangeOption == Rearrange.TO_NEAREST) + { + return false; + } + // Note: it could still be that the rearrange and sort has no effect, but we don't know yet + // Make a copy of the waypoints array first so we can compare it with after the sort + DataPoint[] origWaypoints = new DataPoint[numPoints]; + System.arraycopy(waypoints, 0, origWaypoints, 0, numPoints); + + if (doSort && numWaypoints > 1) + { + // Sort the waypoints array + WaypointComparer comparer = new WaypointComparer(inSortOption); + Arrays.sort(waypoints, comparer); + final boolean sortDidNothing = areArraysSame(origWaypoints, waypoints); + if (sortDidNothing && (numNonWaypoints == 0 + || (wpsToStart && !wayAfterNon && nonAfterWay) + || (!wpsToStart && wayAfterNon && !nonAfterWay))) + { + return false; + } + } + + // Copy the arrays into an array in the specified order + DataPoint[] neworder = new DataPoint[numPoints]; + if (wpsToStart) + { + System.arraycopy(waypoints, 0, neworder, 0, numWaypoints); + System.arraycopy(nonWaypoints, 0, neworder, numWaypoints, numNonWaypoints); + } + else + { + System.arraycopy(nonWaypoints, 0, neworder, 0, numNonWaypoints); + System.arraycopy(waypoints, 0, neworder, numNonWaypoints, numWaypoints); + } + // Give track the new point order + return track.replaceContents(neworder); + } + + /** + * Compare two arrays of DataPoints and see if they're identical or not + * @param inOriginal original array of points + * @param inSorted array of points after sorting + * @return true if the two arrays have the same points in the same order + */ + private static boolean areArraysSame(DataPoint[] inOriginal, DataPoint[] inSorted) + { + if (inOriginal == null && inSorted == null) return true; // both null + if (inOriginal == null || inSorted == null) return false; // only one of them null + if (inOriginal.length != inSorted.length) return false; + // Loop over all points + for (int i=0; i