001 /*
002 * $Id: ConditionalHighlighter.java,v 1.11 2006/05/14 15:55:52 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
022 package org.jdesktop.swingx.decorator;
023
024 import java.awt.Color;
025 import java.awt.Component;
026
027 /**
028 * ConditionalHighlighter.
029 *
030 *
031 * @author Ramesh Gupta
032 */
033 public abstract class ConditionalHighlighter extends Highlighter {
034 protected int testColumn = 0; // always in model coordinates
035 protected int highlightColumn = -1; // always in model coordinates
036
037 // TODO JW ?? - changed from 255 to 256 to not be "on" by default...
038 protected int mask = 256;
039
040 public ConditionalHighlighter() {
041 // default constructor
042 }
043
044 /**
045 * <p>Constructs a <code>ConditionalHighlighter</code> instance with the
046 * specified background and foreground colors that will be used to highlight
047 * the renderer component for a cell in the specified highlightColumn of any
048 * row if and only if {@link #needsHighlight needsHighlight} returns true
049 * for the adapter that identifies that cell.</p>
050 *
051 * @param cellBackground background color for highlighted cells, or null, if
052 * background should not be changed
053 * @param cellForeground foreground color for highlighted cells, or null, if
054 * foreground should not be changed
055 * @param testColumn column whose value is to be tested to determine if a
056 * cell <em>should</em> be highlighted
057 * @param highlightColumn column whose index is used to determine if a cell
058 * <em>could</em> be highlighted; may be a valid column index in model
059 * coordinates, or -1 to indicate all columns
060 */
061 public ConditionalHighlighter(Color cellBackground, Color cellForeground,
062 int testColumn, int highlightColumn) {
063 super(cellBackground, cellForeground);
064 this.testColumn = testColumn;
065 this.highlightColumn = highlightColumn;
066 }
067
068 /**
069 * TODO: JW ??
070 */
071 public void setMask(int alpha) {
072 mask = alpha;
073 fireStateChanged();
074 }
075
076 /**
077 * TODO: JW ??
078 * @return mask
079 */
080 public int getMask() {
081 return mask;
082 }
083
084 /**
085 * Performs a conditional highlight. Calls {@link #doHighlight doHighlight} if
086 * and only if {@link #needsHighlight needsHighlight} returns true.
087 *
088 * @param renderer
089 * @param adapter
090 * @return the highlighted component
091 */
092 @Override
093 public Component highlight(Component renderer, ComponentAdapter adapter) {
094 if (needsHighlight(adapter)) {
095 return doHighlight(renderer, adapter);
096 }
097 else if (getMask() < 256) {
098 return doMask(renderer, adapter);
099 }
100 return renderer;
101 }
102
103 /**
104 * TODO: ??
105 *
106 * @param renderer
107 * @param adapter
108 * @return renderer
109 */
110 protected Component doMask(Component renderer, ComponentAdapter adapter) {
111
112 maskBackground(renderer, adapter);
113 maskForeground(renderer, adapter);
114 // and so on...
115
116 return renderer;
117 }
118
119 /**
120 * TODO: ??
121 */
122 protected void maskBackground(Component renderer, ComponentAdapter adapter) {
123 Color seed = renderer.getBackground();
124 Color color = adapter.isSelected() ? computeSelectedBackground(seed) : seed;
125 // fix issue#21-swingx: foreground of renderers can be null
126 if (color != null) {
127 renderer.setBackground(
128 new Color((getMask() << 24) | (color.getRGB() & 0x00FFFFFF), true));
129 }
130 }
131
132 /**
133 * TODO: ??
134 * @param renderer
135 * @param adapter
136 */
137 protected void maskForeground(Component renderer, ComponentAdapter adapter) {
138 Color seed = renderer.getForeground();
139 Color color = adapter.isSelected() ? computeSelectedForeground(seed) : seed;
140 // fix issue#21-swingx: foreground of renderers can be null
141 if (color != null) {
142 renderer.setForeground(
143 new Color((getMask() << 24) | (color.getRGB() & 0x00FFFFFF), true));
144
145 }
146 }
147
148 @Override
149 @Deprecated
150 protected Color computeSelectedForeground(Color seed) {
151 return getSelectedForeground() == null ?
152 seed == null ? null : seed.brighter() : getSelectedForeground();
153 }
154
155 public int getTestColumnIndex() {
156 return testColumn;
157 }
158
159 public void setTestColumnIndex(int columnIndex) {
160 this.testColumn = columnIndex;
161 fireStateChanged();
162 }
163
164 public int getHighlightColumnIndex() {
165 return highlightColumn;
166 }
167
168 public void setHighlightColumnIndex(int columnIndex) {
169 this.highlightColumn = columnIndex;
170 fireStateChanged();
171 }
172
173 /**
174 * Checks if the cell identified by the specified adapter is a potential
175 * candidate for highlighting, and returns true if so; otherwise, it returns false.
176 *
177 * @param adapter
178 * @return true if the cell identified by the specified adapter needs
179 * highlight; false otherwise
180 */
181 protected boolean needsHighlight(ComponentAdapter adapter) {
182 // Before running test(), quickly check if the cell in the current
183 // adapter is a potential candidate for highlighting. If so, run the test.
184 // highlightColumn is always in "model" coordinates, but adapter.column
185 // is in "view" coordinates. So, convert before comparing.
186 if ((highlightColumn < 0) ||
187 (highlightColumn == adapter.viewToModel(adapter.column))) {
188 return test(adapter);
189 }
190 return false; // cell is not a candidate for decoration;
191 }
192
193 /**
194 * Tests if the cell identified by the specified adapter should actually be
195 * highlighted, and returns true if so; otherwise, it returns false.
196 *
197 * @param adapter
198 * @return true if the test succeeds; false otherwise
199 */
200 protected abstract boolean test(ComponentAdapter adapter);
201
202 }