Source Code Cross Referenced for SearchableBar.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:         * @(#)FirefoxSearchBar.java 10/11/2005
003:         *
004:         * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005:         */
006:        package com.jidesoft.swing;
007:
008:        import com.jidesoft.plaf.UIDefaultsLookup;
009:        import com.jidesoft.swing.event.SearchableEvent;
010:        import com.jidesoft.swing.event.SearchableListener;
011:
012:        import javax.swing.*;
013:        import javax.swing.event.DocumentEvent;
014:        import javax.swing.event.DocumentListener;
015:        import java.awt.*;
016:        import java.awt.event.*;
017:        import java.util.Locale;
018:
019:        /**
020:         * <code>SearchableBar</code> is a convenient component to enable searching feature
021:         * for components. As long as the component support <code>Searchable</code> feature,
022:         * it can work with <code>SearchableBar</code>.
023:         * <p/>
024:         * Different from <code>Searchable</code> feature which uses a small popup window to
025:         * allow user typing in the searching text, <code>SearchableBar</code> provides a full-size panel.
026:         * Although they both pretty provide the same set of features, they should be used in
027:         * different cases to achieve the most desirable result.
028:         * <p/>
029:         * First of all, <code>SearchableBar</code> is a lot bigger than <code>Searchable</code>'s popup
030:         * and need more space on the screen. The component that installs <code>SearchableBar</code> should
031:         * be large enough. In comparison, <code>Searchable</code> can be installed on components of any size
032:         * as it's a floating popup.
033:         * <p/>
034:         * Secondly, <code>SearchableBar</code> can be set visible all the time or can be set visible by a
035:         * keystroke and stay visible unless user explicitly hides it. If your user is not computer savvy,
036:         * <code>SearchableBar</code> is more appropriate because user can see searching feature very easily.
037:         * <code>SearchableBar</code> can also be a better replacement the traditional "Find" or "Search" dialog
038:         * because <code>SearchableBar</code> doesn't block user input like modal dialog. In comparison,
039:         * <code>Searchable</code>'s popup is very transient. Mouse clicks outside the popup will hide the popup.
040:         * For computer savvy it is very helpful but it could be hard for non-computer savvy to "understand" it.
041:         * A good example is IntelliJ IDEA heavily uses Searchable popup because the users are all Java developers. Firefox,
042:         * on the other hand, uses SearchableBar because the users are just regular computer users.
043:         * <p/>
044:         * Although appearence wise, these two are very different, they both based on {@link Searchable} interface. So as developer,
045:         * both are almost the same. <code>SearchableBar</code> based on <code>Searchable</code>. So if you have an interface of
046:         * <code>Searchable</code>, all you need is to call
047:         * <code><pre>
048:         * SearchableBar.install(searchable, KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK), new SearchableBar.Installer() {
049:         *     public void openSearchBar(SearchableBar searchableBar) {
050:         *        // add code to show search bar
051:         *     }
052:         * <p/>
053:         *     public void closeSearchBar(SearchableBar searchableBar) {
054:         *        // add code to close search bar
055:         * }
056:         * });
057:         * </pre></code>
058:         * Or if you want fully control the SearchableBar, you can create one using one of its constructors
059:         * and add to wherever you want.
060:         * <p/>
061:         * There are a few options you can set on <code>SearchableBar</code>. You can set compact or full mode. Compact mode
062:         * will only use icon for buttons v.s. full mode will use both icon and text for buttons. All buttons on the <code>SearchableBar</code>
063:         * can be shown/hidden by using {@link #setVisibleButtons(int)} method. You can also set the text field background for mismatch by using
064:         * {@link #setMismatchForeground(java.awt.Color)}.
065:         * <p/>
066:         */
067:        public class SearchableBar extends JToolBar implements 
068:                SearchableProvider {
069:            private Searchable _searchable;
070:
071:            private JLabel _statusLabel;
072:            private JTextField _textField;
073:
074:            protected AbstractButton _closeButton;
075:            protected AbstractButton _findPrevButton;
076:            protected AbstractButton _findNextButton;
077:            protected AbstractButton _highlightsButton;
078:
079:            private AbstractButton _matchCaseCheckBox;
080:            private AbstractButton _repeatCheckBox;
081:
082:            public static final int SHOW_CLOSE = 0x1;
083:            public static final int SHOW_NAVIGATION = 0x2;
084:            public static final int SHOW_HIGHLIGHTS = 0x4;
085:            public static final int SHOW_MATCHCASE = 0x8;
086:            public static final int SHOW_REPEATS = 0x10;
087:            public static final int SHOW_STATUS = 0x20;
088:            public static final int SHOW_ALL = 0xFFFFFFFF;
089:
090:            private int _visibleButtons = SHOW_ALL & ~SHOW_REPEATS; // default is show all but repeats
091:            private boolean _compact;
092:
093:            /**
094:             * Creates a searchable bar.
095:             *
096:             * @param searchable
097:             */
098:            public SearchableBar(Searchable searchable) {
099:                this (searchable, "", false);
100:            }
101:
102:            /**
103:             * Creates a searchable bar in compact mode or full mode.
104:             *
105:             * @param searchable
106:             */
107:            public SearchableBar(Searchable searchable, boolean compact) {
108:                this (searchable, "", compact);
109:            }
110:
111:            /**
112:             * Creates a searchable bar with initial searching text and in compact mode or full mode.
113:             *
114:             * @param searchable
115:             */
116:            public SearchableBar(Searchable searchable, String initialText,
117:                    boolean compact) {
118:                setFloatable(false);
119:                setRollover(true);
120:                _searchable = searchable;
121:                _searchable.addSearchableListener(new SearchableListener() {
122:                    public void searchableEventFired(SearchableEvent e) {
123:                        if (e.getID() == SearchableEvent.SEARCHABLE_MODEL_CHANGE) {
124:                            highlightAllOrNext();
125:                        }
126:                    }
127:                });
128:                _searchable.setSearchableProvider(this );
129:                _compact = compact;
130:                initComponents(initialText);
131:            }
132:
133:            private void initComponents(String initialText) {
134:                AbstractAction closeAction = new AbstractAction() {
135:                    public void actionPerformed(ActionEvent e) {
136:                        if (getInstaller() != null) {
137:                            getInstaller().closeSearchBar(SearchableBar.this );
138:                        }
139:                    }
140:                };
141:
142:                AbstractAction findNextAction = new AbstractAction() {
143:                    public void actionPerformed(ActionEvent e) {
144:                        _highlightsButton.setSelected(false);
145:                        String text = getSearchingText();
146:                        int cursor = _searchable.getCursor();
147:                        int found = _searchable.findNext(text);
148:                        if (found != -1 && _searchable.isRepeats()
149:                                && found <= cursor) {
150:                            select(found, text, false);
151:                            setStatus(
152:                                    getResourceString("SearchableBar.reachedBottomRepeat"),
153:                                    getImageIcon(SearchableBarIconsFactory.Buttons.REPEAT));
154:                        } else if (!_searchable.isRepeats() && found == -1) {
155:                            setStatus(
156:                                    getResourceString("SearchableBar.reachedBottom"),
157:                                    getImageIcon(SearchableBarIconsFactory.Buttons.ERROR));
158:                        } else if (found != -1) {
159:                            select(found, text, false);
160:                            clearStatus();
161:                        }
162:                    }
163:                };
164:
165:                AbstractAction findPrevAction = new AbstractAction() {
166:                    public void actionPerformed(ActionEvent e) {
167:                        _highlightsButton.setSelected(false);
168:                        String text = getSearchingText();
169:                        int cursor = _searchable.getCursor();
170:                        int found = _searchable.findPrevious(text);
171:                        if (found != -1 && _searchable.isRepeats()
172:                                && found >= cursor) {
173:                            select(found, text, false);
174:                            setStatus(
175:                                    getResourceString("SearchableBar.reachedTopRepeat"),
176:                                    getImageIcon(SearchableBarIconsFactory.Buttons.REPEAT));
177:                        } else if (!_searchable.isRepeats() && found == -1) {
178:                            setStatus(
179:                                    getResourceString("SearchableBar.reachedTop"),
180:                                    getImageIcon(SearchableBarIconsFactory.Buttons.ERROR));
181:                        } else if (found != -1) {
182:                            select(found, text, false);
183:                            clearStatus();
184:                        }
185:                    }
186:                };
187:
188:                _closeButton = createCloseButton(closeAction);
189:                _findNextButton = createFindNextButton(findNextAction);
190:                _findPrevButton = createFindPrevButton(findPrevAction);
191:                _highlightsButton = createHighlightButton();
192:                _matchCaseCheckBox = createMatchCaseButton();
193:                _repeatCheckBox = createRepeatsButton();
194:
195:                _statusLabel = new JLabel();
196:
197:                //setup text field
198:                _textField = createTextField();
199:                _textField.addFocusListener(new FocusAdapter() {
200:                    @Override
201:                    public void focusGained(FocusEvent e) {
202:                        _textField.selectAll();
203:                    }
204:                });
205:                _textField.setColumns(13);
206:                _textField.getDocument().addDocumentListener(
207:                        new DocumentListener() {
208:                            private Timer timer = new Timer(_searchable
209:                                    .getSearchingDelay(), new ActionListener() {
210:                                public void actionPerformed(ActionEvent e) {
211:                                    highlightAllOrNext();
212:                                }
213:                            });
214:
215:                            public void insertUpdate(DocumentEvent e) {
216:                                startTimer();
217:                            }
218:
219:                            public void removeUpdate(DocumentEvent e) {
220:                                startTimer();
221:                            }
222:
223:                            public void changedUpdate(DocumentEvent e) {
224:                                startTimer();
225:                            }
226:
227:                            void startTimer() {
228:                                if (_searchable.getSearchingDelay() > 0) {
229:                                    if (timer.isRunning()) {
230:                                        timer.restart();
231:                                    } else {
232:                                        timer.setRepeats(false);
233:                                        timer.start();
234:                                    }
235:                                } else {
236:                                    highlightAllOrNext();
237:                                }
238:                            }
239:                        });
240:                _textField.setText(initialText);
241:
242:                _textField.registerKeyboardAction(findNextAction, KeyStroke
243:                        .getKeyStroke(KeyEvent.VK_DOWN, 0),
244:                        JComponent.WHEN_FOCUSED);
245:                _textField.registerKeyboardAction(findNextAction, KeyStroke
246:                        .getKeyStroke(KeyEvent.VK_ENTER, 0),
247:                        JComponent.WHEN_FOCUSED);
248:                _textField.registerKeyboardAction(findPrevAction, KeyStroke
249:                        .getKeyStroke(KeyEvent.VK_UP, 0),
250:                        JComponent.WHEN_FOCUSED);
251:                _textField.registerKeyboardAction(closeAction, KeyStroke
252:                        .getKeyStroke(KeyEvent.VK_ESCAPE, 0),
253:                        JComponent.WHEN_FOCUSED);
254:
255:                installComponents();
256:
257:                int found = _searchable.findFromCursor(getSearchingText());
258:                select(found, initialText, false);
259:            }
260:
261:            /**
262:             * Creates the text field where user types the text to be searched.
263:             *
264:             * @return a text field.
265:             */
266:            protected JTextField createTextField() {
267:                return new JTextField();
268:            }
269:
270:            /**
271:             * Gets the underlying Searchable object.
272:             *
273:             * @return the Searchable object.
274:             */
275:            public Searchable getSearchable() {
276:                return _searchable;
277:            }
278:
279:            /**
280:             * Creates the close button. Subclass can override it to create your own close button.
281:             *
282:             * @param closeAction
283:             * @return the close button.
284:             */
285:            protected AbstractButton createCloseButton(
286:                    AbstractAction closeAction) {
287:                AbstractButton button = new JButton(
288:                        getImageIcon(SearchableBarIconsFactory.Buttons.CLOSE));
289:                button.addActionListener(closeAction);
290:                button.setRolloverEnabled(true);
291:                button.setBorder(BorderFactory.createEmptyBorder());
292:                button.setOpaque(false);
293:                button.setRequestFocusEnabled(false);
294:                button.setFocusable(false);
295:                button
296:                        .setRolloverIcon(getImageIcon(SearchableBarIconsFactory.Buttons.CLOSE_ROLLOVER));
297:                return button;
298:            }
299:
300:            /**
301:             * Creates the find next button. Subclass can override it to create your own find next button.
302:             *
303:             * @param findNextAction
304:             * @return the find next button.
305:             */
306:            protected AbstractButton createFindNextButton(
307:                    AbstractAction findNextAction) {
308:                AbstractButton button = new JButton(_compact ? ""
309:                        : getResourceString("SearchableBar.findNext"),
310:                        getImageIcon(SearchableBarIconsFactory.Buttons.NEXT));
311:                button
312:                        .setToolTipText(getResourceString("SearchableBar.findNext.tooltip"));
313:                button.setMnemonic(getResourceString(
314:                        "SearchableBar.findNext.mnemonic").charAt(0));
315:                button
316:                        .setRolloverIcon(getImageIcon(SearchableBarIconsFactory.Buttons.NEXT_ROLLOVER));
317:                button
318:                        .setDisabledIcon(getImageIcon(SearchableBarIconsFactory.Buttons.NEXT_DISABLED));
319:                button.setRequestFocusEnabled(false);
320:                button.setFocusable(false);
321:                button.addActionListener(findNextAction);
322:                button.setEnabled(false);
323:                return button;
324:            }
325:
326:            /**
327:             * Creates the find prev button. Subclass can override it to create your own find prev button.
328:             *
329:             * @param findPrevAction
330:             * @return the find prev button.
331:             */
332:            protected AbstractButton createFindPrevButton(
333:                    AbstractAction findPrevAction) {
334:                AbstractButton button = new JButton(
335:                        _compact ? ""
336:                                : getResourceString("SearchableBar.findPrevious"),
337:                        getImageIcon(SearchableBarIconsFactory.Buttons.PREVIOUS));
338:                button
339:                        .setToolTipText(getResourceString("SearchableBar.findPrevious.tooltip"));
340:                button.setMnemonic(getResourceString(
341:                        "SearchableBar.findPrevious.mnemonic").charAt(0));
342:                button
343:                        .setRolloverIcon(getImageIcon(SearchableBarIconsFactory.Buttons.PREVIOUS_ROLLOVER));
344:                button
345:                        .setDisabledIcon(getImageIcon(SearchableBarIconsFactory.Buttons.PREVIOUS_DISABLED));
346:                button.setRequestFocusEnabled(false);
347:                button.setFocusable(false);
348:                button.addActionListener(findPrevAction);
349:                button.setEnabled(false);
350:                return button;
351:            }
352:
353:            /**
354:             * Creates the highlight button.
355:             *
356:             * @return the highlight button.
357:             */
358:            protected AbstractButton createHighlightButton() {
359:                AbstractButton button = new JToggleButton(
360:                        _compact ? ""
361:                                : getResourceString("SearchableBar.highlights"),
362:                        getImageIcon(SearchableBarIconsFactory.Buttons.HIGHLIGHTS));
363:                button
364:                        .setToolTipText(getResourceString("SearchableBar.highlights.tooltip"));
365:                button.setMnemonic(getResourceString(
366:                        "SearchableBar.highlights.mnemonic").charAt(0));
367:                button
368:                        .setSelectedIcon(getImageIcon(SearchableBarIconsFactory.Buttons.HIGHLIGHTS_SELECTED));
369:                button
370:                        .setDisabledIcon(getImageIcon(SearchableBarIconsFactory.Buttons.HIGHLIGHTS_DISABLED));
371:                button
372:                        .setRolloverIcon(getImageIcon(SearchableBarIconsFactory.Buttons.HIGHLIGHTS_ROLLOVER));
373:                button
374:                        .setRolloverSelectedIcon(getImageIcon(SearchableBarIconsFactory.Buttons.HIGHLIGHTS_ROLLOVER_SELECTED));
375:                button.setRequestFocusEnabled(false);
376:                button.setFocusable(false);
377:
378:                AbstractAction highlightAllAction = new AbstractAction() {
379:                    public void actionPerformed(ActionEvent e) {
380:                        highlightAllOrNext();
381:                    }
382:                };
383:
384:                button.addActionListener(highlightAllAction);
385:                button.setEnabled(false);
386:                return button;
387:            }
388:
389:            /**
390:             * Creates the repeat button. By default it will return a JCheckBox.
391:             * Subclass class can override it to return your own button or customize
392:             * the button created by default as long as it can set underlying Searchable's repeats property.
393:             *
394:             * @return the repeat button.
395:             */
396:            protected AbstractButton createRepeatsButton() {
397:                AbstractButton button = new JCheckBox(
398:                        getResourceString("SearchableBar.repeats"));
399:                button.setMnemonic(getResourceString(
400:                        "SearchableBar.repeats.mnemonic").charAt(0));
401:                button.setRequestFocusEnabled(false);
402:                button.setFocusable(false);
403:                button.setSelected(getSearchable().isRepeats());
404:                button.addItemListener(new ItemListener() {
405:                    public void itemStateChanged(ItemEvent e) {
406:                        if (e.getSource() instanceof  AbstractButton) {
407:                            getSearchable().setRepeats(
408:                                    ((AbstractButton) e.getSource())
409:                                            .isSelected());
410:                        }
411:                    }
412:                });
413:                return button;
414:            }
415:
416:            /**
417:             * Creates the match case button. By default it will return a JCheckBox.
418:             * Subclass class can override it to return your own button or customize
419:             * the button created by default as long as it can set underlying Searchable's caseSensitive property.
420:             *
421:             * @return the match case button.
422:             */
423:            protected AbstractButton createMatchCaseButton() {
424:                JCheckBox checkBox = new JCheckBox(
425:                        getResourceString("SearchableBar.matchCase"));
426:                checkBox.setMnemonic(getResourceString(
427:                        "SearchableBar.matchCase.mnemonic").charAt(0));
428:                checkBox.setRequestFocusEnabled(false);
429:                checkBox.setFocusable(false);
430:                checkBox.setSelected(getSearchable().isCaseSensitive());
431:                checkBox.addItemListener(new ItemListener() {
432:                    public void itemStateChanged(ItemEvent e) {
433:                        if (e.getSource() instanceof  AbstractButton) {
434:                            getSearchable().setCaseSensitive(
435:                                    ((AbstractButton) e.getSource())
436:                                            .isSelected());
437:                            highlightAllOrNext();
438:                        }
439:                    }
440:                });
441:                return checkBox;
442:            }
443:
444:            /**
445:             * Adds the buttons to the SearchableBar. Subclass can override this method to rearrange the layout of those buttons.
446:             */
447:            protected void installComponents() {
448:                setBorder(BorderFactory.createEtchedBorder());
449:                setLayout(new JideBoxLayout(this , JideBoxLayout.X_AXIS));
450:                add(Box.createHorizontalStrut(4), JideBoxLayout.FIX);
451:                if ((_visibleButtons & SHOW_CLOSE) != 0) {
452:                    add(_closeButton);
453:                    add(Box.createHorizontalStrut(10));
454:                }
455:                // setup the label
456:                JLabel label = new JLabel(
457:                        getResourceString("SearchableBar.find"));
458:                label.setDisplayedMnemonic(getResourceString(
459:                        "SearchableBar.find.mnemonic").charAt(0));
460:                label.setLabelFor(_textField);
461:                add(label);
462:                add(Box.createHorizontalStrut(2), JideBoxLayout.FIX);
463:                add(JideSwingUtilities.createCenterPanel(_textField),
464:                        JideBoxLayout.FIX);
465:                add(Box.createHorizontalStrut(2), JideBoxLayout.FIX);
466:                if ((_visibleButtons & SHOW_NAVIGATION) != 0) {
467:                    add(_findNextButton);
468:                    add(_findPrevButton);
469:                }
470:                if ((_visibleButtons & SHOW_HIGHLIGHTS) != 0) {
471:                    add(_highlightsButton);
472:                }
473:                if ((_visibleButtons & SHOW_MATCHCASE) != 0) {
474:                    add(_matchCaseCheckBox);
475:                }
476:                if ((_visibleButtons & SHOW_REPEATS) != 0) {
477:                    add(_repeatCheckBox);
478:                }
479:                if ((_visibleButtons & SHOW_STATUS) != 0) {
480:                    add(Box.createHorizontalStrut(24));
481:                    add(_statusLabel, JideBoxLayout.VARY);
482:                }
483:                add(Box.createHorizontalStrut(6), JideBoxLayout.FIX);
484:            }
485:
486:            private void highlightAllOrNext() {
487:                if (_highlightsButton.isSelected()) {
488:                    highlighAll();
489:                } else {
490:                    highlightNext();
491:                }
492:            }
493:
494:            private void highlighAll() {
495:                String text = getSearchingText();
496:                if (text == null || text.length() == 0) {
497:                    return;
498:                }
499:                boolean old = _searchable.isRepeats();
500:                _searchable.setRepeats(false);
501:                int index = _searchable.findFirst(text);
502:                if (index != -1) {
503:                    _searchable.setSelectedIndex(index, false); // clear side effect of ctrl-a will select all items
504:                    _searchable.setCursor(index); // as setSelectedIndex is used directly, we have to manually set the cursor value.
505:                    _findNextButton.setEnabled(true);
506:                    _findPrevButton.setEnabled(true);
507:                    _highlightsButton.setEnabled(true);
508:                    clearStatus();
509:                } else {
510:                    select(-1, text, false);
511:                    _findNextButton.setEnabled(false);
512:                    _findPrevButton.setEnabled(false);
513:                    _highlightsButton.setEnabled(false);
514:                    setStatus(
515:                            getResourceString("SearchableBar.notFound"),
516:                            getImageIcon(SearchableBarIconsFactory.Buttons.ERROR));
517:                }
518:
519:                int firstIndex = -1;
520:
521:                while (index != -1) {
522:                    int newIndex = _searchable.findNext(text);
523:                    if (index == newIndex) {
524:                        index = -1;
525:                    } else {
526:                        index = newIndex;
527:                    }
528:                    if (index != -1) {
529:                        if (firstIndex == -1) {
530:                            firstIndex = index;
531:                        }
532:                        select(index, text, true);
533:                    }
534:                }
535:                // now select the first one
536:                if (firstIndex != -1) {
537:                    select(firstIndex, text, true);
538:                }
539:
540:                _searchable.setRepeats(old);
541:                _searchable.setCursor(0);
542:            }
543:
544:            private void highlightNext() {
545:                String text = getSearchingText();
546:                if (text == null || text.length() == 0) {
547:                    _findNextButton.setEnabled(false);
548:                    _findPrevButton.setEnabled(false);
549:                    _highlightsButton.setEnabled(false);
550:                    clearStatus();
551:                    return;
552:                }
553:                int found = _searchable.findFromCursor(text);
554:                if (found == -1) {
555:                    select(-1, "", false);
556:                    _findNextButton.setEnabled(false);
557:                    _findPrevButton.setEnabled(false);
558:                    _highlightsButton.setEnabled(false);
559:                    setStatus(
560:                            getResourceString("SearchableBar.notFound"),
561:                            getImageIcon(SearchableBarIconsFactory.Buttons.ERROR));
562:                } else {
563:                    select(found, text, false);
564:                    _findNextButton.setEnabled(true);
565:                    _findPrevButton.setEnabled(true);
566:                    _highlightsButton.setEnabled(true);
567:                    clearStatus();
568:                }
569:            }
570:
571:            private void clearStatus() {
572:                _statusLabel.setIcon(null);
573:                _statusLabel.setText("");
574:                _textField.setBackground(UIDefaultsLookup
575:                        .getColor("TextField.background"));
576:            }
577:
578:            private void setStatus(String message, Icon icon) {
579:                _statusLabel.setIcon(icon);
580:                _statusLabel.setText(message);
581:            }
582:
583:            /**
584:             * Makes the search field having focus.
585:             */
586:            public void focusSearchField() {
587:                if (_textField != null) {
588:                    _textField.requestFocus();
589:                }
590:            }
591:
592:            protected void select(int index, String searchingText,
593:                    boolean incremental) {
594:                if (index != -1) {
595:                    _searchable.setSelectedIndex(index, incremental);
596:                    _searchable.setCursor(index);
597:                    _textField.setBackground(UIDefaultsLookup
598:                            .getColor("TextField.background"));
599:                } else {
600:                    _searchable.setSelectedIndex(-1, false);
601:                    _textField.setBackground(getMismatchBackground());
602:                }
603:                _searchable.firePropertyChangeEvent(searchingText);
604:                if (index != -1) {
605:                    Object element = _searchable.getElementAt(index);
606:                    _searchable.fireSearchableEvent(new SearchableEvent(
607:                            _searchable, SearchableEvent.SEARCHABLE_MATCH,
608:                            searchingText, element, _searchable
609:                                    .convertElementToString(element)));
610:                } else {
611:                    _searchable.fireSearchableEvent(new SearchableEvent(
612:                            _searchable, SearchableEvent.SEARCHABLE_NOMATCH,
613:                            searchingText));
614:                }
615:            }
616:
617:            public String getSearchingText() {
618:                return _textField != null ? _textField.getText() : "";
619:            }
620:
621:            public boolean isPassive() {
622:                return false;
623:            }
624:
625:            final private static Color DEFAULT_MISMATCH_BACKGROUND = new Color(
626:                    255, 85, 85);
627:            private Color _mismatchBackground;
628:
629:            /**
630:             * Sets the background for mismatch.
631:             *
632:             * @param mismatchBackground
633:             */
634:            public void setMismatchForeground(Color mismatchBackground) {
635:                _mismatchBackground = mismatchBackground;
636:            }
637:
638:            /**
639:             * Gets the background color when the searching text doesn't match with any of the elements in the component.
640:             *
641:             * @return the forground color for mismatch. If you never call
642:             *         {@link #setMismatchForeground(java.awt.Color)}. red color will be used.
643:             */
644:            public Color getMismatchBackground() {
645:                if (_mismatchBackground == null) {
646:                    return DEFAULT_MISMATCH_BACKGROUND;
647:                } else {
648:                    return _mismatchBackground;
649:                }
650:            }
651:
652:            private Installer _installer;
653:
654:            /**
655:             * The installer for SearchableBar.
656:             */
657:            public interface Installer {
658:                /**
659:                 * Called to show the SearchableBar so that user can see it.
660:                 * <p/>
661:                 * For example, if you want to add a SearchableBar to the south of a JTextArea,
662:                 * you should add JTextArea to the CENTER of a BorderLayout panel. In this method,
663:                 * you add the SearchableBar to the SOUTH of the same BorderLayout panel.
664:                 *
665:                 * @param searchableBar
666:                 */
667:                public void openSearchBar(SearchableBar searchableBar);
668:
669:                /**
670:                 * Called to hide the SearchableBar.
671:                 *
672:                 * @param searchableBar
673:                 */
674:                public void closeSearchBar(SearchableBar searchableBar);
675:            }
676:
677:            public Installer getInstaller() {
678:                return _installer;
679:            }
680:
681:            /**
682:             * Sets the installer. Installer is responsible for the installation and uninstallation of SearchableBar.
683:             *
684:             * @param installer
685:             */
686:            public void setInstaller(Installer installer) {
687:                _installer = installer;
688:            }
689:
690:            /**
691:             * Installs a SearchableBar on a component. This is just a convenient method for you, you can install it in your own code.
692:             * See below for the actual code we used in this method.
693:             * <p/>
694:             * <code><pre>
695:             * final SearchableBar searchableBar = new SearchableBar(searchable);
696:             * searchableBar.setInstaller(installer);
697:             * ((JComponent) searchable.getComponent()).registerKeyboardAction(new AbstractAction() {
698:             *     public void actionPerformed(ActionEvent e) {
699:             *         searchableBar.getInstaller().openSearchBar(searchableBar);
700:             *         searchableBar.focusSearchField();
701:             *     }
702:             * }, keyStroke, JComponent.WHEN_FOCUSED);
703:             * return searchableBar;
704:             * </pre></code>
705:             *
706:             * @param searchable
707:             * @param keyStroke
708:             * @param installer
709:             * @return the SearchableBar that is created.
710:             */
711:            public static SearchableBar install(Searchable searchable,
712:                    KeyStroke keyStroke, Installer installer) {
713:                final SearchableBar searchableBar = new SearchableBar(
714:                        searchable);
715:                searchableBar.setInstaller(installer);
716:                ((JComponent) searchable.getComponent())
717:                        .registerKeyboardAction(new AbstractAction() {
718:                            public void actionPerformed(ActionEvent e) {
719:                                searchableBar.getInstaller().openSearchBar(
720:                                        searchableBar);
721:                                searchableBar.focusSearchField();
722:                            }
723:                        }, keyStroke, JComponent.WHEN_FOCUSED);
724:                return searchableBar;
725:            }
726:
727:            @Override
728:            public void processKeyEvent(KeyEvent e) {
729:            }
730:
731:            public int getVisibleButtons() {
732:                return _visibleButtons;
733:            }
734:
735:            /**
736:             * Sets visible buttons on <code>SearchableBar</code>.
737:             *
738:             * @param visibleButtons bit-wise all of several constants. Valid constants are
739:             *                       <ul>
740:             *                       <li> {@link #SHOW_CLOSE} - the close button
741:             *                       <li> {@link #SHOW_NAVIGATION} - the find next and find previous buttons
742:             *                       <li> {@link #SHOW_HIGHLIGHTS} - highlights all button
743:             *                       <li> {@link #SHOW_MATCHCASE} - match case button
744:             *                       <li> {@link #SHOW_REPEATS} - repeats button
745:             *                       <li> {@link #SHOW_STATUS} - status area
746:             *                       <li> {@link #SHOW_ALL} - all buttons
747:             *                       </ul>
748:             *                       For example, if you want to show only close and highlighs all button, call
749:             *                       <code>setVisibleButtons(SearchableBar.SHOW_CLOSE | SearchableBar.SHOW_HIGHLIGHTS)</code>.
750:             */
751:            public void setVisibleButtons(int visibleButtons) {
752:                _visibleButtons = visibleButtons;
753:                removeAll();
754:                installComponents();
755:                revalidate();
756:                repaint();
757:            }
758:
759:            /**
760:             * Checks if <code>SearchableBar</code> is in compact mode.
761:             *
762:             * @return true if in compact. Otherwise, false.
763:             */
764:            public boolean isCompact() {
765:                return _compact;
766:            }
767:
768:            /**
769:             * Sets the <code>SearchableBar</code> to compact or full mode. In compact mode
770:             * will only use icon for buttons v.s. full mode will use both icon and text for buttons.
771:             *
772:             * @param compact
773:             */
774:            public void setCompact(boolean compact) {
775:                _compact = compact;
776:                _findNextButton.setText(_compact ? ""
777:                        : getResourceString("SearchableBar.findNext"));
778:                _highlightsButton.setText(_compact ? ""
779:                        : getResourceString("SearchableBar.highlights"));
780:                _findPrevButton.setText(_compact ? ""
781:                        : getResourceString("SearchableBar.findPrevious"));
782:            }
783:
784:            /**
785:             * Gets the icons from SearchableBarIconsFactory. Subclass can override this method if they want to provide their own icon.
786:             *
787:             * @param name
788:             * @return the icon of the specified name.
789:             */
790:            protected ImageIcon getImageIcon(String name) {
791:                return SearchableBarIconsFactory.getImageIcon(name);
792:            }
793:
794:            /**
795:             * Gets the localized string from resource bundle. Subclass can override it to provide its own string.
796:             * Available keys are defined in swing.properties that begin with "SearchableBar.".
797:             *
798:             * @param key
799:             * @return the localized string.
800:             */
801:            protected String getResourceString(String key) {
802:                return Resource.getResourceBundle(Locale.getDefault())
803:                        .getString(key);
804:            }
805:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.