001: /*
002: * $Id: ConditionalHighlighter.java,v 1.13 2006/07/21 09:38:27 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.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,
062: Color cellForeground, 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,
094: ComponentAdapter adapter) {
095: if (needsHighlight(adapter)) {
096: return doHighlight(renderer, adapter);
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,
111: ComponentAdapter adapter) {
112:
113: maskBackground(renderer, adapter);
114: maskForeground(renderer, adapter);
115: // and so on...
116:
117: return renderer;
118: }
119:
120: /**
121: * TODO: ??
122: */
123: protected void maskBackground(Component renderer,
124: ComponentAdapter adapter) {
125: Color seed = renderer.getBackground();
126: Color color = adapter.isSelected() ? computeSelectedBackground(seed)
127: : seed;
128: // fix issue#21-swingx: foreground of renderers can be null
129: if (color != null) {
130: renderer.setBackground(new Color((getMask() << 24)
131: | (color.getRGB() & 0x00FFFFFF), true));
132: }
133: }
134:
135: /**
136: * TODO: ??
137: * @param renderer
138: * @param adapter
139: */
140: protected void maskForeground(Component renderer,
141: ComponentAdapter adapter) {
142: Color seed = renderer.getForeground();
143: Color color = adapter.isSelected() ? computeSelectedForeground(seed)
144: : seed;
145: // fix issue#21-swingx: foreground of renderers can be null
146: if (color != null) {
147: renderer.setForeground(new Color((getMask() << 24)
148: | (color.getRGB() & 0x00FFFFFF), true));
149:
150: }
151: }
152:
153: @Override
154: @Deprecated
155: protected Color computeSelectedForeground(Color seed) {
156: return getSelectedForeground() == null ? seed == null ? null
157: : seed.brighter() : getSelectedForeground();
158: }
159:
160: //------ following methods are the core of the "conditional" notion
161:
162: /**
163: * Returns the index of the column to use for deciding
164: * if the highlight should be on.
165: *
166: * @return the index of the column to use for deciding about highlighting.
167: * The index is in model coordinates, -1 denotes any column.
168: *
169: * @see #setTestColumnIndex(int)
170: *
171: */
172: public int getTestColumnIndex() {
173: return testColumn;
174: }
175:
176: /**
177: * Sets the index of the column to use for deciding
178: * if the highlight should be on.
179: *
180: * @param columnIndex index of the column to used for deciding about highlighting.
181: * The index is in model coordinates, -1 denotes any column.
182: */
183: public void setTestColumnIndex(int columnIndex) {
184: this .testColumn = columnIndex;
185: fireStateChanged();
186: }
187:
188: /**
189: * Returns the index of the column to highlight if the
190: * condition is met.
191: *
192: * @return the index of the column to highlight.
193: * The index is in model coordinates, -1 denotes any column.
194: *
195: * @see #setHighlightColumnIndex(int)
196: *
197: */
198: public int getHighlightColumnIndex() {
199: return highlightColumn;
200: }
201:
202: /**
203: * Sets the index of the column to highlight if the
204: * condition is met.
205: *
206: * @param columnIndex index of the column to highlight.
207: * The index is in model coordinates, -1 denotes every column.
208: *
209: */
210: public void setHighlightColumnIndex(int columnIndex) {
211: this .highlightColumn = columnIndex;
212: fireStateChanged();
213: }
214:
215: /**
216: * Checks if the cell identified by the specified adapter is a potential
217: * candidate for highlighting, and returns true if so; otherwise, it returns false.
218: *
219: * @param adapter
220: * @return true if the cell identified by the specified adapter needs
221: * highlight; false otherwise
222: */
223: protected boolean needsHighlight(ComponentAdapter adapter) {
224: // Before running test(), quickly check if the cell in the current
225: // adapter is a potential candidate for highlighting. If so, run the test.
226: // highlightColumn is always in "model" coordinates, but adapter.column
227: // is in "view" coordinates. So, convert before comparing.
228: if ((highlightColumn < 0)
229: || (highlightColumn == adapter
230: .viewToModel(adapter.column))) {
231: return test(adapter);
232: }
233: return false; // cell is not a candidate for decoration;
234: }
235:
236: /**
237: * Tests if the cell identified by the specified adapter should actually be
238: * highlighted, and returns true if so; otherwise, it returns false.
239: *
240: * @param adapter
241: * @return true if the test succeeds; false otherwise
242: */
243: protected abstract boolean test(ComponentAdapter adapter);
244:
245: }
|