001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
003
004import java.awt.Color;
005import java.awt.Component;
006import java.awt.Toolkit;
007import java.awt.datatransfer.Transferable;
008import java.awt.event.ActionEvent;
009
010import javax.swing.AbstractAction;
011import javax.swing.Action;
012import javax.swing.BorderFactory;
013import javax.swing.JLabel;
014import javax.swing.JPopupMenu;
015
016import org.openstreetmap.josm.tools.I18n;
017import org.openstreetmap.josm.tools.ImageProvider;
018import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
019
020public class ClipboardAction extends AbstractAction {
021
022  private static final long serialVersionUID = -7298944557860158010L;
023  /**
024   * The duration in milliseconds for which the popup will be shown
025   */
026  private static final long POPUP_DURATION = 3000;
027  /**
028   * A small popup that shows up when the key has been moved to the clipboard
029   */
030  private final JPopupMenu popup;
031  /**
032   * The component which is used as parent of the shown popup.
033   * If this is <code>null</code>, no popup will be shown.
034   */
035  private Component popupParent;
036  /**
037   * The UNIX epoch time when the popup for this action was shown the last time
038   */
039  private long lastPopupShowTime;
040  /**
041   * The contents that are transfered into the clipboard when the action is executed.
042   * If this is <code>null</code>, the clipboard won't be changed.
043   */
044  private Transferable contents;
045
046  public ClipboardAction(final String name, final Transferable contents) {
047    super(name, ImageProvider.get("copy", ImageSizes.SMALLICON));
048    this.contents = contents;
049
050    // Init popup
051    popup = new JPopupMenu();
052    // TODO: tr( RRH
053    JLabel label = new JLabel(I18n.tr("Key copied to clipboard") + '…');
054    label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
055    popup.add(label);
056    popup.setBackground(new Color(0f, 0f, 0f, .5f));
057    label.setForeground(Color.WHITE);
058  }
059
060  /**
061   * @param contents the contents, which should be copied to the clipboard when the {@link Action} is executed
062   */
063  public void setContents(Transferable contents) {
064    this.contents = contents;
065    setEnabled(contents != null);
066  }
067
068  /**
069   * Sets the component, under which the popup will be shown, which indicates that the key was copied to the clipboard.
070   * @param popupParent the component to set as parent of the popup
071   */
072  public void setPopupParent(Component popupParent) {
073    this.popupParent = popupParent;
074  }
075
076  /* (non-Javadoc)
077   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
078   */
079  @Override
080  public void actionPerformed(ActionEvent e) {
081    if (contents != null) {
082      Toolkit.getDefaultToolkit().getSystemClipboard().setContents(contents, null);
083      if (popupParent != null) {
084        popup.show(popupParent, 0, popupParent.getHeight() + 2);
085        new Thread(() -> {
086          long threadStart = System.currentTimeMillis();
087          lastPopupShowTime = threadStart;
088          try {
089            Thread.sleep(POPUP_DURATION);
090          } catch (InterruptedException e1) {
091            if (threadStart == lastPopupShowTime) {
092              popup.setVisible(false);
093            }
094          }
095          if (System.currentTimeMillis() >= lastPopupShowTime + POPUP_DURATION) {
096            popup.setVisible(false);
097          }
098        }).start();
099      }
100    }
101  }
102
103}