* AutoCompletion.java: correct indentation
This commit is contained in:
parent
595f062839
commit
80ab81b48c
|
@ -6,193 +6,193 @@ import javax.swing.*;
|
||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
|
|
||||||
|
|
||||||
// phib: this is from http://www.orbital-computer.de/JComboBox
|
//phib: this is from http://www.orbital-computer.de/JComboBox
|
||||||
// with some minor revisions for Adempiere
|
//with some minor revisions for Adempiere
|
||||||
|
|
||||||
/* This work is hereby released into the Public Domain.
|
/* This work is hereby released into the Public Domain.
|
||||||
* To view a copy of the public domain dedication, visit
|
* To view a copy of the public domain dedication, visit
|
||||||
* http://creativecommons.org/licenses/publicdomain/
|
* http://creativecommons.org/licenses/publicdomain/
|
||||||
*/
|
*/
|
||||||
public class AutoCompletion extends PlainDocument {
|
public class AutoCompletion extends PlainDocument {
|
||||||
VComboBox comboBox;
|
VComboBox comboBox;
|
||||||
ComboBoxModel model;
|
ComboBoxModel model;
|
||||||
JTextComponent editor;
|
JTextComponent editor;
|
||||||
// flag to indicate if setSelectedItem has been called
|
// flag to indicate if setSelectedItem has been called
|
||||||
// subsequent calls to remove/insertString should be ignored
|
// subsequent calls to remove/insertString should be ignored
|
||||||
boolean selecting=false;
|
boolean selecting=false;
|
||||||
boolean hidePopupOnFocusLoss;
|
boolean hidePopupOnFocusLoss;
|
||||||
boolean hitBackspace=false;
|
boolean hitBackspace=false;
|
||||||
boolean hitBackspaceOnSelection;
|
boolean hitBackspaceOnSelection;
|
||||||
|
|
||||||
KeyListener editorKeyListener;
|
KeyListener editorKeyListener;
|
||||||
FocusListener editorFocusListener;
|
FocusListener editorFocusListener;
|
||||||
|
|
||||||
public AutoCompletion(final VComboBox comboBox) {
|
public AutoCompletion(final VComboBox comboBox) {
|
||||||
this.comboBox = comboBox;
|
this.comboBox = comboBox;
|
||||||
model = comboBox.getModel();
|
model = comboBox.getModel();
|
||||||
comboBox.addActionListener(new ActionListener() {
|
comboBox.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (!selecting) highlightCompletedText(0);
|
if (!selecting) highlightCompletedText(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
comboBox.addPropertyChangeListener(new PropertyChangeListener() {
|
comboBox.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
public void propertyChange(PropertyChangeEvent e) {
|
public void propertyChange(PropertyChangeEvent e) {
|
||||||
if (e.getPropertyName().equals("editor")) configureEditor((ComboBoxEditor) e.getNewValue());
|
if (e.getPropertyName().equals("editor")) configureEditor((ComboBoxEditor) e.getNewValue());
|
||||||
if (e.getPropertyName().equals("model")) model = (ComboBoxModel) e.getNewValue();
|
if (e.getPropertyName().equals("model")) model = (ComboBoxModel) e.getNewValue();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
editorKeyListener = new KeyAdapter() {
|
editorKeyListener = new KeyAdapter() {
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
// Ignore keys that do not alter the text - teo_sarca [ 1735043 ]
|
// Ignore keys that do not alter the text - teo_sarca [ 1735043 ]
|
||||||
if (e.getKeyChar() == KeyEvent.CHAR_UNDEFINED) {
|
if (e.getKeyChar() == KeyEvent.CHAR_UNDEFINED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
|
if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
|
||||||
hitBackspace=false;
|
hitBackspace=false;
|
||||||
switch (e.getKeyCode()) {
|
switch (e.getKeyCode()) {
|
||||||
// determine if the pressed key is backspace (needed by the remove method)
|
// determine if the pressed key is backspace (needed by the remove method)
|
||||||
case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
|
case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
|
||||||
hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
|
hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
|
||||||
break;
|
break;
|
||||||
// ignore delete key
|
// ignore delete key
|
||||||
case KeyEvent.VK_DELETE : e.consume();
|
case KeyEvent.VK_DELETE : e.consume();
|
||||||
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
|
// Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
|
||||||
hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
|
hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
|
||||||
// Highlight whole text when gaining focus
|
// Highlight whole text when gaining focus
|
||||||
editorFocusListener = new FocusAdapter() {
|
editorFocusListener = new FocusAdapter() {
|
||||||
public void focusGained(FocusEvent e) {
|
public void focusGained(FocusEvent e) {
|
||||||
highlightCompletedText(0);
|
highlightCompletedText(0);
|
||||||
}
|
}
|
||||||
public void focusLost(FocusEvent e) {
|
public void focusLost(FocusEvent e) {
|
||||||
// Workaround for Bug 5100422 - Hide Popup on focus loss
|
// Workaround for Bug 5100422 - Hide Popup on focus loss
|
||||||
if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
|
if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
configureEditor(comboBox.getEditor());
|
configureEditor(comboBox.getEditor());
|
||||||
// Handle initially selected object
|
// Handle initially selected object
|
||||||
Object selected = comboBox.getSelectedItem();
|
Object selected = comboBox.getSelectedItem();
|
||||||
if (selected!=null) setText(selected.toString());
|
if (selected!=null) setText(selected.toString());
|
||||||
highlightCompletedText(0);
|
highlightCompletedText(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enable(VComboBox comboBox) {
|
public static void enable(VComboBox comboBox) {
|
||||||
// has to be editable
|
// has to be editable
|
||||||
comboBox.setEditable(true);
|
comboBox.setEditable(true);
|
||||||
// change the editor's document
|
// change the editor's document
|
||||||
new AutoCompletion(comboBox);
|
new AutoCompletion(comboBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void configureEditor(ComboBoxEditor newEditor) {
|
void configureEditor(ComboBoxEditor newEditor) {
|
||||||
if (editor != null) {
|
if (editor != null) {
|
||||||
editor.removeKeyListener(editorKeyListener);
|
editor.removeKeyListener(editorKeyListener);
|
||||||
editor.removeFocusListener(editorFocusListener);
|
editor.removeFocusListener(editorFocusListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newEditor != null) {
|
if (newEditor != null) {
|
||||||
editor = (JTextComponent) newEditor.getEditorComponent();
|
editor = (JTextComponent) newEditor.getEditorComponent();
|
||||||
editor.addKeyListener(editorKeyListener);
|
editor.addKeyListener(editorKeyListener);
|
||||||
editor.addFocusListener(editorFocusListener);
|
editor.addFocusListener(editorFocusListener);
|
||||||
editor.setDocument(this);
|
editor.setDocument(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(int offs, int len) throws BadLocationException {
|
public void remove(int offs, int len) throws BadLocationException {
|
||||||
// return immediately when selecting an item
|
// return immediately when selecting an item
|
||||||
if (selecting) return;
|
if (selecting) return;
|
||||||
if (hitBackspace) {
|
if (hitBackspace) {
|
||||||
// user hit backspace => move the selection backwards
|
// user hit backspace => move the selection backwards
|
||||||
// old item keeps being selected
|
// old item keeps being selected
|
||||||
if (offs>0) {
|
if (offs>0) {
|
||||||
if (hitBackspaceOnSelection) offs--;
|
if (hitBackspaceOnSelection) offs--;
|
||||||
} else {
|
} else {
|
||||||
// User hit backspace with the cursor positioned on the start => beep
|
// User hit backspace with the cursor positioned on the start => beep
|
||||||
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
||||||
}
|
}
|
||||||
highlightCompletedText(offs);
|
highlightCompletedText(offs);
|
||||||
} else {
|
} else {
|
||||||
super.remove(offs, len);
|
super.remove(offs, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
|
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
|
||||||
|
|
||||||
if (selecting) return;
|
if (selecting) return;
|
||||||
|
|
||||||
super.insertString(offs, str, a);
|
super.insertString(offs, str, a);
|
||||||
|
|
||||||
// lookup and select a matching item
|
// lookup and select a matching item
|
||||||
Object item = lookupItem(getText(0, getLength()));
|
Object item = lookupItem(getText(0, getLength()));
|
||||||
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
setSelectedItem(item);
|
setSelectedItem(item);
|
||||||
} else {
|
} else {
|
||||||
if ( offs == 0 )
|
if ( offs == 0 )
|
||||||
setSelectedItem(null); //null is valid for non-mandatory fields
|
setSelectedItem(null); //null is valid for non-mandatory fields
|
||||||
//so if cursor is at start of line allow it
|
//so if cursor is at start of line allow it
|
||||||
// otherwise keep old item selected if there is no better match
|
// otherwise keep old item selected if there is no better match
|
||||||
else
|
else
|
||||||
item = comboBox.getSelectedItem();
|
item = comboBox.getSelectedItem();
|
||||||
// undo the insertion as there isn't a valid match
|
// undo the insertion as there isn't a valid match
|
||||||
offs = offs-str.length();
|
offs = offs-str.length();
|
||||||
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
setText(item.toString());
|
setText(item.toString());
|
||||||
else setText("");
|
else setText("");
|
||||||
// select the completed part so it can be overwritten easily
|
// select the completed part so it can be overwritten easily
|
||||||
highlightCompletedText(offs+str.length());
|
highlightCompletedText(offs+str.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setText(String text) {
|
private void setText(String text) {
|
||||||
try {
|
try {
|
||||||
// remove all text and insert the completed string
|
// remove all text and insert the completed string
|
||||||
super.remove(0, getLength());
|
super.remove(0, getLength());
|
||||||
super.insertString(0, text, null);
|
super.insertString(0, text, null);
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
throw new RuntimeException(e.toString());
|
throw new RuntimeException(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void highlightCompletedText(int start) {
|
private void highlightCompletedText(int start) {
|
||||||
editor.setCaretPosition(getLength());
|
editor.setCaretPosition(getLength());
|
||||||
editor.moveCaretPosition(start);
|
editor.moveCaretPosition(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSelectedItem(Object item) {
|
private void setSelectedItem(Object item) {
|
||||||
selecting = true;
|
selecting = true;
|
||||||
model.setSelectedItem(item);
|
model.setSelectedItem(item);
|
||||||
selecting = false;
|
selecting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object lookupItem(String pattern) {
|
private Object lookupItem(String pattern) {
|
||||||
Object selectedItem = model.getSelectedItem();
|
Object selectedItem = model.getSelectedItem();
|
||||||
// only search for a different item if the currently selected does not match
|
// only search for a different item if the currently selected does not match
|
||||||
if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
|
if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
|
||||||
return selectedItem;
|
return selectedItem;
|
||||||
} else {
|
} else {
|
||||||
// iterate over all items
|
// iterate over all items
|
||||||
for (int i=0, n=model.getSize(); i < n; i++) {
|
for (int i=0, n=model.getSize(); i < n; i++) {
|
||||||
Object currentItem = model.getElementAt(i);
|
Object currentItem = model.getElementAt(i);
|
||||||
// current item starts with the pattern?
|
// current item starts with the pattern?
|
||||||
if (currentItem != null && startsWithIgnoreCase(currentItem.toString(), pattern)) {
|
if (currentItem != null && startsWithIgnoreCase(currentItem.toString(), pattern)) {
|
||||||
return currentItem;
|
return currentItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if str1 starts with str2 - ignores case
|
// checks if str1 starts with str2 - ignores case
|
||||||
private boolean startsWithIgnoreCase(String str1, String str2) {
|
private boolean startsWithIgnoreCase(String str1, String str2) {
|
||||||
return str1.toUpperCase().startsWith(str2.toUpperCase());
|
return str1.toUpperCase().startsWith(str2.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue