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}