001    /*
002     * $Id: PatternHighlighter.java,v 1.7 2005/10/26 14:30:00 kleopatra 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    
022    package org.jdesktop.swingx.decorator;
023    
024    import java.awt.Color;
025    import java.util.regex.Pattern;
026    import java.util.regex.PatternSyntaxException;
027    
028    /**
029     * PatternHighlighter
030     * 
031     * @author Ramesh Gupta
032     */
033    public class PatternHighlighter extends ConditionalHighlighter implements
034            PatternMatcher {
035    
036        protected Pattern pattern = null;
037    
038        /**
039         * Constructs a <code>PatternHighlighter</code> instance with no
040         * background or foreground color and no pattern
041         */
042        public PatternHighlighter() {
043            // default constructor
044            this(null, null, null, 0, 0); // match flags = 0; test column = 0
045        }
046    
047        /**
048         * <p>
049         * Constructs a <code>PatternHighlighter</code> instance with the
050         * specified background and foreground colors that will be used to decorate
051         * the renderer component for all cell in a row if and only if the specified
052         * regExString defines a valid {@link java.util.regex.Pattern}, and the
053         * value of the cell in the specified testColumn of that row matches that
054         * pattern.
055         * </p>
056         * 
057         * @param background
058         *            background color for decorated cells, or null, if background
059         *            should not be changed
060         * @param foreground
061         *            foreground color for decorated cells, or null, if foreground
062         *            should not be changed
063         * @param regExString
064         *            the regular expression string to compile, or null to leave the
065         *            pattern undefined
066         * @param testColumn
067         *            column to which the pattern matching test is applied; must be
068         *            a valid column index in model coordinates
069         * @throws java.util.regex.PatternSyntaxException
070         *             if regExString is not null, but it does not define a valid
071         *             {@link java.util.regex.Pattern}
072         * @see java.util.regex.Pattern
073         */
074        public PatternHighlighter(Color background, Color foreground,
075                String regExString, int matchFlags, int testColumn)
076                throws PatternSyntaxException {
077            this(background, foreground, regExString, matchFlags, testColumn, -1);
078        }
079    
080        /**
081         * <p>
082         * Constructs a <code>PatternHighlighter</code> instance with the
083         * specified background and foreground colors that will be used to decorate
084         * the renderer component for a cell in the specified decorateColumn of any
085         * row if and only if the specified regExString and matchFlags define a
086         * valid {@link java.util.regex.Pattern}, and the value of the cell in the
087         * specified testColumn of the same row matches that pattern.
088         * </p>
089         * 
090         * @param background
091         *            background color for decorated cells, or null, if background
092         *            should not be changed
093         * @param foreground
094         *            foreground color for decorated cells, or null, if foreground
095         *            should not be changed
096         * @param regExString
097         *            the regular expression string to compile, or null to leave the
098         *            pattern undefined
099         * @param matchFlags
100         *            a bit mask that may include
101         *            {@link java.util.regex.Pattern#CASE_INSENSITIVE},
102         *            {@link java.util.regex.Pattern#MULTILINE},
103         *            {@link java.util.regex.Pattern#DOTALL},
104         *            {@link java.util.regex.Pattern#UNICODE_CASE}, and
105         *            {@link java.util.regex.Pattern#CANON_EQ}
106         * @param testColumn
107         *            column to which the pattern matching test is applied; must be
108         *            a valid column index in model coordinates
109         * @param decorateColumn
110         *            column to which decorator attributes will be applied; may be a
111         *            valid column index in model coordinates, or -1 to indicate all
112         *            columns
113         * @throws java.util.regex.PatternSyntaxException
114         *             if regExString is not null, but regExString and matchFlags do
115         *             not define a valid {@link java.util.regex.Pattern}
116         * @see java.util.regex.Pattern
117         */
118        public PatternHighlighter(Color background, Color foreground,
119                String regExString, int matchFlags, int testColumn,
120                int decorateColumn) throws PatternSyntaxException {
121            super(background, foreground, testColumn, decorateColumn);
122            setPattern(regExString, matchFlags);
123        }
124    
125        /**
126         * Tests whether the string representation of the value of the cell
127         * identified by the specified adapter matches the pattern, if any, that is
128         * set for this <code>PatternHighlighter</code>, and returns true if the
129         * test succeeds; Otherwise, it returns false.
130         * 
131         * @param adapter
132         *            the current cell rendering adapter
133         * @return true if the test succeeds; false otherwise
134         */
135        protected boolean test(ComponentAdapter adapter) {
136            if (pattern == null) {
137                return false;
138            }
139    
140            if (!adapter.isTestable(testColumn))
141                return false;
142            Object value = adapter.getFilteredValueAt(adapter.row, testColumn);
143    
144            if (value == null) {
145                return false;
146            } else {
147                boolean matches = pattern.matcher(value.toString()).find();
148                return matches;
149            }
150        }
151    
152        /**
153         * Returns the pattern used by this cell decorator for matching against a
154         * cell's value to determine if the conditions for cell decoration are met.
155         * 
156         * @return the pattern used by this cell decorator for matching
157         * @see java.util.regex.Pattern
158         */
159        public Pattern getPattern() {
160            return pattern;
161        }
162    
163        public void setPattern(String regularExpr, int matchFlags) {
164            if ((regularExpr == null) || (regularExpr.length() == 0)) {
165                regularExpr = ".*";
166            }
167            setPattern(Pattern.compile(regularExpr, matchFlags));
168        }
169    
170        /**
171         * Sets the pattern used by this cell decorator to match against a cell's
172         * value to determine if the conditions for cell decoration are met.
173         * 
174         * @param pattern
175         *            the pattern used by this cell decorator for matching
176         * @see java.util.regex.Pattern
177         */
178        public void setPattern(Pattern pattern) {
179            this.pattern = pattern;
180            fireStateChanged();
181        }
182    
183    }