001    /*
002     * $Id: ListSearchable.java 3166 2009-01-02 13:27:18Z rah003 $
003     *
004     * Copyright 2007 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.search;
022    
023    import java.util.regex.Matcher;
024    import java.util.regex.Pattern;
025    
026    import org.jdesktop.swingx.JXList;
027    import org.jdesktop.swingx.decorator.AbstractHighlighter;
028    import org.jdesktop.swingx.decorator.Highlighter;
029    
030    public class ListSearchable extends AbstractSearchable {
031    
032            protected JXList list;
033    
034            public ListSearchable(JXList list) {
035               this.list = list; 
036            }
037            
038            @Override
039            protected void findMatchAndUpdateState(Pattern pattern, int startRow, boolean backwards) {
040                SearchResult searchResult = null;
041                if (backwards) {
042                    for (int index = startRow; index >= 0 && searchResult == null; index--) {
043                        searchResult = findMatchAt(pattern, index);
044                    }
045                } else {
046                    for (int index = startRow; index < getSize() && searchResult == null; index++) {
047                        searchResult = findMatchAt(pattern, index);
048                    }
049                }
050                updateState(searchResult);
051            }
052    
053            @Override
054            protected SearchResult findExtendedMatch(Pattern pattern, int row) {
055                
056                return findMatchAt(pattern, row);
057            }
058            /**
059             * Matches the cell content at row/col against the given Pattern.
060             * Returns an appropriate SearchResult if matching or null if no
061             * matching
062             * 
063             * @param pattern 
064             * @param row a valid row index in view coordinates
065             * @return <code>SearchResult</code> if matched otherwise null
066             */
067            protected SearchResult findMatchAt(Pattern pattern, int row) {
068                String text = list.getStringAt(row);
069                if ((text != null) && (text.length() > 0 )) {
070                    Matcher matcher = pattern.matcher(text);
071                    if (matcher.find()) {
072                        return createSearchResult(matcher, row, 0);
073                    }
074                }
075                return null;
076            }
077            
078            /**
079             * {@inheritDoc}
080             */
081            @Override
082            protected int getSize() {
083                return list.getElementCount();
084            }
085    
086            
087            /**
088             * {@inheritDoc}
089             */
090            @Override
091            public JXList getTarget() {
092                return list;
093            }
094    
095            /**
096             * {@inheritDoc}
097             */
098            @Override
099            protected void moveMatchMarker() {
100                if (markByHighlighter()) {
101                    moveMatchByHighlighter();
102                } else { // use selection
103                    moveMatchBySelection();
104                }
105            }
106            
107            protected void moveMatchBySelection() {
108              // PENDING JW: #718-swingx - don't move selection on not found
109              // complying here is accidental, defaultListSelectionModel doesn't
110              // clear on -1 but silently does nothing
111              // isn't doc'ed anywhere - so we back out
112                if (!hasMatch()) {
113                    return;
114                }
115                list.setSelectedIndex(lastSearchResult.foundRow);
116                list.ensureIndexIsVisible(lastSearchResult.foundRow);
117            }
118            
119    
120            /**
121             * use and move the match highlighter.
122             * PRE: markByHighlighter
123             *
124             */
125            protected void moveMatchByHighlighter() {
126                AbstractHighlighter searchHL = getConfiguredMatchHighlighter();
127                // no match
128                if (!hasMatch()) {
129                    return;
130                } else {
131                    ensureInsertedSearchHighlighters(searchHL);
132                    list.ensureIndexIsVisible(lastSearchResult.foundRow);
133                }
134            }
135    
136    
137    
138            /**
139             * @param searchHighlighter
140             */
141            @Override
142            protected void removeHighlighter(Highlighter searchHighlighter) {
143                list.removeHighlighter(searchHighlighter);
144            }
145    
146            /**
147             * @return all registered highlighters
148             */
149            @Override
150            protected Highlighter[] getHighlighters() {
151                return list.getHighlighters();
152            }
153    
154            /**
155             * @param highlighter
156             */
157            @Override
158            protected void addHighlighter(Highlighter highlighter) {
159                list.addHighlighter(highlighter);
160            }
161    
162        }