Source Code Cross Referenced for AbstractIntelliHints.java in  » Swing-Library » jide-common » com » jidesoft » hints » 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.hints 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)AbstractIntelliHints.java 7/24/2005
003:         *
004:         * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005:         */
006:        package com.jidesoft.hints;
007:
008:        import com.jidesoft.plaf.UIDefaultsLookup;
009:        import com.jidesoft.popup.JidePopup;
010:        import com.jidesoft.swing.DelegateAction;
011:
012:        import javax.swing.*;
013:        import javax.swing.event.DocumentEvent;
014:        import javax.swing.event.DocumentListener;
015:        import javax.swing.event.PopupMenuEvent;
016:        import javax.swing.event.PopupMenuListener;
017:        import javax.swing.text.BadLocationException;
018:        import javax.swing.text.JTextComponent;
019:        import java.awt.*;
020:        import java.awt.event.*;
021:
022:        /**
023:         * <code>AbstractIntelliHints</code> is an abstract implementation of {@link com.jidesoft.hints.IntelliHints}. It covers
024:         * functions such as showing the hint popup at the correct position, delegating keystrokes,
025:         * updating and selecting hint. The only thing that is left out to subclasses
026:         * is the creation of the hint popup.
027:         *
028:         * @author Santhosh Kumar T
029:         * @author JIDE Software, Inc.
030:         */
031:        public abstract class AbstractIntelliHints implements  IntelliHints {
032:
033:            /**
034:             * The key of a client property. If a component has intellihints registered, you can use this client
035:             * property to get the IntelliHints instance.
036:             */
037:            public static final String CLIENT_PROPERTY_INTELLI_HINTS = "INTELLI_HINTS"; //NOI18N
038:
039:            private JidePopup _popup;
040:            private JTextComponent _textComponent;
041:
042:            private boolean _followCaret = false;
043:
044:            // we use this flag to workaround the bug that setText() will trigger the hint popup.
045:            private boolean _keyTyped = false;
046:
047:            // Specifies whether the hints popup should be displayed automatically.
048:            // Default is true for backward compatibility.
049:            private boolean _autoPopup = true;
050:
051:            /**
052:             * Creates an IntelliHints object for a given JTextComponent.
053:             *
054:             * @param textComponent the text component.
055:             */
056:            public AbstractIntelliHints(JTextComponent textComponent) {
057:                _textComponent = textComponent;
058:                getTextComponent().putClientProperty(
059:                        CLIENT_PROPERTY_INTELLI_HINTS, this );
060:
061:                _popup = createPopup();
062:
063:                getTextComponent().getDocument().addDocumentListener(
064:                        documentListener);
065:                getTextComponent().addKeyListener(new KeyListener() {
066:                    public void keyTyped(KeyEvent e) {
067:                    }
068:
069:                    public void keyPressed(KeyEvent e) {
070:                    }
071:
072:                    public void keyReleased(KeyEvent e) {
073:                        if (KeyEvent.VK_ESCAPE != e.getKeyCode()) {
074:                            setKeyTyped(true);
075:                        }
076:                    }
077:                });
078:                getTextComponent().addFocusListener(new FocusListener() {
079:                    public void focusGained(FocusEvent e) {
080:                    }
081:
082:                    public void focusLost(FocusEvent e) {
083:                        Container topLevelAncestor = _popup
084:                                .getTopLevelAncestor();
085:                        if (topLevelAncestor == null) {
086:                            return;
087:                        }
088:                        Component oppositeComponent = e.getOppositeComponent();
089:                        if (topLevelAncestor == oppositeComponent
090:                                || topLevelAncestor
091:                                        .isAncestorOf(oppositeComponent)) {
092:                            return;
093:                        }
094:                        hideHintsPopup();
095:                    }
096:                });
097:
098:                DelegateAction.replaceAction(getTextComponent(),
099:                        JComponent.WHEN_FOCUSED, getShowHintsKeyStroke(),
100:                        showAction);
101:
102:                KeyStroke[] keyStrokes = getDelegateKeyStrokes();
103:                for (int i = 0; i < keyStrokes.length; i++) {
104:                    KeyStroke keyStroke = keyStrokes[i];
105:                    DelegateAction.replaceAction(getTextComponent(),
106:                            JComponent.WHEN_FOCUSED, keyStroke,
107:                            new LazyDelegateAction(keyStroke));
108:                }
109:
110:                getDelegateComponent().setRequestFocusEnabled(false);
111:                getDelegateComponent().addMouseListener(new MouseAdapter() {
112:                    @Override
113:                    public void mouseClicked(MouseEvent e) {
114:                        hideHintsPopup();
115:                        setHintsEnabled(false);
116:                        acceptHint(getSelectedHint());
117:                        setHintsEnabled(true);
118:                    }
119:                });
120:            }
121:
122:            protected JidePopup createPopup() {
123:                JidePopup popup = new JidePopup();
124:                popup.setLayout(new BorderLayout());
125:                popup.setResizable(true);
126:                popup.setPopupBorder(BorderFactory.createLineBorder(
127:                        UIDefaultsLookup.getColor("controlDkShadow"), 1));
128:                popup.setMovable(false);
129:                popup.add(createHintsComponent());
130:                popup.addPopupMenuListener(new PopupMenuListener() {
131:                    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
132:                    }
133:
134:                    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
135:                        DelegateAction.restoreAction(getTextComponent(),
136:                                JComponent.WHEN_FOCUSED, KeyStroke
137:                                        .getKeyStroke(KeyEvent.VK_ESCAPE, 0),
138:                                hideAction);
139:                        DelegateAction.restoreAction(getTextComponent(),
140:                                JComponent.WHEN_FOCUSED, KeyStroke
141:                                        .getKeyStroke(KeyEvent.VK_ENTER, 0),
142:                                acceptAction);
143:                    }
144:
145:                    public void popupMenuCanceled(PopupMenuEvent e) {
146:                    }
147:                });
148:                popup.setTransient(true);
149:                return popup;
150:            }
151:
152:            public JTextComponent getTextComponent() {
153:                return _textComponent;
154:            }
155:
156:            /**
157:             * After user has selected a item in the hints popup, this method will update JTextComponent accordingly
158:             * to accept the hint.
159:             * <p/>
160:             * For JTextArea, the default implementation will insert the hint into current caret position.
161:             * For JTextField, by default it will replace the whole content with the item user selected. Subclass can
162:             * always choose to override it to accept the hint in a different way. For example, {@link com.jidesoft.hints.FileIntelliHints}
163:             * will append the selected item at the end of the existing text in order to complete a full file path.
164:             */
165:            public void acceptHint(Object selected) {
166:                if (selected == null)
167:                    return;
168:
169:                if (getTextComponent() instanceof  JTextArea) {
170:                    int pos = getTextComponent().getCaretPosition();
171:                    String text = getTextComponent().getText();
172:                    int start = text.lastIndexOf("\n", pos - 1);
173:                    String remain = pos == -1 ? "" : text.substring(pos);
174:                    text = text.substring(0, start + 1);
175:                    text += selected;
176:                    pos = text.length();
177:                    text += remain;
178:                    getTextComponent().setText(text);
179:                    getTextComponent().setCaretPosition(pos);
180:                } else {
181:                    String hint = "" + selected;
182:                    getTextComponent().setText(hint);
183:                    getTextComponent().setCaretPosition(hint.length());
184:                }
185:            }
186:
187:            /**
188:             * Shows the hints popup which contains the hints.
189:             * It will call {@link #updateHints(Object)}. Only if it returns true,
190:             * the popup will be shown.
191:             */
192:            protected void showHintsPopup() {
193:                if (getTextComponent().isEnabled()
194:                        && getTextComponent().hasFocus()
195:                        && updateHints(getContext())) {
196:                    DelegateAction.replaceAction(getTextComponent(),
197:                            JComponent.WHEN_FOCUSED, KeyStroke.getKeyStroke(
198:                                    KeyEvent.VK_ESCAPE, 0), hideAction);
199:                    DelegateAction.replaceAction(getTextComponent(),
200:                            JComponent.WHEN_FOCUSED, KeyStroke.getKeyStroke(
201:                                    KeyEvent.VK_ENTER, 0), acceptAction, true);
202:
203:                    int x = 0;
204:                    int y = 0;
205:                    int height = 0;
206:
207:                    try {
208:                        int pos = getCaretPositionForPopup();
209:                        Rectangle position = getCaretRectangleForPopup(pos);
210:                        y = position.y;
211:                        x = position.x;
212:                        height = position.height;
213:                    } catch (BadLocationException e) {
214:                        // this should never happen!!!
215:                        e.printStackTrace();
216:                    }
217:
218:                    _popup.setOwner(getTextComponent());
219:                    _popup.showPopup(new Insets(y, x, getTextComponent()
220:                            .getHeight()
221:                            - height - y, 0));
222:                } else {
223:                    _popup.hidePopup();
224:                }
225:            }
226:
227:            /**
228:             * Gets the caret rectangle where caret is displayed. The popup will be show around the area so that the returned rectangle area
229:             * is always visible. This method will be called twice.
230:             *
231:             * @param caretPosition the caret position.
232:             * @return the popup position relative to the text component. <br>Please note, this position is actually a rectangle area. The reason is the popup could be
233:             *         shown below or above the rectangle. Usually, the popup will be shown below the rectangle. In this case, the x and y of the rectangle will
234:             *         be the top-left corner of the popup. However if there isn't enough space for the popup because it's close to screen bottom border, we will
235:             *         show the popup above the rectangle. In this case, the bottom-left corner of the popup will be at x and (y - height). Simply speaking,
236:             *         the popup will never cover the area specified by the rectangle (either below it or above it).
237:             * @throws BadLocationException if the given position does not represent a valid location in the associated document.
238:             */
239:            protected Rectangle getCaretRectangleForPopup(int caretPosition)
240:                    throws BadLocationException {
241:                return getTextComponent().getUI().modelToView(
242:                        getTextComponent(), caretPosition);
243:            }
244:
245:            /**
246:             * Gets the caret position which is used as the anchor point to display the popup.
247:             * By default, it {@link #isFollowCaret()} is true, it will return caret position.
248:             * Otherwise it will return the caret position at the beginning of the caret line.
249:             * Subclass can override to return any caret position.
250:             *
251:             * @return the caret position which is used as the anchor point to display the popup.
252:             */
253:            protected int getCaretPositionForPopup() {
254:                int caretPosition = Math.min(getTextComponent().getCaret()
255:                        .getDot(), getTextComponent().getCaret().getMark());
256:                if (isFollowCaret()) {
257:                    return caretPosition;
258:                } else {
259:                    try {
260:                        Rectangle viewRect = getTextComponent().getUI()
261:                                .modelToView(getTextComponent(), caretPosition);
262:                        viewRect.x = 0;
263:                        return getTextComponent().getUI().viewToModel(
264:                                getTextComponent(), viewRect.getLocation());
265:                    } catch (BadLocationException e) {
266:                        return 0;
267:                    }
268:                }
269:            }
270:
271:            /**
272:             * Gets the context for hints. The context is the information that IntelliHints needs
273:             * in order to generate a list of  hints. For example, for code-completion, the context is
274:             * current word the cursor is on. for file completion, the context is the full string starting from
275:             * the file system root.
276:             * <p>We provide a default context in AbstractIntelliHints. If it's a JTextArea,
277:             * the context will be the string at the caret line from line beginning to the caret position. If it's a JTextField,
278:             * the context will be whatever string in the text field. Subclass can always
279:             * override it to return the context that is appropriate.
280:             *
281:             * @return the context.
282:             */
283:            protected Object getContext() {
284:                if (getTextComponent() instanceof  JTextArea) {
285:                    int pos = getTextComponent().getCaretPosition();
286:                    if (pos == 0) {
287:                        return "";
288:                    } else {
289:                        String text = getTextComponent().getText();
290:                        int start = text.lastIndexOf("\n", pos - 1);
291:                        return text.substring(start + 1, pos);
292:                    }
293:                } else {
294:                    return getTextComponent().getText();
295:                }
296:            }
297:
298:            /**
299:             * Hides the hints popup.
300:             */
301:            protected void hideHintsPopup() {
302:                if (_popup != null) {
303:                    _popup.hidePopup();
304:                }
305:                setKeyTyped(false);
306:            }
307:
308:            /**
309:             * Enables or disables the hints popup.
310:             *
311:             * @param enabled true to enable the hints popup. Otherwise false.
312:             */
313:            public void setHintsEnabled(boolean enabled) {
314:                if (!enabled) {
315:                    // disable show hint temporarily
316:                    getTextComponent().getDocument().removeDocumentListener(
317:                            documentListener);
318:                } else {
319:                    // enable show hint again
320:                    getTextComponent().getDocument().addDocumentListener(
321:                            documentListener);
322:                }
323:
324:            }
325:
326:            /**
327:             * Checks if the hints popup is visible.
328:             *
329:             * @return true if it's visible. Otherwise, false.
330:             */
331:            public boolean isHintsPopupVisible() {
332:                return _popup != null && _popup.isPopupVisible();
333:            }
334:
335:            /**
336:             * Should the hints popup follows the caret.
337:             *
338:             * @return true if the popup shows up right below the caret. False if the popup always shows
339:             *         at the bottom-left corner (or top-left if there isn't enough on the bottom of the screen)
340:             *         of the JTextComponent.
341:             */
342:            public boolean isFollowCaret() {
343:                return _followCaret;
344:            }
345:
346:            /**
347:             * Sets the position of the hints popup. If followCaret is true, the popup
348:             * shows up right below the caret. Otherwise, it will stay at the bottom-left corner
349:             * (or top-left if there isn't enough on the bottom of the screen) of JTextComponent.
350:             *
351:             * @param followCaret true or false.
352:             */
353:            public void setFollowCaret(boolean followCaret) {
354:                _followCaret = followCaret;
355:            }
356:
357:            /**
358:             * Returns whether the hints popup is automatically displayed. Default is
359:             * true
360:             *
361:             * @return true if the popup should be automatically displayed. False will
362:             *         never show it automatically and then need the user to manually activate
363:             *         it via the getShowHintsKeyStroke() key binding.
364:             */
365:            public boolean isAutoPopup() {
366:                return _autoPopup;
367:            }
368:
369:            /**
370:             * Sets whether the popup should be displayed automatically. If autoPopup
371:             * is true then is the popup automatically displayed whenever updateHints()
372:             * return true. If autoPopup is false it's not automatically displayed and
373:             * will need the user to activate the key binding defined by
374:             * getShowHintsKeyStroke().
375:             *
376:             * @param autoPopup true or false
377:             */
378:            public void setAutoPopup(boolean autoPopup) {
379:                this ._autoPopup = autoPopup;
380:            }
381:
382:            /**
383:             * Gets the delegate keystrokes.
384:             * <p/>
385:             * When hint popup is visible, the keyboard focus never leaves the text component.
386:             * However the hint popup usually contains a component that user will try to use navigation key to
387:             * select an item. For example, use UP and DOWN key to navigate the list.
388:             * Those keystrokes, if the popup is visible, will be delegated
389:             * to the the component that returns from {@link #getDelegateComponent()}.
390:             *
391:             * @return an array of keystrokes that will be delegate to {@link #getDelegateComponent()} when hint popup is shown.
392:             */
393:            abstract protected KeyStroke[] getDelegateKeyStrokes();
394:
395:            /**
396:             * Gets the delegate component in the hint popup.
397:             *
398:             * @return the component that will receive the keystrokes that are delegated to hint popup.
399:             */
400:            abstract protected JComponent getDelegateComponent();
401:
402:            /**
403:             * Gets the keystroke that will trigger the hint popup. Usually the hints popup
404:             * will be shown automatically when user types. Only when the hint popup is hidden
405:             * accidentally, this keystroke will show the popup again.
406:             * <p/>
407:             * By default, it's the DOWN key for JTextField and CTRL+SPACE for JTextArea.
408:             *
409:             * @return the keystroek that will trigger the hint popup.
410:             */
411:            protected KeyStroke getShowHintsKeyStroke() {
412:                if (getTextComponent() instanceof  JTextField) {
413:                    return KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
414:                } else {
415:                    return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
416:                            KeyEvent.CTRL_MASK);
417:                }
418:            }
419:
420:            private DelegateAction acceptAction = new DelegateAction() {
421:                @Override
422:                public boolean delegateActionPerformed(ActionEvent e) {
423:                    JComponent tf = (JComponent) e.getSource();
424:                    AbstractIntelliHints hints = (AbstractIntelliHints) tf
425:                            .getClientProperty(CLIENT_PROPERTY_INTELLI_HINTS);
426:                    if (hints != null) {
427:                        hints.hideHintsPopup();
428:                        if (hints.getSelectedHint() != null) {
429:                            hints.setHintsEnabled(false);
430:                            hints.acceptHint(hints.getSelectedHint());
431:                            hints.setHintsEnabled(true);
432:                            return true;
433:                        } else if (getTextComponent().getRootPane() != null) {
434:                            JButton button = getTextComponent().getRootPane()
435:                                    .getDefaultButton();
436:                            if (button != null) {
437:                                button.doClick();
438:                                return true;
439:                            }
440:                        }
441:                    }
442:                    return false;
443:                }
444:            };
445:
446:            private static DelegateAction showAction = new DelegateAction() {
447:                @Override
448:                public boolean delegateActionPerformed(ActionEvent e) {
449:                    JComponent tf = (JComponent) e.getSource();
450:                    AbstractIntelliHints hints = (AbstractIntelliHints) tf
451:                            .getClientProperty(CLIENT_PROPERTY_INTELLI_HINTS);
452:                    if (hints != null && tf.isEnabled()
453:                            && !hints.isHintsPopupVisible()) {
454:                        hints.showHintsPopup();
455:                        return true;
456:                    }
457:                    return false;
458:                }
459:            };
460:
461:            private DelegateAction hideAction = new DelegateAction() {
462:                @Override
463:                public boolean isEnabled() {
464:                    return _textComponent.isEnabled() && isHintsPopupVisible();
465:                }
466:
467:                @Override
468:                public boolean delegateActionPerformed(ActionEvent e) {
469:                    if (isEnabled()) {
470:                        hideHintsPopup();
471:                        return true;
472:                    }
473:                    return false;
474:                }
475:            };
476:
477:            private DocumentListener documentListener = new DocumentListener() {
478:                private Timer timer = new Timer(200, new ActionListener() {
479:                    public void actionPerformed(ActionEvent e) {
480:                        if (isKeyTyped()) {
481:                            if (isHintsPopupVisible() || isAutoPopup()) {
482:                                showHintsPopup();
483:                            }
484:                            setKeyTyped(false);
485:                        }
486:                    }
487:                });
488:
489:                public void insertUpdate(DocumentEvent e) {
490:                    startTimer();
491:                }
492:
493:                public void removeUpdate(DocumentEvent e) {
494:                    startTimer();
495:                }
496:
497:                public void changedUpdate(DocumentEvent e) {
498:                }
499:
500:                void startTimer() {
501:                    if (timer.isRunning()) {
502:                        timer.restart();
503:                    } else {
504:                        timer.setRepeats(false);
505:                        timer.start();
506:                    }
507:                }
508:            };
509:
510:            private boolean isKeyTyped() {
511:                return _keyTyped;
512:            }
513:
514:            private void setKeyTyped(boolean keyTyped) {
515:                _keyTyped = keyTyped;
516:            }
517:
518:            private static class LazyDelegateAction extends DelegateAction {
519:                private KeyStroke _keyStroke;
520:
521:                public LazyDelegateAction(KeyStroke keyStroke) {
522:                    _keyStroke = keyStroke;
523:                }
524:
525:                @Override
526:                public boolean delegateActionPerformed(ActionEvent e) {
527:                    JComponent tf = (JComponent) e.getSource();
528:                    AbstractIntelliHints hints = (AbstractIntelliHints) tf
529:                            .getClientProperty(CLIENT_PROPERTY_INTELLI_HINTS);
530:                    if (hints != null && tf.isEnabled()) {
531:                        if (hints.isHintsPopupVisible()) {
532:                            Object key = hints.getDelegateComponent()
533:                                    .getInputMap().get(_keyStroke);
534:                            key = key == null ? hints
535:                                    .getTextComponent()
536:                                    .getInputMap(
537:                                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
538:                                    .get(_keyStroke)
539:                                    : key;
540:                            if (key != null) {
541:                                Object action = hints.getDelegateComponent()
542:                                        .getActionMap().get(key);
543:                                if (action instanceof  Action) {
544:                                    ((Action) action)
545:                                            .actionPerformed(new ActionEvent(
546:                                                    hints
547:                                                            .getDelegateComponent(),
548:                                                    0, "" + key));
549:                                    return true;
550:                                }
551:                            }
552:                        }
553:                    }
554:                    return false;
555:                }
556:            }
557:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.