package net.classicube.launcher.gui; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.util.logging.Level; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.text.JTextComponent; import net.classicube.launcher.LogUtil; public class CutCopyPasteAdapter extends MouseAdapter implements ClipboardOwner { public static CutCopyPasteAdapter addToComponent( final JTextComponent component, final boolean allowCopy, final boolean allowModification) { CutCopyPasteAdapter adapter = new CutCopyPasteAdapter(component, allowCopy, allowModification); component.addMouseListener(adapter); return adapter; } private final JTextComponent component; private final boolean allowCopy; private final boolean allowModification; private CutCopyPasteAdapter( final JTextComponent component, final boolean allowCopy, final boolean allowModification) { if (!allowCopy && !allowModification) { throw new IllegalArgumentException("Either allowCopy or allowModification must be set."); } this.component = component; this.allowCopy = allowCopy; this.allowModification = allowModification; } @Override public void mousePressed(final MouseEvent e) { if (e.isPopupTrigger()) { doPop(e); } } @Override public void mouseReleased(final MouseEvent e) { if (e.isPopupTrigger()) { doPop(e); } } private void doPop(final MouseEvent e) { final CopyPasteMenu menu = new CopyPasteMenu(); menu.show(e.getComponent(), e.getX(), e.getY()); } @Override public void lostOwnership(Clipboard clipboard, Transferable contents) { // Do nothing. // This overload is necessary to be a ClipboardOwner. } // Menu that provides [Cut], [Copy], and [Paste] buttons for the text box. // Isn't it silly that I have to do this manually in Java? class CopyPasteMenu extends JPopupMenu { CopyPasteMenu() { final boolean hasSelectedText = (component.getSelectedText() != null) && component.getSelectedText().length() > 0; if (allowCopy && allowModification) { final JMenuItem cutMenuItem = new JMenuItem("Cut"); cutMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setClipboardContents(component.getSelectedText()); final int selStart = component.getSelectionStart(); final int selEnd = component.getSelectionEnd(); String newText = component.getText().substring(0, selStart) + component.getText().substring(selEnd); component.setText(newText); component.setSelectionStart(selStart); component.setSelectionEnd(component.getSelectionStart()); } }); cutMenuItem.setEnabled(hasSelectedText); add(cutMenuItem); } if (allowCopy) { final JMenuItem copyMenuItem = new JMenuItem("Copy"); copyMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setClipboardContents(component.getSelectedText()); } }); copyMenuItem.setEnabled(hasSelectedText); add(copyMenuItem); } if (allowModification) { final JMenuItem pasteMenuItem = new JMenuItem("Paste"); pasteMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final int selStart = component.getSelectionStart(); final int selEnd = component.getSelectionEnd(); final String pastedText = getClipboardContents(); final String newText = component.getText().substring(0, selStart) + pastedText + component.getText().substring(selEnd); component.setText(newText); component.setSelectionStart(selStart + pastedText.length()); component.setSelectionEnd(component.getSelectionStart()); } }); add(pasteMenuItem); } } } // Places string to clipboard, and makes PromptScreen the clipboard owner public void setClipboardContents(String stringToCopy) { final StringSelection stringSelection = new StringSelection(stringToCopy); final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(stringSelection, this); } // Tries to get string from clipboard. Returns empty string if impossible. public String getClipboardContents() { String result = ""; final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); final Transferable contents = clipboard.getContents(null); if ((contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) { try { result = (String) contents.getTransferData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException | IOException ex) { LogUtil.getLogger().log(Level.WARNING, "Error pasting text from clipboard", ex); } } return result; } }