Source Code Cross Referenced for AutoCompletion.java in  » Swing-Library » jide-common » com » jidesoft » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jide common » com.jidesoft.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)AutoCompletion.java 6/22/2005
003:         *
004:         * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005:         */
006:        package com.jidesoft.swing;
007:
008:        import com.jidesoft.utils.SystemInfo;
009:
010:        import javax.swing.*;
011:        import javax.swing.event.ListSelectionEvent;
012:        import javax.swing.event.ListSelectionListener;
013:        import javax.swing.event.TreeSelectionEvent;
014:        import javax.swing.event.TreeSelectionListener;
015:        import javax.swing.text.*;
016:        import javax.swing.tree.TreePath;
017:        import java.awt.event.*;
018:        import java.beans.PropertyChangeEvent;
019:        import java.beans.PropertyChangeListener;
020:        import java.util.List;
021:
022:        /**
023:         * <code>AutoCompletion</code> is a helper class to make JTextComponent or JComboBox auto-complete based
024:         * on a list of known items.
025:         * <p/>
026:         * There are three constructors. The simplest one is {@link #AutoCompletion(javax.swing.JComboBox)}.
027:         * It takes any combobox and make it auto completion. If you are looking for an auto-complete combobox solution,
028:         * this is all you need. However <code>AutoCompletion</code> can do more than that. There are two more constrcutors.
029:         * One is {@link #AutoCompletion(javax.swing.text.JTextComponent,Searchable)}.
030:         * It will use {@link Searchable} which is another component available in JIDE to
031:         * make the JTextCompoent auto-complete. We used Searchable here because it provides
032:         * a common interface to access the element in JTree, JList or JTable. In
033:         * the other word, the known list item we used to auto-complete can be got
034:         * from JTree or JList or even JTable or any other component as
035:         * long as it has Searchable interface implemented.
036:         * The last constrcutor takes any java.util.List and use it as auto completion list.
037:         * <p/>
038:         * The only option available on <code>AutoCompletion</code> is {@link #setStrict(boolean)}. If it's true, it will not allow
039:         * user to type in anything that is not in the known item list. If false, user can type in whatever he/she wants. If the text
040:         * can match with a item in the known item list, it will still auto-complete.
041:         * <p/>
042:         *
043:         * @author Thomas Bierhance
044:         * @author JIDE Software, Inc.
045:         */
046:        public class AutoCompletion {
047:
048:            private Searchable _searchable;
049:            private JTextComponent _textComponent;
050:
051:            private AutoCompletionDocument _document;
052:
053:            // flag to indicate if setSelectedItem has been called
054:            // subsequent calls to remove/insertString should be ignored
055:            private boolean _selecting = false;
056:
057:            private boolean _hidePopupOnFocusLoss;
058:            private boolean _hitBackspace = false;
059:            private boolean _hitBackspaceOnSelection;
060:
061:            private KeyListener _editorKeyListener;
062:            private FocusListener _editorFocusListener;
063:
064:            private boolean _strict = true;
065:            private boolean _strictCompletion = true;
066:            private PropertyChangeListener _propertyChangeListener;
067:            private JComboBox _comboBox;
068:            private Document _oldDocument;
069:
070:            public AutoCompletion(final JComboBox comboBox) {
071:                this (comboBox, new ComboBoxSearchable(comboBox));
072:            }
073:
074:            public AutoCompletion(final JComboBox comboBox,
075:                    Searchable searchable) {
076:                _searchable = searchable;
077:                _propertyChangeListener = new PropertyChangeListener() {
078:                    public void propertyChange(PropertyChangeEvent e) {
079:                        if ("editor".equals(e.getPropertyName())) {
080:                            if (e.getNewValue() != null) {
081:                                _textComponent = (JTextComponent) ((ComboBoxEditor) e
082:                                        .getNewValue()).getEditorComponent();
083:                                configureEditor(getTextComponent());
084:                            }
085:                        }
086:                    }
087:                };
088:                _comboBox = comboBox;
089:                _searchable.setWildcardEnabled(false);
090:                if (_searchable instanceof  ComboBoxSearchable) {
091:                    ((ComboBoxSearchable) _searchable)
092:                            .setShowPopupDuringSearching(false);
093:                }
094:                _textComponent = (JTextComponent) comboBox.getEditor()
095:                        .getEditorComponent();
096:                installListeners();
097:                setInitValue();
098:            }
099:
100:            public AutoCompletion(final JTextComponent textComponent,
101:                    final Searchable searchable) {
102:                _searchable = searchable;
103:                _searchable.setWildcardEnabled(false);
104:                _textComponent = textComponent;
105:                registerSelectionListener(getSearchable());
106:
107:                installListeners();
108:                setInitValue();
109:            }
110:
111:            public AutoCompletion(final JTextComponent textComponent,
112:                    final List list) {
113:                this (textComponent, new Searchable(new JLabel()) {
114:                    int _selectIndex = -1;
115:
116:                    @Override
117:                    protected int getSelectedIndex() {
118:                        return _selectIndex;
119:                    }
120:
121:                    @Override
122:                    protected void setSelectedIndex(int index,
123:                            boolean incremental) {
124:                        _selectIndex = index;
125:                    }
126:
127:                    @Override
128:                    protected int getElementCount() {
129:                        return list.size();
130:                    }
131:
132:                    @Override
133:                    protected Object getElementAt(int index) {
134:                        return list.get(index);
135:                    }
136:
137:                    @Override
138:                    protected String convertElementToString(Object element) {
139:                        return "" + element;
140:                    }
141:                });
142:            }
143:
144:            public AutoCompletion(final JTextComponent textComponent,
145:                    final Object[] array) {
146:                this (textComponent, new Searchable(new JLabel()) {
147:                    int _selectIndex = -1;
148:
149:                    @Override
150:                    protected int getSelectedIndex() {
151:                        return _selectIndex;
152:                    }
153:
154:                    @Override
155:                    protected void setSelectedIndex(int index,
156:                            boolean incremental) {
157:                        _selectIndex = index;
158:                    }
159:
160:                    @Override
161:                    protected int getElementCount() {
162:                        return array.length;
163:                    }
164:
165:                    @Override
166:                    protected Object getElementAt(int index) {
167:                        return array[index];
168:                    }
169:
170:                    @Override
171:                    protected String convertElementToString(Object element) {
172:                        return "" + element;
173:                    }
174:                });
175:            }
176:
177:            private void registerSelectionListener(Searchable searchable) {
178:                if (searchable.getComponent() instanceof  JList) {
179:                    final JList list = (JList) getSearchable().getComponent();
180:                    list.getSelectionModel().addListSelectionListener(
181:                            new ListSelectionListener() {
182:                                public void valueChanged(ListSelectionEvent e) {
183:                                    int index = list.getSelectedIndex();
184:                                    if (index != -1) {
185:                                        getTextComponent().setText(
186:                                                ""
187:                                                        + list.getModel()
188:                                                                .getElementAt(
189:                                                                        index));
190:                                        highlightCompletedText(0);
191:                                    }
192:                                }
193:                            });
194:                    DelegateAction.replaceAction(getTextComponent(),
195:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
196:                            list, JComponent.WHEN_FOCUSED, KeyStroke
197:                                    .getKeyStroke(KeyEvent.VK_UP, 0));
198:                    DelegateAction.replaceAction(getTextComponent(),
199:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
200:                            list, JComponent.WHEN_FOCUSED, KeyStroke
201:                                    .getKeyStroke(KeyEvent.VK_DOWN, 0));
202:                    DelegateAction.replaceAction(getTextComponent(),
203:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
204:                            list, JComponent.WHEN_FOCUSED, KeyStroke
205:                                    .getKeyStroke(KeyEvent.VK_PAGE_UP, 0));
206:                    DelegateAction.replaceAction(getTextComponent(),
207:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
208:                            list, JComponent.WHEN_FOCUSED, KeyStroke
209:                                    .getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0));
210:                } else if (searchable.getComponent() instanceof  JTree) {
211:                    final JTree tree = (JTree) getSearchable().getComponent();
212:                    tree.getSelectionModel().addTreeSelectionListener(
213:                            new TreeSelectionListener() {
214:                                public void valueChanged(TreeSelectionEvent e) {
215:                                    TreePath treePath = tree.getSelectionPath();
216:                                    if (treePath != null) {
217:                                        getTextComponent()
218:                                                .setText(
219:                                                        ""
220:                                                                + treePath
221:                                                                        .getLastPathComponent());
222:                                        highlightCompletedText(0);
223:                                    }
224:                                }
225:                            });
226:                    DelegateAction.replaceAction(getTextComponent(),
227:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
228:                            tree, JComponent.WHEN_FOCUSED, KeyStroke
229:                                    .getKeyStroke(KeyEvent.VK_UP, 0));
230:                    DelegateAction.replaceAction(getTextComponent(),
231:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
232:                            tree, JComponent.WHEN_FOCUSED, KeyStroke
233:                                    .getKeyStroke(KeyEvent.VK_DOWN, 0));
234:                    DelegateAction.replaceAction(getTextComponent(),
235:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
236:                            tree, JComponent.WHEN_FOCUSED, KeyStroke
237:                                    .getKeyStroke(KeyEvent.VK_PAGE_UP, 0));
238:                    DelegateAction.replaceAction(getTextComponent(),
239:                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
240:                            tree, JComponent.WHEN_FOCUSED, KeyStroke
241:                                    .getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0));
242:                }
243:            }
244:
245:            private void setInitValue() {
246:                int index = getSearchable().getSelectedIndex();
247:                if (index != -1) {
248:                    Object selected = getSearchable().getElementAt(index);
249:                    if (selected != null)
250:                        _document.setText(getSearchable()
251:                                .convertElementToString(selected));
252:                    highlightCompletedText(0);
253:                } else {
254:                    _document.setText("");
255:                }
256:            }
257:
258:            /**
259:             * Uninstalls the listeners so that the component is not auto-completion anymore.
260:             */
261:            public void uninstallListeners() {
262:                if (_propertyChangeListener != null && _comboBox != null) {
263:                    _comboBox
264:                            .removePropertyChangeListener(_propertyChangeListener);
265:                }
266:
267:                if (getTextComponent() != null) {
268:                    getTextComponent().removeKeyListener(_editorKeyListener);
269:                    getTextComponent()
270:                            .removeFocusListener(_editorFocusListener);
271:                    String text = getTextComponent().getText();
272:                    if (_oldDocument != null) {
273:                        getTextComponent().setDocument(_oldDocument);
274:                        _oldDocument = null;
275:                    }
276:                    getTextComponent().setText(text);
277:                }
278:            }
279:
280:            /**
281:             * Installs the listeners needed for auto-completion feature.
282:             * Please note, this method is already called when you create AutoCompletion.
283:             * Unless you called {@link #uninstallListeners()}, there is no need to call this method yourself.
284:             */
285:            public void installListeners() {
286:                if (_comboBox != null && _propertyChangeListener != null) {
287:                    _comboBox
288:                            .addPropertyChangeListener(_propertyChangeListener);
289:                }
290:
291:                _editorKeyListener = new KeyAdapter() {
292:                    private boolean _deletePressed;
293:                    private String _saveText;
294:
295:                    @Override
296:                    public void keyPressed(KeyEvent e) {
297:                        _hitBackspace = false;
298:                        switch (e.getKeyCode()) {
299:                        // determine if the pressed key is backspace (needed by the remove method)
300:                        case KeyEvent.VK_BACK_SPACE:
301:                            if (isStrict()) {
302:                                _hitBackspace = true;
303:                                _hitBackspaceOnSelection = getTextComponent()
304:                                        .getSelectionStart() != getTextComponent()
305:                                        .getSelectionEnd();
306:                            }
307:                            break;
308:                        // ignore delete key
309:                        case KeyEvent.VK_DELETE:
310:                            if (isStrict()) {
311:                                _deletePressed = true;
312:                                _saveText = getTextComponent().getText();
313:                            }
314:                            break;
315:                        }
316:                    }
317:
318:                    @Override
319:                    public void keyReleased(KeyEvent e) {
320:                        super .keyReleased(e);
321:
322:                        if (_deletePressed) {
323:                            _deletePressed = false;
324:                            String text = getTextComponent().getText();
325:                            int index = getSearchable().findFirst(text);
326:                            if (index != -1) {
327:                                Object item = getSearchable().getElementAt(
328:                                        index);
329:                                setSelectedItem(item);
330:                                getTextComponent().setText(
331:                                        getSearchable().convertElementToString(
332:                                                item)); // this is what auto complete is
333:                                // select the completed part
334:                                highlightCompletedText(text.length());
335:                            } else { // didn't find a matching one
336:                                if (isStrict()) {
337:                                    getTextComponent().setText(_saveText);
338:                                    e.consume();
339:                                    UIManager.getLookAndFeel()
340:                                            .provideErrorFeedback(
341:                                                    _textComponent);
342:                                }
343:                            }
344:                        }
345:                    }
346:                };
347:                // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
348:                _hidePopupOnFocusLoss = SystemInfo.isJdk15Above();
349:                // Highlight whole text when gaining focus
350:                _editorFocusListener = new FocusAdapter() {
351:                    @Override
352:                    public void focusGained(FocusEvent e) {
353:                        highlightCompletedText(0);
354:                    }
355:
356:                    @Override
357:                    public void focusLost(FocusEvent e) {
358:                        // Workaround for Bug 5100422 - Hide Popup on focus loss
359:                        //                if (_hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
360:                    }
361:                };
362:
363:                _document = createDocument();
364:                configureEditor(getTextComponent());
365:            }
366:
367:            /**
368:             * Creates AutoCompletionDocument.
369:             *
370:             * @return the AutoCompletionDocument.
371:             */
372:            protected AutoCompletionDocument createDocument() {
373:                return new AutoCompletionDocument();
374:            }
375:
376:            private void configureEditor(JTextComponent textComponent) {
377:                if (getTextComponent() != null) {
378:                    getTextComponent().removeKeyListener(_editorKeyListener);
379:                    getTextComponent()
380:                            .removeFocusListener(_editorFocusListener);
381:                }
382:
383:                if (textComponent != null) {
384:                    _textComponent = textComponent;
385:                    getTextComponent().addKeyListener(_editorKeyListener);
386:                    getTextComponent().addFocusListener(_editorFocusListener);
387:                    String text = getTextComponent().getText();
388:                    _oldDocument = getTextComponent().getDocument();
389:                    getTextComponent().setDocument(_document);
390:                    getTextComponent().setText(text);
391:                }
392:            }
393:
394:            /**
395:             * The document class used by <tt>AutoCompletion</tt>.
396:             */
397:            protected class AutoCompletionDocument extends PlainDocument {
398:                @Override
399:                public void remove(int offs, int len)
400:                        throws BadLocationException {
401:                    // return immediately when _selecting an item
402:                    if (_selecting)
403:                        return;
404:                    if (_hitBackspace) {
405:                        // user hit backspace => move the selection backwards
406:                        // old item keeps being selected
407:                        if (offs > 0) {
408:                            if (_hitBackspaceOnSelection)
409:                                offs--;
410:                        } else {
411:                            // User hit backspace with the cursor positioned on the start => beep
412:                            UIManager.getLookAndFeel().provideErrorFeedback(
413:                                    _textComponent);
414:                        }
415:                        highlightCompletedText(offs);
416:                    } else {
417:                        super .remove(offs, len);
418:                    }
419:                }
420:
421:                @Override
422:                public void insertString(int offs, String str, AttributeSet a)
423:                        throws BadLocationException {
424:                    // return immediately when _selecting an item
425:                    if (_selecting)
426:                        return;
427:                    // insert the string into the document
428:                    super .insertString(offs, str, a);
429:                    // lookup and select a matching item
430:                    final String text = getText(0, getLength());
431:                    int index = getSearchable().findFromCursor(text);
432:                    Object item = null;
433:                    if (index != -1) {
434:                        item = getSearchable().getElementAt(index);
435:                        setSelectedItem(item);
436:                        setText(getSearchable().convertElementToString(item)); // this is what auto complete is
437:                        // select the completed part
438:                        highlightCompletedText(offs + str.length());
439:                    } else { // didn't find a matching one
440:                        if (isStrict()) {
441:                            index = getSearchable().getSelectedIndex();
442:                            if (index == -1) {
443:                                if (getSearchable().getElementCount() > 0) {
444:                                    index = 0;
445:                                    getSearchable().setSelectedIndex(0, false);
446:                                }
447:                            }
448:
449:                            if (index != -1) {
450:                                item = getSearchable().getElementAt(index);
451:                                offs = offs - str.length();
452:                                // imitate no insert (later on offs will be incremented by str.length(): selection won't move forward)
453:                                UIManager.getLookAndFeel()
454:                                        .provideErrorFeedback(_textComponent);
455:                                setText(getSearchable().convertElementToString(
456:                                        item));
457:                                // select the completed part
458:                                highlightCompletedText(offs + str.length());
459:                            }
460:                        }
461:                    }
462:                }
463:
464:                protected void setText(String text) {
465:                    try {
466:                        // remove all text and insert the completed string
467:                        if (isStrictCompletion()) {
468:                            super .remove(0, getLength());
469:                            super .insertString(0, text, null);
470:                        } else {
471:                            String existingText = super .getText(0, getLength());
472:                            int matchIndex = existingText.length();
473:                            // try to find a match
474:                            for (int i = 0; i < existingText.length(); i++) {
475:                                if (!existingText.substring(0, matchIndex)
476:                                        .equalsIgnoreCase(
477:                                                text.substring(0, matchIndex))) {
478:                                    matchIndex--;
479:                                }
480:                            }
481:                            // remove the no-match part and complete with the one in Searchable
482:                            super .remove(matchIndex, getLength() - matchIndex);
483:                            super .insertString(matchIndex, text
484:                                    .substring(matchIndex), null);
485:                        }
486:                    } catch (BadLocationException e) {
487:                        throw new RuntimeException(e.toString());
488:                    }
489:                }
490:            }
491:
492:            private void highlightCompletedText(int start) {
493:                getTextComponent().setCaretPosition(
494:                        getTextComponent().getDocument().getLength());
495:                getTextComponent().moveCaretPosition(start);
496:            }
497:
498:            private void setSelectedItem(Object item) {
499:                _selecting = true;
500:                for (int i = 0, n = getSearchable().getElementCount(); i < n; i++) {
501:                    Object currentItem = getSearchable().getElementAt(i);
502:                    // current item starts with the pattern?
503:                    if (item == currentItem) {
504:                        getSearchable().setSelectedIndex(i, false);
505:                    }
506:                }
507:                _selecting = false;
508:            }
509:
510:            /**
511:             * Gets the strict property.
512:             *
513:             * @return the value of strict property.
514:             */
515:            public boolean isStrict() {
516:                return _strict;
517:            }
518:
519:            /**
520:             * Sets the strict property. If true, it will not allow user to type in anything
521:             * that is not in the known item list. If false, user can type in whatever he/she wants. If the text
522:             * can match with a item in the known item list, it will still auto-complete.
523:             *
524:             * @param strict
525:             */
526:            public void setStrict(boolean strict) {
527:                _strict = strict;
528:            }
529:
530:            /**
531:             * Gets the strict completion property.
532:             *
533:             * @return the value of strict completion property.
534:             * @see #setStrictCompletion(boolean)
535:             */
536:            public boolean isStrictCompletion() {
537:                return _strictCompletion;
538:            }
539:
540:            /**
541:             * Sets the strict completion property. If true, in case insensitive searching,
542:             * it will always use the exact item in the Searchable to replace whatever user types. For example,
543:             * when Searchable has an item "Arial" and user types in "AR", if this flag is true, it will autocompleted
544:             * as "Arial". If false, it will be autocompleted as "ARial". Of course, this flag will only
545:             * make a difference if Searchable is case insensitive.
546:             *
547:             * @param strictCompletion
548:             */
549:            public void setStrictCompletion(boolean strictCompletion) {
550:                _strictCompletion = strictCompletion;
551:            }
552:
553:            /**
554:             * Gets the underlying text component which auto-completes.
555:             *
556:             * @return the underlying text component.
557:             */
558:            protected JTextComponent getTextComponent() {
559:                return _textComponent;
560:            }
561:
562:            /**
563:             * Gets the underlying Searchable. If you use the constructor {@link #AutoCompletion(javax.swing.text.JTextComponent,Searchable)}, the return value
564:             * will be the Searcable you passed in. If you use the other two constrcutors, internally we will
565:             * still create a Searchable. If so, this Searchable will be returned.
566:             *
567:             * @return the Searchable.
568:             */
569:            public Searchable getSearchable() {
570:                return _searchable;
571:            }
572:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.