001    /*
002     * $Id: SearchHighlighter.java,v 1.9 2006/05/14 15:55:53 dmouse Exp $
003     *
004     * Copyright 2004 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.decorator;
022    
023    import java.awt.Color;
024    import java.awt.Component;
025    import java.util.regex.Pattern;
026    
027    /**
028     * Convenience Highlighter to test and highlight cells in searching.
029     *  
030     * @author Jeanette Winzenburg
031     */
032    public class SearchHighlighter extends PatternHighlighter {
033        /** the row to highlight in view coordinates. -1 means all */
034        int highlightRow;
035        private boolean enableHighlight;
036        private static final String ALL = ".*";
037        
038        /**
039         * Instantiates a default SearchHighlighter. 
040         * The default colors are Yellow background and null foreground.
041         * The default matching state is 
042         *  Pattern == null, flags = 0, tests all columns and all rows.
043         * 
044         */
045        public SearchHighlighter() {
046            this(Color.YELLOW.brighter(), null);
047        }
048        
049        /**
050         * Instantiates a default SearchHighlighter with background/foreground colors.
051         * The default matching state is 
052         *  Pattern == null, flags = 0, tests all columns and all rows.
053         * 
054         * @param background color of hightlight background
055         * @param foreground color of highlight foreground
056         */
057        public SearchHighlighter(Color background, Color foreground) {
058            super(background, foreground, null, 0, -1);
059            setHighlightRow(-1);
060        }
061    
062        /**
063         * Toggle to enable/disable - if disabled never hightlights.
064         * 
065         * @param enableHighlight
066         */
067        public void setEnabled(boolean enableHighlight) {
068            this.enableHighlight = enableHighlight;
069            fireStateChanged();
070        }
071        
072        protected boolean needsHighlight(ComponentAdapter adapter) {
073            if (!isEnabled()) return false;
074            if (highlightRow >= 0 && (adapter.row != highlightRow)) {
075                return false;
076            }
077            return super.needsHighlight(adapter);
078        }
079    
080        private boolean isEnabled() {
081            Pattern pattern = getPattern();
082            if (pattern == null || ALL.equals(pattern.pattern())) {
083                return false;
084            }
085            return enableHighlight;
086        }
087    
088        protected boolean test(ComponentAdapter adapter) {
089            if (pattern == null) {
090                return false;
091            }
092            int columnToTest = testColumn;
093            // use one highlighter for all columns
094            if (columnToTest < 0) {
095                columnToTest = adapter.viewToModel(adapter.column);
096            }
097            Object  value = adapter.getFilteredValueAt(adapter.row, columnToTest);
098            if (value == null) {
099                return false;
100            }
101            else {
102                return pattern.matcher(value.toString()).find();
103            }
104        }
105    
106        
107        /**
108         * <p>Computes a suitable selected background for the renderer component within the
109         * specified adapter and returns the computed color. 
110         * 
111         * This implementation returns super if != null, 
112         * otherwise returns computeUnselectedBackground. The reason is to always 
113         * show a match marker even if no selection specific colors are set. 
114         * 
115         *  PENDING: move up to ConditionalHighlighter?
116         * 
117         * @param renderer
118         * @param adapter
119         * @return
120         * 
121         */
122        @Override
123        protected Color computeSelectedBackground(Component renderer, ComponentAdapter adapter) {
124            Color color = super.computeSelectedBackground(renderer, adapter);
125            return color != null ? color : computeUnselectedBackground(renderer, adapter);
126        }
127    
128        /** set the row to match in test. 
129         * - 1 means all.
130         * @param row
131         */
132        public void setHighlightRow(int row) {
133            highlightRow = row;
134            fireStateChanged();
135        }
136    
137        /** 
138         * convenience method to test and highlight all rows/columns and 
139         * enable.
140         *
141         */
142        public void setHighlightAll() {
143            setHighlightCell(-1, -1);
144            
145        }
146    
147        /**
148         * Set's highlightRow to row, test- and highlight column = column
149         * @param row
150         * @param modelColumn
151         */
152        public void setHighlightCell(int row, int modelColumn) {
153            this.testColumn = modelColumn;
154            this.highlightColumn = modelColumn;
155            this.highlightRow = row;
156            setEnabled(true);
157        }
158    
159    }