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}