source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/JosmTextField.java @ 11809

Last change on this file since 11809 was 11809, checked in by Don-vip, 9 months ago

findbugs - BC_UNCONFIRMED_CAST

  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import java.awt.Color;
5import java.awt.FontMetrics;
6import java.awt.Graphics;
7import java.awt.Graphics2D;
8import java.awt.Insets;
9import java.awt.RenderingHints;
10import java.awt.event.FocusEvent;
11import java.awt.event.FocusListener;
12
13import javax.swing.JTextField;
14import javax.swing.text.Document;
15
16import org.openstreetmap.josm.Main;
17
18/**
19 * Subclass of {@link JTextField} that:<ul>
20 * <li>adds a "native" context menu (undo/redo/cut/copy/paste/select all)</li>
21 * <li>adds an optional "hint" displayed when no text has been entered</li>
22 * <li>disables the global advanced key press detector when focused</li>
23 * <li>implements a workaround to <a href="https://bugs.openjdk.java.net/browse/JDK-6322854">JDK bug 6322854</a></li>
24 * </ul><br>This class must be used everywhere in core and plugins instead of {@code JTextField}.
25 * @since 5886
26 */
27public class JosmTextField extends JTextField implements FocusListener {
28
29    private String hint;
30
31    /**
32     * Constructs a new <code>JosmTextField</code> that uses the given text
33     * storage model and the given number of columns.
34     * This is the constructor through which the other constructors feed.
35     * If the document is <code>null</code>, a default model is created.
36     *
37     * @param doc  the text storage to use; if this is <code>null</code>,
38     *      a default will be provided by calling the
39     *      <code>createDefaultModel</code> method
40     * @param text  the initial string to display, or <code>null</code>
41     * @param columns  the number of columns to use to calculate
42     *   the preferred width &gt;= 0; if <code>columns</code>
43     *   is set to zero, the preferred width will be whatever
44     *   naturally results from the component implementation
45     * @throws IllegalArgumentException if <code>columns</code> &lt; 0
46     */
47    public JosmTextField(Document doc, String text, int columns) {
48        this(doc, text, columns, true);
49    }
50
51    /**
52     * Constructs a new <code>JosmTextField</code> that uses the given text
53     * storage model and the given number of columns.
54     * This is the constructor through which the other constructors feed.
55     * If the document is <code>null</code>, a default model is created.
56     *
57     * @param doc  the text storage to use; if this is <code>null</code>,
58     *      a default will be provided by calling the
59     *      <code>createDefaultModel</code> method
60     * @param text  the initial string to display, or <code>null</code>
61     * @param columns  the number of columns to use to calculate
62     *   the preferred width &gt;= 0; if <code>columns</code>
63     *   is set to zero, the preferred width will be whatever
64     *   naturally results from the component implementation
65     * @param undoRedo Enables or not Undo/Redo feature. Not recommended for table cell editors, unless each cell provides its own editor
66     * @throws IllegalArgumentException if <code>columns</code> &lt; 0
67     */
68    public JosmTextField(Document doc, String text, int columns, boolean undoRedo) {
69        super(doc, text, columns);
70        TextContextualPopupMenu.enableMenuFor(this, undoRedo);
71        // Fix minimum size when columns are specified
72        if (columns > 0) {
73            setMinimumSize(getPreferredSize());
74        }
75        addFocusListener(this);
76        // Workaround for Java bug 6322854
77        JosmPasswordField.workaroundJdkBug6322854(this);
78    }
79
80    /**
81     * Constructs a new <code>JosmTextField</code> initialized with the
82     * specified text and columns.  A default model is created.
83     *
84     * @param text the text to be displayed, or <code>null</code>
85     * @param columns  the number of columns to use to calculate
86     *   the preferred width; if columns is set to zero, the
87     *   preferred width will be whatever naturally results from
88     *   the component implementation
89     */
90    public JosmTextField(String text, int columns) {
91        this(null, text, columns);
92    }
93
94    /**
95     * Constructs a new <code>JosmTextField</code> initialized with the
96     * specified text. A default model is created and the number of
97     * columns is 0.
98     *
99     * @param text the text to be displayed, or <code>null</code>
100     */
101    public JosmTextField(String text) {
102        this(null, text, 0);
103    }
104
105    /**
106     * Constructs a new empty <code>JosmTextField</code> with the specified
107     * number of columns.
108     * A default model is created and the initial string is set to
109     * <code>null</code>.
110     *
111     * @param columns  the number of columns to use to calculate
112     *   the preferred width; if columns is set to zero, the
113     *   preferred width will be whatever naturally results from
114     *   the component implementation
115     */
116    public JosmTextField(int columns) {
117        this(null, null, columns);
118    }
119
120    /**
121     * Constructs a new <code>JosmTextField</code>.  A default model is created,
122     * the initial string is <code>null</code>,
123     * and the number of columns is set to 0.
124     */
125    public JosmTextField() {
126        this(null, null, 0);
127    }
128
129    /**
130     * Replies the hint displayed when no text has been entered.
131     * @return the hint
132     * @since 7505
133     */
134    public final String getHint() {
135        return hint;
136    }
137
138    /**
139     * Sets the hint to display when no text has been entered.
140     * @param hint the hint to set
141     * @since 7505
142     */
143    public final void setHint(String hint) {
144        this.hint = hint;
145    }
146
147    @Override
148    public void paint(Graphics g) {
149        super.paint(g);
150        if (hint != null && !hint.isEmpty() && getText().isEmpty() && !isFocusOwner()) {
151            // Taken from http://stackoverflow.com/a/24571681/2257172
152            int h = getHeight();
153            if (g instanceof Graphics2D) {
154                ((Graphics2D) g).setRenderingHint(
155                        RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
156            }
157            Insets ins = getInsets();
158            FontMetrics fm = g.getFontMetrics();
159            int c0 = getBackground().getRGB();
160            int c1 = getForeground().getRGB();
161            int m = 0xfefefefe;
162            int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1);
163            g.setColor(new Color(c2, true));
164            g.drawString(hint, ins.left, h / 2 + fm.getAscent() / 2 - 2);
165        }
166    }
167
168    @Override
169    public void focusGained(FocusEvent e) {
170        if (Main.map != null) {
171            Main.map.keyDetector.setEnabled(false);
172        }
173        repaint();
174    }
175
176    @Override
177    public void focusLost(FocusEvent e) {
178        if (Main.map != null) {
179            Main.map.keyDetector.setEnabled(true);
180        }
181        repaint();
182    }
183}
Note: See TracBrowser for help on using the repository browser.