0
|
1 package com.glavsoft.viewer.swing.gui;
|
|
2
|
|
3 import javax.swing.*;
|
|
4 import javax.swing.text.AttributeSet;
|
|
5 import javax.swing.text.BadLocationException;
|
|
6 import javax.swing.text.JTextComponent;
|
|
7 import javax.swing.text.PlainDocument;
|
|
8 import java.awt.event.ActionEvent;
|
|
9 import java.awt.event.ActionListener;
|
|
10 import java.awt.event.FocusAdapter;
|
|
11 import java.awt.event.FocusEvent;
|
|
12
|
|
13 /**
|
|
14 * @author dime at tightvnc.com
|
|
15 *
|
|
16 * Using idea by Thomas Bierhance from http://www.orbital-computer.de/JComboBox/
|
|
17 */
|
|
18 public class AutoCompletionComboEditorDocument extends PlainDocument {
|
|
19
|
|
20 private ComboBoxModel model;
|
|
21 private boolean selecting;
|
|
22 private JComboBox comboBox;
|
|
23 private final boolean hidePopupOnFocusLoss;
|
|
24 private JTextComponent editor;
|
|
25
|
|
26 public AutoCompletionComboEditorDocument(final JComboBox comboBox) {
|
|
27 this.comboBox = comboBox;
|
|
28 this.model = comboBox.getModel();
|
|
29 this.editor = (JTextComponent)comboBox.getEditor().getEditorComponent();
|
|
30 editor.setDocument(this);
|
|
31 comboBox.addActionListener(new ActionListener() {
|
|
32 @Override
|
|
33 public void actionPerformed(ActionEvent e) {
|
|
34 if (!selecting) highlightCompletedText(0);
|
|
35 }
|
|
36 });
|
|
37
|
|
38 Object selectedItem = comboBox.getSelectedItem();
|
|
39 if (selectedItem!=null) {
|
|
40 setText(selectedItem.toString());
|
|
41 highlightCompletedText(0);
|
|
42 }
|
|
43 hidePopupOnFocusLoss = System.getProperty("java.version").startsWith("1.5");
|
|
44 editor.addFocusListener(new FocusAdapter() {
|
|
45 @Override
|
|
46 public void focusLost(FocusEvent e) {
|
|
47 if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
|
|
48 }
|
|
49 });
|
|
50 }
|
|
51
|
|
52 @Override
|
|
53 public void remove(int offs, int len) throws BadLocationException {
|
|
54 if (selecting) return;
|
|
55 super.remove(offs, len);
|
|
56 }
|
|
57
|
|
58 @Override
|
|
59 public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
|
|
60 if (selecting) return;
|
|
61 super.insertString(offs, str, a);
|
|
62 Object item = lookupItem(getText(0, getLength()));
|
|
63 if (item != null) {
|
|
64 setSelectedItem(item);
|
|
65 setText(item.toString());
|
|
66 highlightCompletedText(offs + str.length());
|
|
67 if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
|
|
68 }
|
|
69 }
|
|
70
|
|
71 private void setText(String text) {
|
|
72 try {
|
|
73 super.remove(0, getLength());
|
|
74 super.insertString(0, text, null);
|
|
75 } catch (BadLocationException e) {
|
|
76 throw new RuntimeException(e);
|
|
77 }
|
|
78 }
|
|
79
|
|
80 private void setSelectedItem(Object item) {
|
|
81 selecting = true;
|
|
82 model.setSelectedItem(item);
|
|
83 selecting = false;
|
|
84 }
|
|
85
|
|
86 private void highlightCompletedText(int offs) {
|
|
87 JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
|
|
88 editor.setSelectionStart(offs);
|
|
89 editor.setSelectionEnd(getLength());
|
|
90 }
|
|
91
|
|
92 private Object lookupItem(String pattern) {
|
|
93 Object selectedItem = model.getSelectedItem();
|
|
94 if (selectedItem != null && startsWithIgnoreCase(selectedItem, pattern)) {
|
|
95 return selectedItem;
|
|
96 } else {
|
|
97 for (int i = 0, n = model.getSize(); i < n; i++) {
|
|
98 Object currentItem = model.getElementAt(i);
|
|
99 if (startsWithIgnoreCase(currentItem, pattern)) {
|
|
100 return currentItem;
|
|
101 }
|
|
102 }
|
|
103 }
|
|
104 return null;
|
|
105 }
|
|
106
|
|
107 private boolean startsWithIgnoreCase(Object currentItem, String pattern) {
|
|
108 return currentItem.toString().toLowerCase().startsWith(pattern.toLowerCase());
|
|
109 }
|
|
110
|
|
111
|
|
112 }
|