// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.widgets;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeListener;
import javax.swing.Action;
import javax.swing.JPasswordField;
import javax.swing.TransferHandler;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.tools.Logging;
/**
* A subclass of {@link JPasswordField} to implement a workaround to
* JDK bug 6322854.
*
* @see https://josm.openstreetmap.de/ticket/8404
* @see https://hg.netbeans.org/main/rev/33cb2e81b640
* @since 5752
*/
public class JosmPasswordField extends JPasswordField implements FocusListener {
/**
* Constructs a new JosmPasswordField
,
* with a default document, null
starting
* text string, and 0 column width.
*/
public JosmPasswordField() {
workaroundJdkBug6322854(this);
addFocusListener(this);
}
/**
* Constructs a new JosmPasswordField
that uses the
* given text storage model and the given number of columns.
* This is the constructor through which the other constructors feed.
* The echo character is set to '*', but may be changed by the current
* Look and Feel. If the document model is
* null
, a default one will be created.
*
* @param doc the text storage to use
* @param txt the text to be displayed, null
if none
* @param columns the number of columns to use to calculate
* the preferred width >= 0; if columns is set to zero, the
* preferred width will be whatever naturally results from
* the component implementation
*/
public JosmPasswordField(Document doc, String txt, int columns) {
super(doc, txt, columns);
workaroundJdkBug6322854(this);
addFocusListener(this);
}
/**
* Constructs a new empty JosmPasswordField
with the specified
* number of columns. A default model is created, and the initial string
* is set to null
.
*
* @param columns the number of columns >= 0
*/
public JosmPasswordField(int columns) {
super(columns);
workaroundJdkBug6322854(this);
addFocusListener(this);
}
/**
* Constructs a new JPasswordField
initialized with
* the specified text and columns. The document model is set to
* the default.
*
* @param text the text to be displayed, null
if none
* @param columns the number of columns >= 0
*/
public JosmPasswordField(String text, int columns) {
super(text, columns);
workaroundJdkBug6322854(this);
addFocusListener(this);
}
/**
* Constructs a new JosmPasswordField
initialized
* with the specified text. The document model is set to the
* default, and the number of columns to 0.
*
* @param text the text to be displayed, null
if none
*/
public JosmPasswordField(String text) {
super(text);
workaroundJdkBug6322854(this);
addFocusListener(this);
}
@Override
public void focusGained(FocusEvent e) {
if (Main.map != null) {
Main.map.keyDetector.setEnabled(false);
}
}
@Override
public void focusLost(FocusEvent e) {
if (Main.map != null) {
Main.map.keyDetector.setEnabled(true);
}
}
/**
* Implements a workaround to JDK bug 6322854.
* This method can be deleted after Oracle decides to fix this bug...
* @param text The {@link JTextComponent} to protect.
*/
public static final void workaroundJdkBug6322854(final JTextComponent text) {
if (text != null) {
text.getActionMap().put("paste", new Action() {
private final Action pasteAction = TransferHandler.getPasteAction();
@Override
public void actionPerformed(ActionEvent e) {
try {
pasteAction.actionPerformed(e);
} catch (NullPointerException npe) { // NOPMD
Logging.log(Logging.LEVEL_ERROR, "NullPointerException occured because of JDK bug 6322854. "
+"Copy/Paste operation has not been performed. Please complain to Oracle: "+
"https://bugs.openjdk.java.net/browse/JDK-6322854", npe);
}
}
@Override
public void setEnabled(boolean b) {
pasteAction.setEnabled(b);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
pasteAction.removePropertyChangeListener(listener);
}
@Override
public void putValue(String key, Object value) {
pasteAction.putValue(key, value);
}
@Override
public boolean isEnabled() {
return pasteAction.isEnabled();
}
@Override
public Object getValue(String key) {
return pasteAction.getValue(key);
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
pasteAction.addPropertyChangeListener(listener);
}
});
}
}
}