]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/App.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / App.java
index 205d88ae11c74165c23bd6aa7ef1fab275af4485..3a778588ab815a7f30c4b396e4de9d2c266836da 100644 (file)
@@ -4,13 +4,11 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.EmptyStackException;
 import java.util.Set;
-import java.util.Stack;
 
 import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 
 import tim.prune.config.Config;
-import tim.prune.data.Altitude;
 import tim.prune.data.Checker;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Field;
@@ -18,28 +16,31 @@ import tim.prune.data.LatLonRectangle;
 import tim.prune.data.NumberUtils;
 import tim.prune.data.Photo;
 import tim.prune.data.PhotoList;
+import tim.prune.data.PointCreateOptions;
 import tim.prune.data.RecentFile;
 import tim.prune.data.SourceInfo;
 import tim.prune.data.Track;
 import tim.prune.data.TrackInfo;
 import tim.prune.data.SourceInfo.FILE_TYPE;
+import tim.prune.data.Unit;
 import tim.prune.function.AsyncMediaLoader;
-import tim.prune.function.SaveConfig;
 import tim.prune.function.SelectTracksFunction;
-import tim.prune.function.browser.BrowserLauncher;
-import tim.prune.function.browser.UrlGenerator;
 import tim.prune.function.edit.FieldEditList;
 import tim.prune.function.edit.PointEditor;
+import tim.prune.function.settings.SaveConfig;
 import tim.prune.gui.MenuManager;
 import tim.prune.gui.SidebarController;
 import tim.prune.gui.UndoManager;
 import tim.prune.gui.Viewport;
+import tim.prune.gui.colour.ColourerCaretaker;
+import tim.prune.gui.colour.PointColourer;
 import tim.prune.load.FileLoader;
 import tim.prune.load.JpegLoader;
 import tim.prune.load.MediaLinkInfo;
 import tim.prune.load.TrackNameList;
 import tim.prune.save.ExifSaver;
 import tim.prune.save.FileSaver;
+import tim.prune.tips.TipManager;
 import tim.prune.undo.*;
 
 
@@ -58,7 +59,8 @@ public class App
        private FileLoader _fileLoader = null;
        private JpegLoader _jpegLoader = null;
        private FileSaver _fileSaver = null;
-       private Stack<UndoOperation> _undoStack = null;
+       private UndoStack _undoStack = null;
+       private ColourerCaretaker _colCaretaker = null;
        private boolean _mangleTimestampsConfirmed = false;
        private Viewport _viewport = null;
        private ArrayList<File> _dataFiles = null;
@@ -77,10 +79,13 @@ public class App
        public App(JFrame inFrame)
        {
                _frame = inFrame;
-               _undoStack = new Stack<UndoOperation>();
+               _undoStack = new UndoStack();
                _track = new Track();
                _trackInfo = new TrackInfo(_track);
                FunctionLibrary.initialise(this);
+               _colCaretaker = new ColourerCaretaker(this);
+               UpdateMessageBroker.addSubscriber(_colCaretaker);
+               _colCaretaker.setColourer(Config.getPointColourer());
        }
 
 
@@ -107,17 +112,51 @@ public class App
        public boolean hasDataUnsaved()
        {
                return (_undoStack.size() > _lastSavePosition
-                       && (_track.getNumPoints() > 0 || _trackInfo.getPhotoList().getNumPhotos() > 0));
+                       && (_track.getNumPoints() > 0 || _trackInfo.getPhotoList().hasModifiedMedia()));
        }
 
        /**
         * @return the undo stack
         */
-       public Stack<UndoOperation> getUndoStack()
+       public UndoStack getUndoStack()
        {
                return _undoStack;
        }
 
+       /**
+        * Update the system's point colourer using the one in the Config
+        */
+       public void updatePointColourer()
+       {
+               if (_colCaretaker != null) {
+                       _colCaretaker.setColourer(Config.getPointColourer());
+               }
+       }
+
+       /**
+        * @return colourer object, or null
+        */
+       public PointColourer getPointColourer()
+       {
+               if (_colCaretaker == null) {return null;}
+               return _colCaretaker.getColourer();
+       }
+
+       /**
+        * Show the specified tip if appropriate
+        * @param inTipNumber tip number from TipManager
+        */
+       public void showTip(int inTipNumber)
+       {
+               String key = TipManager.fireTipTrigger(inTipNumber);
+               if (key != null && !key.equals(""))
+               {
+                       JOptionPane.showMessageDialog(_frame, I18nManager.getText(key),
+                               I18nManager.getText("tip.title"), JOptionPane.INFORMATION_MESSAGE);
+               }
+       }
+
+
        /**
         * Load the specified data files one by one
         * @param inDataFiles arraylist containing File objects to load
@@ -261,7 +300,7 @@ public class App
                        // pass to track for completion
                        if (_track.editPoint(currentPoint, inEditList, false))
                        {
-                               _undoStack.push(undo);
+                               _undoStack.add(undo);
                                // Confirm point edit
                                UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.point.edit"));
                        }
@@ -301,13 +340,15 @@ public class App
                        int audioIndex = _trackInfo.getAudioList().getAudioIndex(currentPoint.getAudio());
                        DataPoint nextTrackPoint = _trackInfo.getTrack().getNextTrackPoint(pointIndex + 1);
                        // Construct Undo object
-                       UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex,
+                       UndoDeletePoint undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex,
                                audioIndex, nextTrackPoint != null && nextTrackPoint.getSegmentStart());
+                       undo.setAtBoundaryOfSelectedRange(pointIndex == _trackInfo.getSelection().getStart() ||
+                               pointIndex == _trackInfo.getSelection().getEnd());
                        // call track to delete point
                        if (_trackInfo.deletePoint())
                        {
                                // Delete was successful so add undo info to stack
-                               _undoStack.push(undo);
+                               _undoStack.add(undo);
                                if (currentPhoto != null)
                                {
                                        // delete photo if necessary
@@ -334,27 +375,6 @@ public class App
        }
 
 
-       /**
-        * Finish the compression by deleting the marked points
-        */
-       public void finishCompressTrack()
-       {
-               UndoDeleteMarked undo = new UndoDeleteMarked(_track);
-               // call track to do compress
-               int numPointsDeleted = _trackInfo.deleteMarkedPoints();
-               // add to undo stack if successful
-               if (numPointsDeleted > 0)
-               {
-                       undo.setNumPointsDeleted(numPointsDeleted);
-                       _undoStack.add(undo);
-                       UpdateMessageBroker.informSubscribers("" + numPointsDeleted + " "
-                                + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi")));
-               }
-               else {
-                       showErrorMessage("function.compress", "dialog.deletemarked.nonefound");
-               }
-       }
-
        /**
         * Reverse the currently selected section of the track
         */
@@ -382,16 +402,16 @@ public class App
        }
 
        /**
-        * Complete the add time offset function with the specified offset
+        * Complete the add time offset function with the specified offset in seconds
         * @param inTimeOffset time offset to add (+ve for add, -ve for subtract)
         */
-       public void finishAddTimeOffset(long inTimeOffset)
+       public void finishAddTimeOffsetSeconds(long inTimeOffset)
        {
                // Construct undo information
                int selStart = _trackInfo.getSelection().getStart();
                int selEnd = _trackInfo.getSelection().getEnd();
                UndoAddTimeOffset undo = new UndoAddTimeOffset(selStart, selEnd, inTimeOffset);
-               if (_trackInfo.getTrack().addTimeOffset(selStart, selEnd, inTimeOffset, false))
+               if (_trackInfo.getTrack().addTimeOffsetSeconds(selStart, selEnd, inTimeOffset, false))
                {
                        _undoStack.add(undo);
                        UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
@@ -403,12 +423,12 @@ public class App
        /**
         * Complete the add altitude offset function with the specified offset
         * @param inOffset altitude offset to add as String
-        * @param inFormat altitude format of offset (eg Feet, Metres)
+        * @param inUnit altitude units of offset (eg Feet, Metres)
         */
-       public void finishAddAltitudeOffset(String inOffset, Altitude.Format inFormat)
+       public void finishAddAltitudeOffset(String inOffset, Unit inUnit)
        {
                // Sanity check
-               if (inOffset == null || inOffset.equals("") || inFormat==Altitude.Format.NO_FORMAT) {
+               if (inOffset == null || inOffset.equals("") || inUnit == null) {
                        return;
                }
                // Construct undo information
@@ -421,7 +441,7 @@ public class App
                // Decimal offset given
                try {
                        double offsetd = Double.parseDouble(inOffset);
-                       success = _trackInfo.getTrack().addAltitudeOffset(selStart, selEnd, offsetd, inFormat, numDecimals);
+                       success = _trackInfo.getTrack().addAltitudeOffset(selStart, selEnd, offsetd, inUnit, numDecimals);
                }
                catch (NumberFormatException nfe) {}
                if (success)
@@ -480,12 +500,22 @@ public class App
         * @param inPoint point to add
         */
        public void createPoint(DataPoint inPoint)
+       {
+               createPoint(inPoint, true);
+       }
+
+       /**
+        * Create a new point at the end of the track
+        * @param inPoint point to add
+        * @param inNewSegment true for a single point, false for a continuation
+        */
+       public void createPoint(DataPoint inPoint, boolean inNewSegment)
        {
                // create undo object
                UndoCreatePoint undo = new UndoCreatePoint();
                _undoStack.add(undo);
                // add point to track
-               inPoint.setSegmentStart(true);
+               inPoint.setSegmentStart(inNewSegment);
                _track.appendPoints(new DataPoint[] {inPoint});
                // ensure track's field list contains point's fields
                _track.extendFieldList(inPoint.getFieldList());
@@ -510,6 +540,13 @@ public class App
                // ensure track's field list contains point's fields
                _track.extendFieldList(inPoint.getFieldList());
                _trackInfo.selectPoint(inIndex);
+               final int selStart = _trackInfo.getSelection().getStart();
+               final int selEnd   = _trackInfo.getSelection().getEnd();
+               if (selStart < inIndex && selEnd >= inIndex)
+               {
+                       // Extend end of selection by 1
+                       _trackInfo.getSelection().selectRange(selStart, selEnd+1);
+               }
                // update listeners
                UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.createpoint"));
        }
@@ -568,15 +605,14 @@ public class App
         * Receive loaded data and determine whether to filter on tracks or not
         * @param inFieldArray array of fields
         * @param inDataArray array of data
-        * @param inAltFormat altitude format
         * @param inSourceInfo information about the source of the data
         * @param inTrackNameList information about the track names
         */
        public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
-               Altitude.Format inAltFormat, SourceInfo inSourceInfo, TrackNameList inTrackNameList)
+               SourceInfo inSourceInfo, TrackNameList inTrackNameList)
        {
                // no link array given
-               informDataLoaded(inFieldArray, inDataArray, inAltFormat, inSourceInfo,
+               informDataLoaded(inFieldArray, inDataArray, null, inSourceInfo,
                        inTrackNameList, null);
        }
 
@@ -584,18 +620,33 @@ public class App
         * Receive loaded data and determine whether to filter on tracks or not
         * @param inFieldArray array of fields
         * @param inDataArray array of data
-        * @param inAltFormat altitude format
+        * @param inOptions creation options such as units
         * @param inSourceInfo information about the source of the data
         * @param inTrackNameList information about the track names
-        * @param inLinkInfo links to photo/audio clips
         */
        public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
-               Altitude.Format inAltFormat, SourceInfo inSourceInfo,
-               TrackNameList inTrackNameList, MediaLinkInfo inLinkInfo)
+               PointCreateOptions inOptions, SourceInfo inSourceInfo, TrackNameList inTrackNameList)
+       {
+               // no link array given
+               informDataLoaded(inFieldArray, inDataArray, inOptions, inSourceInfo,
+                       inTrackNameList, null);
+       }
+
+       /**
+        * Receive loaded data and determine whether to filter on tracks or not
+        * @param inFieldArray array of fields
+        * @param inDataArray array of data
+        * @param inOptions creation options such as units
+        * @param inSourceInfo information about the source of the data
+        * @param inTrackNameList information about the track names
+        * @param inLinkInfo links to photo/audio clips
+        */
+       public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, PointCreateOptions inOptions,
+               SourceInfo inSourceInfo, TrackNameList inTrackNameList, MediaLinkInfo inLinkInfo)
        {
                // Check whether loaded array can be properly parsed into a Track
                Track loadedTrack = new Track();
-               loadedTrack.load(inFieldArray, inDataArray, inAltFormat);
+               loadedTrack.load(inFieldArray, inDataArray, inOptions);
                if (loadedTrack.getNumPoints() <= 0)
                {
                        showErrorMessage("error.load.dialogtitle", "error.load.nopoints");
@@ -816,7 +867,7 @@ public class App
                }
                else
                {
-                       new UndoManager(this, _frame);
+                       new UndoManager(this, _frame).show();
                }
        }
 
@@ -856,7 +907,7 @@ public class App
                {
                        for (int i=0; i<inNumUndos; i++)
                        {
-                               _undoStack.pop().performUndo(_trackInfo);
+                               _undoStack.popOperation().performUndo(_trackInfo);
                        }
                        String message = "" + inNumUndos + " "
                                 + (inNumUndos==1?I18nManager.getText("confirm.undo.single"):I18nManager.getText("confirm.undo.multi"));
@@ -872,16 +923,15 @@ public class App
                UpdateMessageBroker.informSubscribers();
        }
 
-
        /**
-        * Show a map url in an external browser
-        * @param inSourceIndex index of map source to use
+        * @return the current data status, used for later comparison
         */
-       public void showExternalMap(int inSourceIndex)
+       public DataStatus getCurrentDataStatus()
        {
-               BrowserLauncher.launchBrowser(UrlGenerator.generateUrl(inSourceIndex, _trackInfo));
+               return new DataStatus(_undoStack.size(), _undoStack.getNumUndos());
        }
 
+
        /**
         * Display a standard error message
         * @param inTitleKey key to lookup for window title