]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/correlate/Correlator.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / correlate / Correlator.java
index 2a4b49f882937100705aa67195c48552676f70f1..0aaafc36577628a1165b5867f539555b2c06abcd 100644 (file)
@@ -6,8 +6,8 @@ import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.Calendar;
 import java.util.Iterator;
+import java.util.TimeZone;
 import java.util.TreeSet;
 
 import javax.swing.BorderFactory;
@@ -27,6 +27,7 @@ import javax.swing.JTextField;
 import tim.prune.App;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
+import tim.prune.config.TimezoneHelper;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
 import tim.prune.data.Field;
@@ -35,6 +36,9 @@ import tim.prune.data.MediaList;
 import tim.prune.data.TimeDifference;
 import tim.prune.data.Timestamp;
 import tim.prune.data.Track;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
+import tim.prune.tips.TipManager;
 
 /**
  * Abstract superclass of the two correlator functions
@@ -43,20 +47,21 @@ public abstract class Correlator extends GenericFunction
 {
        protected JDialog _dialog;
        private CardStack _cards = null;
-       private JLabel _tipLabel = null;
        private JTable _selectionTable = null;
        protected JTable _previewTable = null;
        private boolean _previewEnabled = false; // flag required to enable preview function on final panel
        private boolean[] _cardEnabled = null; // flag for each card
+       private TimeZone _timezone = null;
        private JTextField _offsetHourBox = null, _offsetMinBox = null, _offsetSecBox = null;
        private JRadioButton _mediaLaterOption = null, _pointLaterOption = null;
        private JRadioButton _timeLimitRadio = null, _distLimitRadio = null;
        private JTextField _limitMinBox = null, _limitSecBox = null;
        private JTextField _limitDistBox = null;
-       private JComboBox _distUnitsDropdown = null;
+       private JComboBox<String> _distUnitsDropdown = null;
        private JButton _nextButton = null, _backButton = null;
        protected JButton _okButton = null;
 
+
        /**
         * Constructor
         * @param inApp App object to report actions to
@@ -108,14 +113,20 @@ public abstract class Correlator extends GenericFunction
                        _dialog.getContentPane().add(makeDialogContents());
                        _dialog.pack();
                }
+               _okButton.setEnabled(false);
+               // Init timezone to the currently selected one
+               _timezone = TimezoneHelper.getSelectedTimezone();
                // Go to first available card
                int card = 0;
                _cardEnabled = null;
-               while (!isCardEnabled(card)) {card++;}
+               while (!isCardEnabled(card)) {
+                       card++;
+               }
                _cards.showCard(card);
                showCard(0); // does set up and next/prev enabling
-               _okButton.setEnabled(false);
-               _tipLabel.setVisible(!isCardEnabled(1));
+               if (!isCardEnabled(1)) {
+                       _app.showTip(TipManager.Tip_ManuallyCorrelateOne);
+               }
                _dialog.setVisible(true);
        }
 
@@ -201,7 +212,7 @@ public abstract class Correlator extends GenericFunction
                                && media.getOriginalStatus() == MediaObject.Status.NOT_CONNECTED)
                        {
                                // Calculate time difference, add to table model
-                               long timeDiff = getMediaTimestamp(media).getSecondsSince(media.getDataPoint().getTimestamp());
+                               long timeDiff = getMediaTimestamp(media).getSecondsSince(media.getDataPoint().getTimestamp(), _timezone);
                                model.addMedia(media, timeDiff);
                        }
                }
@@ -238,27 +249,6 @@ public abstract class Correlator extends GenericFunction
        }
 
 
-       /**
-        * @param inFirstTimestamp timestamp of first photo / audio object, or null if not available
-        * @return time difference of local time zone from UTC when the first photo was taken
-        */
-       private static TimeDifference getTimezoneOffset(Timestamp inFirstTimestamp)
-       {
-               Calendar cal = null;
-               // Use first timestamp if available
-               if (inFirstTimestamp != null) {
-                       cal = inFirstTimestamp.getCalendar();
-               }
-               else {
-                       // No photo or no timestamp, just use current time
-                       cal = Calendar.getInstance();
-               }
-               // Both time zone offset and dst offset are based on milliseconds, so convert to seconds
-               TimeDifference timeDiff = new TimeDifference((cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 1000);
-               return timeDiff;
-       }
-
-
        /**
         * Calculate the median index to select from the table
         * @param inModel table model
@@ -312,8 +302,10 @@ public abstract class Correlator extends GenericFunction
        {
                JPanel card = new JPanel();
                card.setLayout(new BorderLayout(10, 10));
-               card.add(new JLabel(I18nManager.getText(
-                       "dialog.correlate." + getMediaTypeKey() + "select.intro")), BorderLayout.NORTH);
+               JLabel introLabel = new JLabel(I18nManager.getText(
+                       "dialog.correlate." + getMediaTypeKey() + "select.intro"));
+               introLabel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+               card.add(introLabel, BorderLayout.NORTH);
                // table doesn't have model yet - that will be attached later
                _selectionTable = new JTable();
                JScrollPane photoScrollPane = new JScrollPane(_selectionTable);
@@ -335,9 +327,6 @@ public abstract class Correlator extends GenericFunction
                card2.setLayout(new BorderLayout());
                JPanel card2Top = new JPanel();
                card2Top.setLayout(new BoxLayout(card2Top, BoxLayout.Y_AXIS));
-               _tipLabel = new JLabel(I18nManager.getText("dialog.correlate.options.tip"));
-               _tipLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 5, 6));
-               card2Top.add(_tipLabel);
                JLabel introLabel = new JLabel(I18nManager.getText("dialog.correlate.options.intro"));
                introLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 5, 6));
                card2Top.add(introLabel);
@@ -368,7 +357,7 @@ public abstract class Correlator extends GenericFunction
                offsetPanelBot.setLayout(new FlowLayout());
                offsetPanelBot.setBorder(null);
                _mediaLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options." + getMediaTypeKey() + "later"));
-               _pointLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options.pointlaterphoto"));
+               _pointLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options.pointlater" + getMediaTypeKey()));
                _mediaLaterOption.addItemListener(optionsChangedListener);
                _pointLaterOption.addItemListener(optionsChangedListener);
                ButtonGroup laterGroup = new ButtonGroup();
@@ -380,6 +369,12 @@ public abstract class Correlator extends GenericFunction
                offsetPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
                card2Top.add(offsetPanel);
 
+               // listener for radio buttons
+               ActionListener radioListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               enableEditBoxes();
+                       }
+               };
                // time limits section
                JPanel limitsPanel = new JPanel();
                limitsPanel.setBorder(BorderFactory.createTitledBorder(I18nManager.getText("dialog.correlate.options.limitspanel")));
@@ -388,9 +383,11 @@ public abstract class Correlator extends GenericFunction
                timeLimitPanel.setLayout(new FlowLayout());
                JRadioButton noTimeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.notimelimit"));
                noTimeLimitRadio.addItemListener(optionsChangedListener);
+               noTimeLimitRadio.addActionListener(radioListener);
                timeLimitPanel.add(noTimeLimitRadio);
-               _timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + " : ");
+               _timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + ": ");
                _timeLimitRadio.addItemListener(optionsChangedListener);
+               _timeLimitRadio.addActionListener(radioListener);
                timeLimitPanel.add(_timeLimitRadio);
                groupRadioButtons(noTimeLimitRadio, _timeLimitRadio);
                _limitMinBox = new JTextField(3);
@@ -407,9 +404,11 @@ public abstract class Correlator extends GenericFunction
                distLimitPanel.setLayout(new FlowLayout());
                JRadioButton noDistLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.nodistancelimit"));
                noDistLimitRadio.addItemListener(optionsChangedListener);
+               noDistLimitRadio.addActionListener(radioListener);
                distLimitPanel.add(noDistLimitRadio);
-               _distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit"));
+               _distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit") + ": ");
                _distLimitRadio.addItemListener(optionsChangedListener);
+               _distLimitRadio.addActionListener(radioListener);
                distLimitPanel.add(_distLimitRadio);
                groupRadioButtons(noDistLimitRadio, _distLimitRadio);
                _limitDistBox = new JTextField(4);
@@ -417,7 +416,7 @@ public abstract class Correlator extends GenericFunction
                distLimitPanel.add(_limitDistBox);
                String[] distUnitsOptions = {I18nManager.getText("units.kilometres"), I18nManager.getText("units.metres"),
                        I18nManager.getText("units.miles")};
-               _distUnitsDropdown = new JComboBox(distUnitsOptions);
+               _distUnitsDropdown = new JComboBox<String>(distUnitsOptions);
                _distUnitsDropdown.addItemListener(optionsChangedListener);
                distLimitPanel.add(_distUnitsDropdown);
                limitsPanel.add(distLimitPanel);
@@ -465,7 +464,9 @@ public abstract class Correlator extends GenericFunction
         */
        private boolean isCardEnabled(int inCardNum)
        {
-               if (_cardEnabled == null) {_cardEnabled = getCardEnabledFlags();}
+               if (_cardEnabled == null) {
+                       _cardEnabled = getCardEnabledFlags();
+               }
                return (inCardNum >= 0 && inCardNum < _cardEnabled.length && _cardEnabled[inCardNum]);
        }
 
@@ -516,6 +517,18 @@ public abstract class Correlator extends GenericFunction
                _okButton.setEnabled(inCardNum == 2 && ((MediaPreviewTableModel) _previewTable.getModel()).hasAnySelected());
        }
 
+       /**
+        * Enable or disable the edit boxes according to the radio button selections
+        */
+       private void enableEditBoxes()
+       {
+               // enable/disable text field for distance input
+               _limitDistBox.setEnabled(_distLimitRadio.isSelected());
+               // and for time limits
+               _limitMinBox.setEnabled(_timeLimitRadio.isSelected());
+               _limitSecBox.setEnabled(_timeLimitRadio.isSelected());
+       }
+
        /**
         * Parse the time limit values entered and validate them
         * @return TimeDifference object describing limit
@@ -557,9 +570,9 @@ public abstract class Correlator extends GenericFunction
        /**
         * @return the selected distance units from the dropdown
         */
-       protected Distance.Units getSelectedDistanceUnits()
+       protected Unit getSelectedDistanceUnits()
        {
-               final Distance.Units[] distUnits = {Distance.Units.KILOMETRES, Distance.Units.METRES, Distance.Units.MILES};
+               final Unit[] distUnits = {UnitSetLibrary.UNITS_KILOMETRES, UnitSetLibrary.UNITS_METRES, UnitSetLibrary.UNITS_MILES};
                return distUnits[_distUnitsDropdown.getSelectedIndex()];
        }
 
@@ -570,7 +583,9 @@ public abstract class Correlator extends GenericFunction
        public void createPreview(boolean inFromButton)
        {
                // Exit if still on first panel
-               if (!_previewEnabled) {return;}
+               if (!_previewEnabled) {
+                       return;
+               }
                // Create a TimeDifference based on the edit boxes
                int numHours = getValue(_offsetHourBox.getText());
                int numMins = getValue(_offsetMinBox.getText());
@@ -590,12 +605,8 @@ public abstract class Correlator extends GenericFunction
                TimeDifference timeDiff = inTimeDiff;
                if (timeDiff == null)
                {
-                       // No time difference available, so calculate based on computer's time zone
-                       Timestamp tstamp = null;
-                       if (inFirstMedia != null) {
-                               tstamp = inFirstMedia.getTimestamp();
-                       }
-                       timeDiff = getTimezoneOffset(tstamp);
+                       // No time difference available, so try with zero
+                       timeDiff = new TimeDifference(0L);
                }
                // Use time difference to set edit boxes
                _offsetHourBox.setText("" + timeDiff.getNumHours());
@@ -604,6 +615,7 @@ public abstract class Correlator extends GenericFunction
                _mediaLaterOption.setSelected(timeDiff.getIsPositive());
                _pointLaterOption.setSelected(!timeDiff.getIsPositive());
                _previewEnabled = true;
+               enableEditBoxes();
                createPreview(timeDiff, true);
        }
 
@@ -635,19 +647,23 @@ public abstract class Correlator extends GenericFunction
        protected PointMediaPair getPointPairForMedia(Track inTrack, MediaObject inMedia, TimeDifference inOffset)
        {
                PointMediaPair pair = new PointMediaPair(inMedia);
-               // Add/subtract offset to media timestamp
-               Timestamp mediaStamp = getMediaTimestamp(inMedia).createMinusOffset(inOffset);
-               int numPoints = inTrack.getNumPoints();
-               for (int i=0; i<numPoints; i++)
+               if (inMedia.hasTimestamp())
                {
-                       DataPoint point = inTrack.getPoint(i);
-                       if (point.getPhoto() == null && point.getAudio() == null)
+                       // Add/subtract offset to media timestamp
+                       Timestamp mediaStamp = getMediaTimestamp(inMedia);
+                       int numPoints = inTrack.getNumPoints();
+                       for (int i=0; i<numPoints; i++)
                        {
-                               Timestamp pointStamp = point.getTimestamp();
-                               if (pointStamp != null && pointStamp.isValid())
+                               DataPoint point = inTrack.getPoint(i);
+                               if (point.getPhoto() == null && point.getAudio() == null)
                                {
-                                       long numSeconds = pointStamp.getSecondsSince(mediaStamp);
-                                       pair.addPoint(point, numSeconds);
+                                       Timestamp pointStamp = point.getTimestamp();
+                                       if (pointStamp != null && pointStamp.isValid())
+                                       {
+                                               long numSeconds = pointStamp.getSecondsSince(mediaStamp, _timezone)
+                                                       + inOffset.getTotalSeconds();
+                                               pair.addPoint(point, numSeconds);
+                                       }
                                }
                        }
                }