    001// License: GPL. For details, see LICENSE file.
    002package org.openstreetmap.josm.plugins.streetside.gui.dialog;
    003
    004import java.awt.BorderLayout;
    005import java.awt.Component;
    006import java.awt.Container;
    007import java.awt.FlowLayout;
    008import java.awt.GraphicsEnvironment;
    009import java.util.ArrayList;
    010import java.util.List;
    011import java.util.Objects;
    012import java.util.stream.Collectors;
    013
    014import javax.swing.AbstractListModel;
    015import javax.swing.JButton;
    016import javax.swing.JDialog;
    017import javax.swing.JLabel;
    018import javax.swing.JList;
    019import javax.swing.JPanel;
    020import javax.swing.ListCellRenderer;
    021import javax.swing.ListSelectionModel;
    022import javax.swing.SwingConstants;
    023import javax.swing.UIManager;
    024
    025import org.openstreetmap.josm.gui.Notification;
    026import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    027import org.openstreetmap.josm.gui.util.GuiHelper;
    028import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
    029import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
    030import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
    031import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
    032import org.openstreetmap.josm.tools.I18n;
    033import org.openstreetmap.josm.tools.ImageProvider;
    034import org.openstreetmap.josm.tools.Logging;
    035
    036public class ChooseGeoImageLayersDialog extends JDialog {
    037  private static final long serialVersionUID = -1793622345412435234L;
    038  private static final String QUESTION = I18n.marktr("Which image layers do you want to import into the Streetside layer?");
    039
    040  public ChooseGeoImageLayersDialog(final Component parent, final List<GeoImageLayer> layers) {
    041      super(GuiHelper.getFrameForComponent(parent), I18n.tr(QUESTION));
    042    final Container c = getContentPane();
    043    c.setLayout(new BorderLayout(10, 10));
    044
    045    final JPanel questionPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10));
    046    questionPanel.add(new JLabel(I18n.tr(QUESTION)));
    047    c.add(questionPanel, BorderLayout.NORTH);
    048
    049    final JList<GeoImageLayer> list = new JList<>();
    050    list.setModel(new BasicListModel<>(layers));
    051    list.setCellRenderer(new GeoImageLayerListCellRenderer());
    052    list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    053    c.add(list, BorderLayout.CENTER);
    054
    055    final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
    056    final JButton cancelButton = new JButton(I18n.tr("Cancel"), new ImageProvider("cancel").get());
    057    cancelButton.addActionListener(e -> dispose());
    058    cancelButton.requestFocus();
    059    buttonPanel.add(cancelButton);
    060    final JButton importButton = new JButton(I18n.tr("Import"), new ImageProvider("copy").get());
    061    importButton.addActionListener(e -> {
    062      list.getSelectedValuesList().parallelStream().map(gil -> {
    063        StreetsideSequence seq = new StreetsideSequence();
    064        seq.add(
    065          gil.getImages().parallelStream()
    066            .map(img -> {
    067              try {
    068                return StreetsideImportedImage.createInstance(img);
    069              } catch (IllegalArgumentException iae) {
    070                final String message = I18n.tr("Could not import a geotagged image to the Streetside layer!");
    071                Logging.log(Logging.LEVEL_WARN, message, iae);
    072                if (!GraphicsEnvironment.isHeadless()) {
    073                  new Notification(message).setIcon(StreetsidePlugin.LOGO.get()).show();
    074                }
    075                return null;
    076              }
    077            })
    078            .filter(Objects::nonNull)
    079            .sorted((o1, o2) -> (int) Math.signum(o1.getCd() - o2.getCd())) // order by capture date timestamp (ascending)
    080            .collect(Collectors.toList())
    081        );
    082        return seq;
    083      }).forEach(seq -> {
    084        StreetsideLayer.getInstance().getData().addAll(seq.getImages(), false);
    085        // TODO: @rrh
    086        //StreetsideImportAction.recordChanges(seq.getImages());
    087      });
    088      StreetsideLayer.invalidateInstance();
    089      dispose();
    090    });
    091    buttonPanel.add(importButton);
    092    c.add(buttonPanel, BorderLayout.SOUTH);
    093
    094    setModal(true);
    095    pack();
    096    setLocationRelativeTo(parent);
    097  }
    098
    099  protected static class GeoImageLayerListCellRenderer implements ListCellRenderer<GeoImageLayer> {
    100    @Override
    101    public Component getListCellRendererComponent(
    102      JList<? extends GeoImageLayer> list, GeoImageLayer value, int index, boolean isSelected, boolean cellHasFocus
    103    ) {
    104      final JLabel result = value == null
    105          ? null
    106          /* i18n: {0} is the layer name, {1} the number of images in it */
    107          : new JLabel(I18n.tr("{0} ({1} images)", value.getName(), value.getImages().size()), value.getIcon(), SwingConstants.LEADING);
    108      if (result != null) {
    109        result.setOpaque(true);
    110        result.setBackground(isSelected ? UIManager.getColor("List.selectionBackground") : UIManager.getColor("List.background"));
    111      }
    112      return result;
    113    }
    114  }
    115
    116  private static class BasicListModel<T> extends AbstractListModel<T> {
    117    private static final long serialVersionUID = 3107247955341855290L;
    118    private final List<T> list;
    119
    120    public BasicListModel(List<T> list) {
    121      this.list = list == null ? new ArrayList<>() : list;
    122    }
    123
    124    @Override
    125    public int getSize() {
    126      return list.size();
    127    }
    128
    129    @Override
    130    public T getElementAt(int index) {
    131      return list.get(index);
    132    }
    133  }
    134}