001package org.jdesktop.swingx.plaf;
002
003import static javax.swing.BorderFactory.createEmptyBorder;
004
005import java.awt.Insets;
006import java.awt.Rectangle;
007
008import javax.swing.JTextField;
009import javax.swing.border.Border;
010import javax.swing.plaf.TextUI;
011import javax.swing.text.JTextComponent;
012
013import org.jdesktop.swingx.search.NativeSearchFieldSupport;
014import org.jdesktop.swingx.util.OS;
015
016/**
017 * {@link PromptTextUI} implementation for rendering prompts on
018 * {@link JTextField}s and uses a {@link JTextField} as a prompt component.
019 * 
020 * @author Peter Weishapl <petw@gmx.net>
021 * 
022 */
023public class PromptTextFieldUI extends PromptTextUI {
024    /**
025     * Creates a new {@link PromptTextFieldUI}.
026     * 
027     * @param delegate
028     */
029    public PromptTextFieldUI(TextUI delegate) {
030        super(delegate);
031    }
032
033    /**
034     * Overrides {@link #getPromptComponent(JTextComponent)} to additionally
035     * update {@link JTextField} specific properties.
036     */
037    @Override
038    public JTextComponent getPromptComponent(JTextComponent txt) {
039        LabelField lbl = (LabelField) super.getPromptComponent(txt);
040        JTextField txtField = (JTextField) txt;
041
042        lbl.setHorizontalAlignment(txtField.getHorizontalAlignment());
043        lbl.setColumns(txtField.getColumns());
044
045        // Make search field in Leopard paint focused border.
046        lbl.hasFocus = txtField.hasFocus()
047                && NativeSearchFieldSupport.isNativeSearchField(txtField);
048
049        // leopard client properties. see
050        // http://developer.apple.com/technotes/tn2007/tn2196.html#JTEXTFIELD_VARIANT
051        NativeSearchFieldSupport.setSearchField(lbl, NativeSearchFieldSupport
052                .isSearchField(txtField));
053        NativeSearchFieldSupport.setFindPopupMenu(lbl, NativeSearchFieldSupport
054                .getFindPopupMenu(txtField));
055
056        // here we need to copy the border again for Mac OS X, because the above
057        // calls may have replaced it.
058        Border b = txt.getBorder();
059
060        if (b == null) {
061            lbl.setBorder(txt.getBorder());
062        } else {
063            Insets insets = b.getBorderInsets(txt);
064            lbl.setBorder(
065                    createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right));
066        }
067        //              lbl.setBorder(txtField.getBorder());
068
069        // buddy support: not needed, because BuddyLayoutAndBorder queries
070        // original text field
071        // BuddySupport.setOuterMargin(lbl,
072        // BuddySupport.getOuterMargin(txtField));
073        // BuddySupport.setLeft(lbl, BuddySupport.getLeft(txtField));
074        // BuddySupport.setRight(lbl, BuddySupport.getRight(txtField));
075
076        return lbl;
077    }
078
079    /**
080     * Returns a shared {@link JTextField}.
081     */
082    @Override
083    protected JTextComponent createPromptComponent() {
084        return new LabelField();
085    }
086
087    private static final class LabelField extends JTextField {
088        boolean hasFocus;
089
090        @Override
091        public boolean hasFocus() {
092            return hasFocus;
093        }
094
095        /**
096         * {@inheritDoc} <p>
097         * 
098         * Overridden to not automatically de/register itself from/to the ToolTipManager.
099         * As rendering component it is not considered to be active in any way, so the
100         * manager must not listen.
101         */
102        @Override
103        public void setToolTipText(String text) {
104            putClientProperty(TOOL_TIP_TEXT_KEY, text);
105        }
106
107        /**
108         * Overridden for performance reasons.
109         * See the <a href="#override">Implementation Note</a>
110         * for more information.
111         *
112         * @since 1.5
113         */
114        @Override
115        public void invalidate() {}
116
117        /**
118         * Overridden for performance reasons.
119         * See the <a href="#override">Implementation Note</a>
120         * for more information.
121         */
122        @Override
123        public void validate() {}
124
125        /**
126         * Overridden for performance reasons.
127         * See the <a href="#override">Implementation Note</a>
128         * for more information.
129         */
130        @Override
131        public void revalidate() {}
132
133        /**
134         * Overridden for performance reasons.
135         * See the <a href="#override">Implementation Note</a>
136         * for more information.
137         */
138        @Override
139        public void repaint(long tm, int x, int y, int width, int height) {}
140
141        /**
142         * Overridden for performance reasons.
143         * See the <a href="#override">Implementation Note</a>
144         * for more information.
145         */
146        @Override
147        public void repaint(Rectangle r) { }
148
149        /**
150         * Overridden for performance reasons.
151         * See the <a href="#override">Implementation Note</a>
152         * for more information.
153         *
154         * @since 1.5
155         */
156        @Override
157        public void repaint() {
158        }
159
160        /**
161         * Overridden for performance reasons.
162         * See the <a href="#override">Implementation Note</a>
163         * for more information.
164         */
165        @Override
166        protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
167                if (OS.isMacOSX()) {
168                        super.firePropertyChange(propertyName, oldValue, newValue);
169                } else {
170                        // Strings get interned...
171                        if ("document".equals(propertyName)) {
172                                super.firePropertyChange(propertyName, oldValue, newValue);
173                        }
174                }
175        }
176
177        /**
178         * Overridden for performance reasons.
179         * See the <a href="#override">Implementation Note</a>
180         * for more information.
181         */
182        @Override
183        public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
184                if (OS.isMacOSX()) {
185                        super.firePropertyChange(propertyName, oldValue, newValue);
186                }
187        }
188    }
189}