00001
00002
00003
00004
00005 package edu.stanford.hci.r3.util.components;
00006
00007 import java.awt.BorderLayout;
00008 import java.awt.Color;
00009 import java.awt.Font;
00010 import java.awt.event.FocusEvent;
00011 import java.awt.event.FocusListener;
00012 import java.awt.event.KeyAdapter;
00013 import java.awt.event.KeyEvent;
00014 import java.text.NumberFormat;
00015 import java.text.ParseException;
00016 import java.util.LinkedList;
00017 import java.util.List;
00018
00019 import javax.swing.JButton;
00020 import javax.swing.JFrame;
00021 import javax.swing.JTextField;
00022 import javax.swing.text.*;
00023
00044 public class SuperJTextField extends JTextField {
00045
00051 private class SuperDocument extends PlainDocument {
00052
00053 private SuperJTextField parent;
00054
00058 public SuperDocument(SuperJTextField p) {
00059 parent = p;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068 public void insertString(int offs, String str, AttributeSet attributeSet)
00069 throws BadLocationException {
00070 super.insertString(offs, str, attributeSet);
00071
00072
00073
00074
00075
00076 final String myText = parent.getText().toLowerCase();
00077 String match = null;
00078
00079
00080
00081 try {
00082
00083
00084
00085 NumberFormat.getInstance().parse(myText);
00086
00087 return;
00088 } catch (ParseException e) {
00089
00090
00091 }
00092
00093
00094 String restOfText = null;
00095
00096
00097 for (final String testString : possibleCompletions) {
00098
00099 if (testString.toLowerCase().startsWith(myText)) {
00100
00101
00102
00103 match = testString;
00104 restOfText = match.substring(myText.length());
00105
00106
00107
00108
00109 super.insertString(offs + 1, restOfText, attributeSet);
00110 final Caret c = parent.getCaret();
00111 c.setDot(match.length());
00112 c.moveDot(offs + 1);
00113 autocompleteJustHappened = true;
00114 break;
00115 }
00116 }
00117 }
00118 }
00119
00123 public static void main(String[] args) {
00124 final JFrame f = new JFrame();
00125 SuperJTextField stf = new SuperJTextField("Hello");
00126 {
00127 stf.setFont(new Font("Verdana", Font.PLAIN, 11));
00128 stf.setInputHintFont(new Font("Verdana", Font.ITALIC, 11));
00129 stf.setInputHint("<Search>");
00130 }
00131 {
00132 stf.addPossibleCompletion("Bumpkin");
00133 stf.addPossibleCompletion("Pumpkin");
00134 stf.addPossibleCompletion("Word Up");
00135 stf.addPossibleCompletion("821.56");
00136 }
00137
00138 f.add(stf, BorderLayout.CENTER);
00139 f.add(new JButton("X"), BorderLayout.EAST);
00140 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00141 f.pack();
00142 f.setVisible(true);
00143 }
00144
00145 private boolean autocompleteJustHappened = false;
00146
00147 private boolean focusOnEdit;
00148
00149 private Color hintColor = Color.LIGHT_GRAY;
00150
00151 private String inputHint;
00152
00153 private Font inputHintFont;
00154
00155 protected boolean inputHintShowing;
00156
00157
00158 protected int lastKeyCode = -1;
00159
00160 private boolean lastKeyShiftDown;
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 private LinkedList<String> possibleCompletions = new LinkedList<String>();
00173
00174
00175 protected Color textColor = Color.BLACK;
00176
00177
00178 protected Font textFont;
00179
00183 public SuperJTextField() {
00184 setup();
00185 }
00186
00190 public SuperJTextField(int numCols) {
00191 super(numCols);
00192 setup();
00193 }
00194
00198 public SuperJTextField(String string) {
00199 super();
00200 setup();
00201 setText(string);
00202 }
00203
00208 public SuperJTextField(String defaultText, int numCols) {
00209 super(numCols);
00210 setup();
00211 setText(defaultText);
00212 }
00213
00222 public void addPossibleCompletion(String completion) {
00223 possibleCompletions.addFirst(completion);
00224 }
00225
00226
00227
00228
00229
00230
00231 protected Document createDefaultModel() {
00232 return new SuperDocument(this);
00233 }
00234
00241 public int getExitKey() {
00242 return lastKeyCode;
00243 }
00244
00248 public String getInputHint() {
00249 return inputHint;
00250 }
00251
00255 public boolean getLastKeyShiftDown() {
00256 return lastKeyShiftDown;
00257 }
00258
00259
00260
00261
00262
00263
00264 public String getText() {
00265 if (inputHintShowing) {
00266 return "";
00267 } else {
00268 return super.getText();
00269 }
00270 }
00271
00275 protected boolean noText() {
00276 return super.getText() == null || super.getText().equals("");
00277 }
00278
00282 public void removePossibleCompletion(String completion) {
00283 possibleCompletions.remove(completion);
00284 }
00285
00286 public void setFocusGainedOnEdit(boolean foe) {
00287 focusOnEdit = foe;
00288 }
00289
00295 public void setInputHint(String hint) {
00296 inputHint = hint;
00297 if (noText()) {
00298 setInputHintVisible(true);
00299 }
00300 }
00301
00305 private void setInputHintFont(Font font) {
00306 inputHintFont = font;
00307 }
00308
00312 private void setInputHintVisible(boolean toBeVisible) {
00313 if (toBeVisible) {
00314 if (inputHint != null && !inputHint.equals("")) {
00315 setForeground(hintColor);
00316 super.setText(inputHint);
00317 setFont(inputHintFont);
00318 inputHintShowing = true;
00319 }
00320 } else {
00321 if (inputHintShowing) {
00322 super.setText("");
00323 setForeground(textColor);
00324 setFont(textFont);
00325 inputHintShowing = false;
00326 }
00327 }
00328 }
00329
00333 public void setPossibleCompletions(final List<String> possible) {
00334 possibleCompletions.clear();
00335 for (final String entry : possible) {
00336 possibleCompletions.addFirst(entry);
00337 }
00338 }
00339
00340
00341
00342
00343
00344
00345 @Override
00346 public void setText(String t) {
00347 super.setText(t);
00348
00349 if (noText()) {
00350 setInputHintVisible(true);
00351 } else {
00352 setForeground(textColor);
00353 inputHintShowing = false;
00354 }
00355 }
00356
00360 private void setup() {
00361 textFont = getFont();
00362 inputHintFont = getFont();
00363
00364 addFocusListener(new FocusListener() {
00365
00366
00367
00368
00369 public void focusGained(FocusEvent arg0) {
00370 setForeground(textColor);
00371 setFont(textFont);
00372
00373 setInputHintVisible(false);
00374
00375 final int length = SuperJTextField.super.getText().length();
00376
00377
00378
00379
00380 if (!autocompleteJustHappened && !focusOnEdit) {
00381 select(0, length);
00382 }
00383
00384 autocompleteJustHappened = false;
00385 focusOnEdit = false;
00386 }
00387
00388
00389
00390 public void focusLost(FocusEvent arg0) {
00391
00392
00393 if (noText()) {
00394 setInputHintVisible(true);
00395 }
00396 autocompleteJustHappened = false;
00397 }
00398 });
00399
00400 addKeyListener(new KeyAdapter() {
00401
00402 public void keyPressed(KeyEvent ke) {
00403
00404
00405 lastKeyCode = ke.getKeyCode();
00406
00407
00408 lastKeyShiftDown = ke.isShiftDown();
00409 }
00410 });
00411 }
00412
00413 }