1 6 21 22 package de.schlichtherle.swing; 23 24 import java.awt.Component ; 25 import java.awt.event.ActionListener ; 26 import java.beans.PropertyChangeEvent ; 27 import java.beans.PropertyChangeListener ; 28 import java.io.Serializable ; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 32 import javax.swing.ComboBoxEditor ; 33 import javax.swing.ComboBoxModel ; 34 import javax.swing.JComboBox ; 35 import javax.swing.MutableComboBoxModel ; 36 import javax.swing.event.DocumentEvent ; 37 import javax.swing.event.DocumentListener ; 38 import javax.swing.plaf.basic.BasicComboBoxEditor ; 39 import javax.swing.text.BadLocationException ; 40 import javax.swing.text.Caret ; 41 import javax.swing.text.Document ; 42 import javax.swing.text.JTextComponent ; 43 44 63 public abstract class AbstractComboBoxBrowser implements Serializable { 64 65 private final Listener listener = new Listener (); 66 67 private JComboBox comboBox; 68 69 72 private transient boolean recursion; 73 74 78 public AbstractComboBoxBrowser() { 79 } 80 81 89 public AbstractComboBoxBrowser(final JComboBox comboBox) { 90 changeComboBox(null, comboBox, false); 91 } 92 93 97 public JComboBox getComboBox() { 98 return comboBox; 99 } 100 101 109 public void setComboBox(final JComboBox comboBox) { 110 changeComboBox(getComboBox(), comboBox, true); 111 } 112 113 private void changeComboBox( 114 final JComboBox oldCB, 115 final JComboBox newCB, 116 final boolean update) { 117 if (newCB == oldCB) 118 return; 119 120 ComboBoxEditor oldCBE = null; 121 if (oldCB != null) { 122 oldCB.removePropertyChangeListener("editor", listener); 123 oldCBE = oldCB.getEditor(); 124 oldCB.setEditor(((ComboBoxEditorProxy) oldCBE).getEditor()); 125 } 126 127 this.comboBox = newCB; 128 129 ComboBoxEditor newCBE = null; 130 if (newCB != null) { 131 newCB.updateUI(); newCBE = new ComboBoxEditorProxy(newCB.getEditor()); 133 newCB.setEditor(newCBE); 134 newCB.addPropertyChangeListener("editor", listener); 135 } 136 137 changeEditor(oldCBE, newCBE, update); 138 } 139 140 private void changeEditor( 141 final ComboBoxEditor oldCBE, 142 final ComboBoxEditor newCBE, 143 final boolean update) { 144 if (newCBE == oldCBE) 145 return; 146 147 JTextComponent oldText = null; 148 if (oldCBE != null) { 149 final Component component = oldCBE.getEditorComponent(); 150 if (component instanceof JTextComponent ) 151 oldText = (JTextComponent ) component; 152 } 153 154 JTextComponent newText = null; 155 if (newCBE != null) { 156 final Component component = newCBE.getEditorComponent(); 157 if (component instanceof JTextComponent ) 158 newText = (JTextComponent ) component; 159 } 160 161 changeText(oldText, newText, update); 162 } 163 164 private void changeText( 165 final JTextComponent oldTC, 166 final JTextComponent newTC, 167 final boolean update) { 168 if (newTC == oldTC) 169 return; 170 171 Document oldDocument = null; 172 if (oldTC != null) { 173 oldTC.removePropertyChangeListener("document", listener); 174 oldDocument = oldTC.getDocument(); 175 } 176 177 Document newDocument = null; 178 if (newTC != null) { 179 newDocument = newTC.getDocument(); 180 newTC.addPropertyChangeListener("document", listener); 181 } 182 183 changeDocument(oldDocument, newDocument, update); 184 } 185 186 private void changeDocument( 187 final Document oldDoc, 188 final Document newDoc, 189 final boolean update) { 190 if (newDoc == oldDoc) 191 return; 192 193 if (oldDoc != null) 194 oldDoc.removeDocumentListener(listener); 195 196 if (newDoc != null) { 197 if (update) { 198 String txt; 199 try { 200 txt = newDoc.getText(0, newDoc.getLength()); 201 } catch (BadLocationException e) { 202 txt = null; 203 } 204 update(txt); 205 } 206 newDoc.addDocumentListener(listener); 207 } 208 } 209 210 private void documentUpdated() { 211 if (lock()) 212 return; 213 try { 214 final JComboBox cb = getComboBox(); 215 final ComboBoxEditor cbe = cb.getEditor(); 216 final JTextComponent tc = (JTextComponent ) cbe.getEditorComponent(); 217 assert cb.isShowing() || !tc.isFocusOwner(); 218 if (!tc.isFocusOwner() ) 219 return; 220 221 cb.setPopupVisible(false); 223 if (update(tc.getText())) 224 cb.setPopupVisible(true); 225 } finally { 226 unlock(); 227 } 228 } 229 230 private void updateEditor(final ComboBoxEditor cbe, final Object item) { 231 if (lock()) 232 return; 233 try { 234 cbe.setItem(item); 235 if (!(item instanceof String )) 236 return; 237 238 final JComboBox cb = getComboBox(); 239 final JTextComponent tc = (JTextComponent ) cbe.getEditorComponent(); 240 assert cb.isShowing() || !tc.isFocusOwner(); 241 if (!tc.isFocusOwner() ) 242 return; 243 244 final Caret caret = tc.getCaret(); 249 caret.setDot(((String ) item).length()); 250 } finally { 251 unlock(); 252 } 253 } 254 255 269 protected abstract boolean update(String initials); 270 271 278 private final boolean lock() { 279 if (recursion) 280 return true; 281 recursion = true; 282 return false; 283 } 284 285 290 private final void unlock() { 291 recursion = false; 292 } 293 294 private final class Listener 295 implements DocumentListener , PropertyChangeListener { 296 public void insertUpdate(DocumentEvent e) { 297 documentUpdated(); 298 } 299 300 public void removeUpdate(DocumentEvent e) { 301 documentUpdated(); 302 } 303 304 public void changedUpdate(DocumentEvent e) { 305 documentUpdated(); 306 } 307 308 public void propertyChange(final PropertyChangeEvent e) { 309 final String property = e.getPropertyName(); 310 if ("editor".equals(property)) 311 changeEditor( (ComboBoxEditor ) e.getOldValue(), 312 (ComboBoxEditor ) e.getNewValue(), 313 true); 314 else if ("document".equals(property)) 315 changeDocument( (Document ) e.getOldValue(), 316 (Document ) e.getNewValue(), 317 true); 318 else 319 throw new AssertionError ( 320 "Received change event for unknown property: " 321 + property); 322 } 323 } 324 325 339 private final class ComboBoxEditorProxy 340 extends BasicComboBoxEditor 341 implements ComboBoxEditor { 342 private final ComboBoxEditor comboBoxEditor; 343 344 public ComboBoxEditorProxy(ComboBoxEditor comboBoxEditor) { 345 this.comboBoxEditor = comboBoxEditor; 346 } 347 348 public ComboBoxEditor getEditor() { 349 return comboBoxEditor; 350 } 351 352 public Component getEditorComponent() { 353 return comboBoxEditor.getEditorComponent(); 354 } 355 356 public void setItem(final Object item) { 357 updateEditor(comboBoxEditor, item); 358 } 359 360 public Object getItem() { 361 return comboBoxEditor.getItem(); 362 } 363 364 public void selectAll() { 365 comboBoxEditor.selectAll(); 366 } 367 368 public void addActionListener(ActionListener actionListener) { 369 comboBoxEditor.addActionListener(actionListener); 370 } 371 372 public void removeActionListener(ActionListener actionListener) { 373 comboBoxEditor.removeActionListener(actionListener); 374 } 375 } 376 } 377 | Popular Tags |