source: josm/trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletingTextField.java@ 6084

Last change on this file since 6084 was 6084, checked in by bastiK, 11 years ago

see #8902 - add missing @Override annotations (patch by shinigami)

  • Property svn:eol-style set to native
File size: 8.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.tagging.ac;
3
4import java.awt.Component;
5import java.awt.event.FocusAdapter;
6import java.awt.event.FocusEvent;
7import java.awt.event.KeyAdapter;
8import java.awt.event.KeyEvent;
9import java.util.EventObject;
10
11import javax.swing.ComboBoxEditor;
12import javax.swing.JTable;
13import javax.swing.event.CellEditorListener;
14import javax.swing.table.TableCellEditor;
15import javax.swing.text.AttributeSet;
16import javax.swing.text.BadLocationException;
17import javax.swing.text.Document;
18import javax.swing.text.PlainDocument;
19import javax.swing.text.StyleConstants;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.gui.util.TableCellEditorSupport;
23import org.openstreetmap.josm.gui.widgets.JosmTextField;
24
25
26/**
27 * AutoCompletingTextField is an text field with autocompletion behaviour. It
28 * can be used as table cell editor in {@link JTable}s.
29 *
30 * Autocompletion is controlled by a list of {@link AutoCompletionListItem}s
31 * managed in a {@link AutoCompletionList}.
32 *
33 *
34 */
35public class AutoCompletingTextField extends JosmTextField implements ComboBoxEditor, TableCellEditor {
36
37 private Integer maxChars;
38
39 /**
40 * The document model for the editor
41 */
42 class AutoCompletionDocument extends PlainDocument {
43
44 /**
45 * inserts a string at a specific position
46 *
47 */
48 @Override
49 public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
50
51 // If a maximum number of characters is specified, avoid to exceed it
52 if (maxChars != null && str != null && getLength() + str.length() > maxChars) {
53 int allowedLength = maxChars-getLength();
54 if (allowedLength > 0) {
55 str = str.substring(0, allowedLength);
56 } else {
57 return;
58 }
59 }
60
61 if (autoCompletionList == null) {
62 super.insertString(offs, str, a);
63 return;
64 }
65
66 // input method for non-latin characters (e.g. scim)
67 if (a != null && a.isDefined(StyleConstants.ComposedTextAttribute)) {
68 super.insertString(offs, str, a);
69 return;
70 }
71
72 // if the current offset isn't at the end of the document we don't autocomplete.
73 // If a highlighted autocompleted suffix was present and we get here Swing has
74 // already removed it from the document. getLength() therefore doesn't include the
75 // autocompleted suffix.
76 //
77 if (offs < getLength()) {
78 super.insertString(offs, str, a);
79 return;
80 }
81
82 String currentText = getText(0, getLength());
83 // if the text starts with a number we don't autocomplete
84 if (Main.pref.getBoolean("autocomplete.dont_complete_numbers", true)) {
85 try {
86 Long.parseLong(str);
87 if (currentText.length() == 0) {
88 // we don't autocomplete on numbers
89 super.insertString(offs, str, a);
90 return;
91 }
92 Long.parseLong(currentText);
93 super.insertString(offs, str, a);
94 return;
95 } catch(NumberFormatException e) {
96 // either the new text or the current text isn't a number. We continue with
97 // autocompletion
98 }
99 }
100 String prefix = currentText.substring(0, offs);
101 autoCompletionList.applyFilter(prefix+str);
102 if (autoCompletionList.getFilteredSize()>0) {
103 // there are matches. Insert the new text and highlight the
104 // auto completed suffix
105 //
106 String matchingString = autoCompletionList.getFilteredItem(0).getValue();
107 remove(0,getLength());
108 super.insertString(0,matchingString,a);
109
110 // highlight from insert position to end position to put the caret at the end
111 setCaretPosition(offs + str.length());
112 moveCaretPosition(getLength());
113 } else {
114 // there are no matches. Insert the new text, do not highlight
115 //
116 String newText = prefix + str;
117 remove(0,getLength());
118 super.insertString(0,newText,a);
119 setCaretPosition(getLength());
120
121 }
122 }
123 }
124
125 /** the auto completion list user input is matched against */
126 protected AutoCompletionList autoCompletionList = null;
127
128 /**
129 * creates the default document model for this editor
130 *
131 */
132 @Override
133 protected Document createDefaultModel() {
134 return new AutoCompletionDocument();
135 }
136
137 protected void init() {
138 addFocusListener(
139 new FocusAdapter() {
140 @Override public void focusGained(FocusEvent e) {
141 selectAll();
142 applyFilter(getText());
143 }
144 }
145 );
146
147 addKeyListener(
148 new KeyAdapter() {
149
150 @Override
151 public void keyReleased(KeyEvent e) {
152 if (getText().equals("")) {
153 applyFilter("");
154 }
155 }
156 }
157 );
158 tableCellEditorSupport = new TableCellEditorSupport(this);
159 }
160
161 /**
162 * constructor
163 */
164 public AutoCompletingTextField() {
165 init();
166 }
167
168 public AutoCompletingTextField(int columns) {
169 super(columns);
170 init();
171 }
172
173 protected void applyFilter(String filter) {
174 if (autoCompletionList != null) {
175 autoCompletionList.applyFilter(filter);
176 }
177 }
178
179 /**
180 *
181 * @return the auto completion list; may be null, if no auto completion list is set
182 */
183 public AutoCompletionList getAutoCompletionList() {
184 return autoCompletionList;
185 }
186
187 /**
188 * sets the auto completion list
189 * @param autoCompletionList the auto completion list; if null, auto completion is
190 * disabled
191 */
192 public void setAutoCompletionList(AutoCompletionList autoCompletionList) {
193 this.autoCompletionList = autoCompletionList;
194 }
195
196 @Override
197 public Component getEditorComponent() {
198 return this;
199 }
200
201 @Override
202 public Object getItem() {
203 return getText();
204 }
205
206 @Override
207 public void setItem(Object anObject) {
208 if (anObject == null) {
209 setText("");
210 } else {
211 setText(anObject.toString());
212 }
213 }
214
215 /**
216 * Sets the maximum number of characters allowed.
217 * @param max maximum number of characters allowed
218 * @since 5579
219 */
220 public void setMaxChars(Integer max) {
221 maxChars = max;
222 }
223
224 /* ------------------------------------------------------------------------------------ */
225 /* TableCellEditor interface */
226 /* ------------------------------------------------------------------------------------ */
227
228 private TableCellEditorSupport tableCellEditorSupport;
229 private String originalValue;
230
231 @Override
232 public void addCellEditorListener(CellEditorListener l) {
233 tableCellEditorSupport.addCellEditorListener(l);
234 }
235
236 protected void rememberOriginalValue(String value) {
237 this.originalValue = value;
238 }
239
240 protected void restoreOriginalValue() {
241 setText(originalValue);
242 }
243
244 @Override
245 public void removeCellEditorListener(CellEditorListener l) {
246 tableCellEditorSupport.removeCellEditorListener(l);
247 }
248 @Override
249 public void cancelCellEditing() {
250 restoreOriginalValue();
251 tableCellEditorSupport.fireEditingCanceled();
252
253 }
254
255 @Override
256 public Object getCellEditorValue() {
257 return getText();
258 }
259
260 @Override
261 public boolean isCellEditable(EventObject anEvent) {
262 return true;
263 }
264
265 @Override
266 public boolean shouldSelectCell(EventObject anEvent) {
267 return true;
268 }
269
270 @Override
271 public boolean stopCellEditing() {
272 tableCellEditorSupport.fireEditingStopped();
273 return true;
274 }
275
276 @Override
277 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
278 setText( value == null ? "" : value.toString());
279 rememberOriginalValue(getText());
280 return this;
281 }
282}
Note: See TracBrowser for help on using the repository browser.