001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.jvnet.substance;
031:
032: import java.awt.*;
033:
034: import javax.swing.*;
035: import javax.swing.plaf.FontUIResource;
036: import javax.swing.plaf.TreeUI;
037: import javax.swing.tree.TreeCellRenderer;
038:
039: import org.jvnet.lafwidget.animation.FadeKind;
040: import org.jvnet.substance.SubstanceTreeUI.TreePathId;
041: import org.jvnet.substance.theme.SubstanceTheme;
042: import org.jvnet.substance.utils.*;
043:
044: /**
045: * Default renderer for tree cells.
046: *
047: * @author Kirill Grouchnikov
048: */
049: public class SubstanceDefaultTreeCellRenderer extends JLabel implements
050: TreeCellRenderer {
051: /** Last tree the renderer was painted in. */
052: private JTree tree;
053:
054: /** Is the value currently selected. */
055: protected boolean selected;
056:
057: /** True if has focus. */
058: protected boolean hasFocus;
059:
060: /**
061: * Returns a new instance of SubstanceDefaultTreeCellRenderer. Alignment is
062: * set to left aligned. Icons and text color are determined from the
063: * UIManager.
064: */
065: public SubstanceDefaultTreeCellRenderer() {
066: this .setHorizontalAlignment(SwingConstants.LEFT);
067: // this.setBorder(new EmptyBorder(1, 1, 1, 1));
068: }
069:
070: /**
071: * Returns the default icon that is used to represent non-leaf nodes that
072: * are expanded.
073: *
074: * @return The default icon for non-leaf expanded nodes.
075: */
076: public Icon getDefaultOpenIcon() {
077: return UIManager.getIcon("Tree.openIcon");
078: }
079:
080: /**
081: * Returns the default icon that is used to represent non-leaf nodes that
082: * are not expanded.
083: *
084: * @return The default icon for non-leaf non-expanded nodes.
085: */
086: public Icon getDefaultClosedIcon() {
087: return UIManager.getIcon("Tree.closedIcon");
088: }
089:
090: /**
091: * Returns the default icon that is used to represent leaf nodes.
092: *
093: * @return The default icon for leaf nodes.
094: */
095: public Icon getDefaultLeafIcon() {
096: return UIManager.getIcon("Tree.leafIcon");
097: }
098:
099: /**
100: * Subclassed to map <code>FontUIResource</code>s to null. If
101: * <code>font</code> is null, or a <code>FontUIResource</code>, this
102: * has the effect of letting the font of the JTree show through. On the
103: * other hand, if <code>font</code> is non-null, and not a
104: * <code>FontUIResource</code>, the font becomes <code>font</code>.
105: */
106: @Override
107: public void setFont(Font font) {
108: if (font instanceof FontUIResource)
109: font = null;
110: super .setFont(font);
111: }
112:
113: /**
114: * Gets the font of this component.
115: *
116: * @return this component's font; if a font has not been set for this
117: * component, the font of its parent is returned
118: */
119: @Override
120: public Font getFont() {
121: Font font = super .getFont();
122:
123: if ((font == null) && (this .tree != null)) {
124: // Strive to return a non-null value, otherwise the html support
125: // will typically pick up the wrong font in certain situations.
126: font = this .tree.getFont();
127: }
128: return font;
129: }
130:
131: // /**
132: // * Subclassed to map <code>ColorUIResource</code>s to null. If
133: // * <code>color</code> is null, or a <code>ColorUIResource</code>, this
134: // * has the effect of letting the background color of the JTree show
135: // through.
136: // * On the other hand, if <code>color</code> is non-null, and not a
137: // * <code>ColorUIResource</code>, the background becomes
138: // * <code>color</code>.
139: // */
140: // @Override
141: // public void setBackground(Color color) {
142: // if (color instanceof ColorUIResource)
143: // color = null;
144: // super.setBackground(color);
145: // }
146: //
147: /**
148: * Configures the renderer based on the passed in components. The value is
149: * set from messaging the tree with <code>convertValueToText</code>,
150: * which ultimately invokes <code>toString</code> on <code>value</code>.
151: * The foreground color is set based on the selection and the icon is set
152: * based on on leaf and expanded.
153: */
154: public Component getTreeCellRendererComponent(JTree tree,
155: Object value, boolean sel, boolean expanded, boolean leaf,
156: int row, boolean hasFocus) {
157: String stringValue = tree.convertValueToText(value, sel,
158: expanded, leaf, row, hasFocus);
159:
160: this .tree = tree;
161: this .hasFocus = hasFocus;
162: this .setText(stringValue);
163:
164: TreeUI treeUI = tree.getUI();
165: if (treeUI instanceof SubstanceTreeUI) {
166: SubstanceTreeUI ui = (SubstanceTreeUI) treeUI;
167: TreePathId pathId = new TreePathId(tree.getPathForRow(row));
168: ComponentState state = ui.getPathState(pathId);
169: ComponentState prevState = ui.getPrevPathState(pathId);
170: SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
171: tree, state);
172: Color color = SubstanceCoreUtilities
173: .getInterpolatedForegroundColor(tree, pathId,
174: theme, state, prevState,
175: FadeKind.SELECTION, FadeKind.ROLLOVER);
176:
177: // System.out.println("[" + row + "," + column + "] - "
178: // + prevState.name() + ":" + state.name() + ":" + color);
179:
180: super .setForeground(color);
181: } else {
182: if (sel)
183: this .setForeground(UIManager
184: .getColor("Tree.selectionForeground"));
185: else
186: this .setForeground(UIManager
187: .getColor("Tree.textForeground"));
188: }
189:
190: SubstanceCoreUtilities.applyStripedBackground(tree, row, this );
191:
192: // There needs to be a way to specify disabled icons.
193: if (!tree.isEnabled()) {
194: this .setEnabled(false);
195: if (leaf) {
196: this .setDisabledIcon(SubstanceImageCreator
197: .toGreyscale(SubstanceImageCreator
198: .makeTransparent(tree, this
199: .getDefaultLeafIcon(), 0.5)));
200: } else if (expanded) {
201: this .setDisabledIcon(SubstanceImageCreator
202: .toGreyscale(SubstanceImageCreator
203: .makeTransparent(tree, this
204: .getDefaultOpenIcon(), 0.5)));
205: // setIcon(SubstanceImageCreator.toGreyscale(SubstanceImageCreator
206: // .makeTransparent(getDefaultOpenIcon(), 0.5)));
207: } else {
208: this .setDisabledIcon(SubstanceImageCreator
209: .toGreyscale(SubstanceImageCreator
210: .makeTransparent(tree, this
211: .getDefaultClosedIcon(), 0.5)));
212: // setIcon(SubstanceImageCreator.toGreyscale(SubstanceImageCreator
213: // .makeTransparent(getDefaultClosedIcon(), 0.5)));
214: }
215: } else {
216: this .setEnabled(true);
217: if (leaf) {
218: this .setIcon(this .getDefaultLeafIcon());
219: } else if (expanded) {
220: this .setIcon(this .getDefaultOpenIcon());
221: } else {
222: this .setIcon(this .getDefaultClosedIcon());
223: }
224: }
225: this .setComponentOrientation(tree.getComponentOrientation());
226:
227: this .setOpaque(false);
228:
229: this .selected = sel;
230:
231: return this ;
232: }
233:
234: /**
235: * Overrides <code>JComponent.getPreferredSize</code> to return slightly
236: * wider preferred size value.
237: */
238: @Override
239: public Dimension getPreferredSize() {
240: Dimension retDimension = super .getPreferredSize();
241:
242: if (retDimension != null)
243: retDimension = new Dimension(retDimension.width + 3,
244: retDimension.height);
245: return retDimension;
246: }
247:
248: /**
249: * Overridden for performance reasons. See the <a
250: * href="#override">Implementation Note</a> for more information.
251: */
252: @Override
253: public void validate() {
254: }
255:
256: /**
257: * Overridden for performance reasons. See the <a
258: * href="#override">Implementation Note</a> for more information.
259: *
260: * @since 1.5
261: */
262: @Override
263: public void invalidate() {
264: }
265:
266: /**
267: * Overridden for performance reasons. See the <a
268: * href="#override">Implementation Note</a> for more information.
269: */
270: @Override
271: public void revalidate() {
272: }
273:
274: /**
275: * Overridden for performance reasons. See the <a
276: * href="#override">Implementation Note</a> for more information.
277: */
278: @Override
279: public void repaint(long tm, int x, int y, int width, int height) {
280: }
281:
282: /**
283: * Overridden for performance reasons. See the <a
284: * href="#override">Implementation Note</a> for more information.
285: */
286: @Override
287: public void repaint(Rectangle r) {
288: }
289:
290: /**
291: * Overridden for performance reasons. See the <a
292: * href="#override">Implementation Note</a> for more information.
293: *
294: * @since 1.5
295: */
296: @Override
297: public void repaint() {
298: }
299:
300: /**
301: * Overridden for performance reasons. See the <a
302: * href="#override">Implementation Note</a> for more information.
303: */
304: @Override
305: protected void firePropertyChange(String propertyName,
306: Object oldValue, Object newValue) {
307: // Strings get interned...
308: if (propertyName == "text")
309: super .firePropertyChange(propertyName, oldValue, newValue);
310: }
311:
312: /**
313: * Overridden for performance reasons. See the <a
314: * href="#override">Implementation Note</a> for more information.
315: */
316: @Override
317: public void firePropertyChange(String propertyName, byte oldValue,
318: byte newValue) {
319: }
320:
321: /**
322: * Overridden for performance reasons. See the <a
323: * href="#override">Implementation Note</a> for more information.
324: */
325: @Override
326: public void firePropertyChange(String propertyName, char oldValue,
327: char newValue) {
328: }
329:
330: /**
331: * Overridden for performance reasons. See the <a
332: * href="#override">Implementation Note</a> for more information.
333: */
334: @Override
335: public void firePropertyChange(String propertyName, short oldValue,
336: short newValue) {
337: }
338:
339: /**
340: * Overridden for performance reasons. See the <a
341: * href="#override">Implementation Note</a> for more information.
342: */
343: @Override
344: public void firePropertyChange(String propertyName, int oldValue,
345: int newValue) {
346: }
347:
348: /**
349: * Overridden for performance reasons. See the <a
350: * href="#override">Implementation Note</a> for more information.
351: */
352: @Override
353: public void firePropertyChange(String propertyName, long oldValue,
354: long newValue) {
355: }
356:
357: /**
358: * Overridden for performance reasons. See the <a
359: * href="#override">Implementation Note</a> for more information.
360: */
361: @Override
362: public void firePropertyChange(String propertyName, float oldValue,
363: float newValue) {
364: }
365:
366: /**
367: * Overridden for performance reasons. See the <a
368: * href="#override">Implementation Note</a> for more information.
369: */
370: @Override
371: public void firePropertyChange(String propertyName,
372: double oldValue, double newValue) {
373: }
374:
375: /**
376: * Overridden for performance reasons. See the <a
377: * href="#override">Implementation Note</a> for more information.
378: */
379: @Override
380: public void firePropertyChange(String propertyName,
381: boolean oldValue, boolean newValue) {
382: }
383:
384: }
|