Changeset 18045 in josm for trunk/src/org


Ignore:
Timestamp:
2021-07-16T23:15:08+02:00 (3 years ago)
Author:
Don-vip
Message:

CorrelateGpxWithImages : extract dialog to synchronize time from a photo of the GPS receiver to a new class

Location:
trunk/src/org/openstreetmap/josm/gui/layer/geoimage
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/AdvancedCorrelationSettingsDialog.java

    r18044 r18045  
    5252     * Constructs a new {@code AdvancedCorrelationSettingsDialog}.
    5353     * @param parent The parent element that will be used for position and maximum size
    54      * @param forceTags
     54     * @param forceTags Initial value of forced tagging of all pictures
    5555     */
    5656    public AdvancedCorrelationSettingsDialog(Component parent, boolean forceTags) {
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r18044 r18045  
    77import java.awt.BorderLayout;
    88import java.awt.Cursor;
    9 import java.awt.Dimension;
    109import java.awt.FlowLayout;
    1110import java.awt.Font;
     
    2423import java.beans.PropertyChangeListener;
    2524import java.io.File;
    26 import java.text.DateFormat;
    2725import java.text.ParseException;
    28 import java.text.SimpleDateFormat;
    29 import java.time.Instant;
    30 import java.util.ArrayList;
    31 import java.util.Collections;
    3226import java.util.Comparator;
    33 import java.util.Date;
    3427import java.util.List;
    3528import java.util.TimeZone;
     
    3932
    4033import javax.swing.AbstractAction;
    41 import javax.swing.AbstractListModel;
    4234import javax.swing.BorderFactory;
    4335import javax.swing.DefaultComboBoxModel;
    4436import javax.swing.JButton;
    4537import javax.swing.JCheckBox;
    46 import javax.swing.JFileChooser;
    4738import javax.swing.JLabel;
    48 import javax.swing.JList;
    4939import javax.swing.JOptionPane;
    5040import javax.swing.JPanel;
    51 import javax.swing.JScrollPane;
    5241import javax.swing.JSeparator;
    53 import javax.swing.ListSelectionModel;
    5442import javax.swing.MutableComboBoxModel;
    5543import javax.swing.SwingConstants;
     
    5745import javax.swing.event.DocumentListener;
    5846
    59 import org.openstreetmap.josm.actions.DiskAccessAction;
    6047import org.openstreetmap.josm.data.gpx.GpxData;
    6148import org.openstreetmap.josm.data.gpx.GpxImageCorrelation;
     
    6754import org.openstreetmap.josm.gui.ExtendedDialog;
    6855import org.openstreetmap.josm.gui.MainApplication;
    69 import org.openstreetmap.josm.gui.io.importexport.ImageImporter;
    7056import org.openstreetmap.josm.gui.layer.GpxLayer;
    7157import org.openstreetmap.josm.gui.layer.Layer;
     
    7561import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
    7662import org.openstreetmap.josm.gui.layer.geoimage.AdjustTimezoneAndOffsetDialog.AdjustListener;
     63import org.openstreetmap.josm.gui.layer.geoimage.SynchronizeTimeFromPhotoDialog.TimeZoneItem;
    7764import org.openstreetmap.josm.gui.layer.gpx.GpxDataHelper;
    78 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
    7965import org.openstreetmap.josm.gui.widgets.JosmComboBox;
    8066import org.openstreetmap.josm.gui.widgets.JosmTextField;
     
    8571import org.openstreetmap.josm.tools.Logging;
    8672import org.openstreetmap.josm.tools.Pair;
    87 import org.openstreetmap.josm.tools.date.DateUtils;
    8873
    8974/**
     
    305290     */
    306291    private class SetOffsetActionListener implements ActionListener {
    307         private JCheckBox ckDst;
    308         private ImageDisplay imgDisp;
    309         private JLabel lbExifTime;
    310         private JosmTextField tfGpsTime;
    311 
    312         class TimeZoneItem implements Comparable<TimeZoneItem> {
    313             private final TimeZone tz;
    314             private String rawString;
    315             private String dstString;
    316 
    317             TimeZoneItem(TimeZone tz) {
    318                 this.tz = tz;
    319             }
    320 
    321             public String getFormattedString() {
    322                 if (ckDst.isSelected()) {
    323                     return getDstString();
    324                 } else {
    325                     return getRawString();
    326                 }
    327             }
    328 
    329             public String getDstString() {
    330                 if (dstString == null) {
    331                     dstString = formatTimezone(tz.getRawOffset() + tz.getDSTSavings());
    332                 }
    333                 return dstString;
    334             }
    335 
    336             public String getRawString() {
    337                 if (rawString == null) {
    338                     rawString = formatTimezone(tz.getRawOffset());
    339                 }
    340                 return rawString;
    341             }
    342 
    343             public String getID() {
    344                 return tz.getID();
    345             }
    346 
    347             @Override
    348             public String toString() {
    349                 return getID() + " (" + getFormattedString() + ')';
    350             }
    351 
    352             @Override
    353             public int compareTo(TimeZoneItem o) {
    354                 return getID().compareTo(o.getID());
    355             }
    356 
    357             private String formatTimezone(int offset) {
    358                 return new GpxTimezone((double) offset / TimeUnit.HOURS.toMillis(1)).formatTimezone();
    359             }
    360         }
    361 
    362         private SimpleDateFormat getDateTimeFormat() {
    363             return (SimpleDateFormat) DateUtils.getDateTimeFormat(DateFormat.SHORT, DateFormat.MEDIUM);
    364         }
    365292
    366293        @Override
    367294        public void actionPerformed(ActionEvent e) {
    368             SimpleDateFormat dateFormat = getDateTimeFormat();
    369 
    370             JPanel panel = new JPanel(new BorderLayout());
    371             panel.add(new JLabel(tr("<html>Take a photo of your GPS receiver while it displays the time.<br>"
    372                     + "Display that photo here.<br>"
    373                     + "And then, simply capture the time you read on the photo and select a timezone<hr></html>")),
    374                     BorderLayout.NORTH);
    375 
    376             imgDisp = new ImageDisplay();
    377             imgDisp.setPreferredSize(new Dimension(300, 225));
    378             panel.add(imgDisp, BorderLayout.CENTER);
    379 
    380             JPanel panelTf = new JPanel(new GridBagLayout());
    381 
    382             GridBagConstraints gc = new GridBagConstraints();
    383             gc.gridx = gc.gridy = 0;
    384             gc.gridwidth = gc.gridheight = 1;
    385             gc.weightx = gc.weighty = 0.0;
    386             gc.fill = GridBagConstraints.NONE;
    387             gc.anchor = GridBagConstraints.LINE_START;
    388             panelTf.add(new JLabel(tr("Photo time (from exif):")), gc);
    389 
    390             lbExifTime = new JLabel();
    391             gc.gridx = 1;
    392             gc.weightx = 1.0;
    393             gc.fill = GridBagConstraints.HORIZONTAL;
    394             gc.gridwidth = 2;
    395             panelTf.add(lbExifTime, gc);
    396 
    397             gc.gridx = 0;
    398             gc.gridy = 1;
    399             gc.gridwidth = gc.gridheight = 1;
    400             gc.weightx = gc.weighty = 0.0;
    401             gc.fill = GridBagConstraints.NONE;
    402             gc.anchor = GridBagConstraints.LINE_START;
    403             panelTf.add(new JLabel(tr("Gps time (read from the above photo): ")), gc);
    404 
    405             tfGpsTime = new JosmTextField(12);
    406             tfGpsTime.setEnabled(false);
    407             tfGpsTime.setMinimumSize(new Dimension(155, tfGpsTime.getMinimumSize().height));
    408             gc.gridx = 1;
    409             gc.weightx = 1.0;
    410             gc.fill = GridBagConstraints.HORIZONTAL;
    411             panelTf.add(tfGpsTime, gc);
    412 
    413             gc.gridx = 2;
    414             gc.weightx = 0.2;
    415             panelTf.add(new JLabel(" ["+dateFormat.toLocalizedPattern()+']'), gc);
    416 
    417             gc.gridx = 0;
    418             gc.gridy = 2;
    419             gc.gridwidth = gc.gridheight = 1;
    420             gc.weightx = gc.weighty = 0.0;
    421             gc.fill = GridBagConstraints.NONE;
    422             gc.anchor = GridBagConstraints.LINE_START;
    423             panelTf.add(new JLabel(tr("Photo taken in the timezone of: ")), gc);
    424 
    425             ckDst = new JCheckBox(tr("Use daylight saving time (where applicable)"), Config.getPref().getBoolean("geoimage.timezoneid.dst"));
    426 
    427             String[] tmp = TimeZone.getAvailableIDs();
    428             List<TimeZoneItem> vtTimezones = new ArrayList<>(tmp.length);
    429 
    430             String defTzStr = Config.getPref().get("geoimage.timezoneid", "");
    431             if (defTzStr.isEmpty()) {
    432                 defTzStr = TimeZone.getDefault().getID();
    433             }
    434             TimeZoneItem defTzItem = null;
    435 
    436             for (String tzStr : tmp) {
    437                 TimeZoneItem tz = new TimeZoneItem(TimeZone.getTimeZone(tzStr));
    438                 vtTimezones.add(tz);
    439                 if (defTzStr.equals(tzStr)) {
    440                     defTzItem = tz;
    441                 }
    442             }
    443 
    444             Collections.sort(vtTimezones);
    445 
    446             JosmComboBox<TimeZoneItem> cbTimezones = new JosmComboBox<>(vtTimezones.toArray(new TimeZoneItem[0]));
    447 
    448             if (defTzItem != null) {
    449                 cbTimezones.setSelectedItem(defTzItem);
    450             }
    451 
    452             gc.gridx = 1;
    453             gc.weightx = 1.0;
    454             gc.gridwidth = 2;
    455             gc.fill = GridBagConstraints.HORIZONTAL;
    456             panelTf.add(cbTimezones, gc);
    457 
    458             gc.gridy = 3;
    459             panelTf.add(ckDst, gc);
    460 
    461             ckDst.addActionListener(x -> cbTimezones.repaint());
    462 
    463             panel.add(panelTf, BorderLayout.SOUTH);
    464 
    465             JPanel panelLst = new JPanel(new BorderLayout());
    466 
    467             JList<String> imgList = new JList<>(new AbstractListModel<String>() {
    468                 @Override
    469                 public String getElementAt(int i) {
    470                     return yLayer.getImageData().getImages().get(i).getDisplayName();
    471                 }
    472 
    473                 @Override
    474                 public int getSize() {
    475                     return yLayer.getImageData().getImages().size();
    476                 }
    477             });
    478             imgList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    479             imgList.getSelectionModel().addListSelectionListener(evt -> {
    480                 int index = imgList.getSelectedIndex();
    481                 ImageEntry img = yLayer.getImageData().getImages().get(index);
    482                 updateExifComponents(img);
    483             });
    484             panelLst.add(new JScrollPane(imgList), BorderLayout.CENTER);
    485 
    486             JButton openButton = new JButton(tr("Open another photo"));
    487             openButton.addActionListener(ae -> {
    488                 AbstractFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true, false, null,
    489                         ImageImporter.FILE_FILTER_WITH_FOLDERS, JFileChooser.FILES_ONLY, "geoimage.lastdirectory");
    490                 if (fc == null)
    491                     return;
    492                 ImageEntry entry = new ImageEntry(fc.getSelectedFile());
    493                 entry.extractExif();
    494                 updateExifComponents(entry);
    495             });
    496             panelLst.add(openButton, BorderLayout.PAGE_END);
    497 
    498             panel.add(panelLst, BorderLayout.LINE_START);
    499 
    500295            boolean isOk = false;
    501296            while (!isOk) {
    502                 int answer = JOptionPane.showConfirmDialog(
    503                         MainApplication.getMainFrame(), panel,
    504                         tr("Synchronize time from a photo of the GPS receiver"),
    505                         JOptionPane.OK_CANCEL_OPTION,
    506                         JOptionPane.QUESTION_MESSAGE
    507                 );
    508                 if (answer != JOptionPane.OK_OPTION)
     297                SynchronizeTimeFromPhotoDialog ed = new SynchronizeTimeFromPhotoDialog(
     298                        MainApplication.getMainFrame(), yLayer.getImageData().getImages());
     299                int answer = ed.showDialog().getValue();
     300                if (answer != 1)
    509301                    return;
    510302
     
    512304
    513305                try {
    514                     delta = dateFormat.parse(lbExifTime.getText()).getTime()
    515                           - dateFormat.parse(tfGpsTime.getText()).getTime();
     306                    delta = ed.getDelta();
    516307                } catch (ParseException ex) {
    517308                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(), tr("Error while parsing the date.\n"
     
    521312                }
    522313
    523                 TimeZoneItem selectedTz = (TimeZoneItem) cbTimezones.getSelectedItem();
     314                TimeZoneItem selectedTz = ed.getTimeZoneItem();
    524315
    525316                Config.getPref().put("geoimage.timezoneid", selectedTz.getID());
    526                 Config.getPref().putBoolean("geoimage.timezoneid.dst", ckDst.isSelected());
     317                Config.getPref().putBoolean("geoimage.timezoneid.dst", ed.isDstSelected());
    527318                tfOffset.setText(GpxTimeOffset.milliseconds(delta).formatOffset());
    528319                tfTimezone.setText(selectedTz.getFormattedString());
    529320
    530321                isOk = true;
    531 
    532322            }
    533323            statusBarUpdater.matchAndUpdateStatusBar();
    534324            yLayer.updateBufferAndRepaint();
    535         }
    536 
    537         void updateExifComponents(ImageEntry img) {
    538             imgDisp.setImage(img);
    539             Instant date = img.getExifInstant();
    540             if (date != null) {
    541                 DateFormat df = getDateTimeFormat();
    542                 df.setTimeZone(DateUtils.UTC); // EXIF data does not contain timezone information and is read as UTC
    543                 lbExifTime.setText(df.format(Date.from(date)));
    544                 tfGpsTime.setText(df.format(Date.from(date)));
    545                 tfGpsTime.setCaretPosition(tfGpsTime.getText().length());
    546                 tfGpsTime.setEnabled(true);
    547                 tfGpsTime.requestFocus();
    548             } else {
    549                 lbExifTime.setText(tr("No date"));
    550                 tfGpsTime.setText("");
    551                 tfGpsTime.setEnabled(false);
    552             }
    553325        }
    554326    }
Note: See TracChangeset for help on using the changeset viewer.