0001: /*
0002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * o Redistributions of source code must retain the above copyright notice,
0008: * this list of conditions and the following disclaimer.
0009: *
0010: * o Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
0015: * its contributors may be used to endorse or promote products derived
0016: * from this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
0025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: */
0030: package org.jvnet.substance;
0031:
0032: import java.awt.*;
0033: import java.awt.event.*;
0034: import java.beans.PropertyChangeEvent;
0035: import java.beans.PropertyChangeListener;
0036: import java.util.*;
0037:
0038: import javax.swing.*;
0039: import javax.swing.event.TreeSelectionEvent;
0040: import javax.swing.event.TreeSelectionListener;
0041: import javax.swing.plaf.ComponentUI;
0042: import javax.swing.plaf.IconUIResource;
0043: import javax.swing.plaf.basic.BasicTreeUI;
0044: import javax.swing.tree.*;
0045:
0046: import org.jvnet.lafwidget.animation.*;
0047: import org.jvnet.lafwidget.layout.TransitionLayout;
0048: import org.jvnet.lafwidget.utils.LookUtils;
0049: import org.jvnet.substance.painter.highlight.SubstanceHighlightUtils;
0050: import org.jvnet.substance.painter.text.SubstanceTextPainter;
0051: import org.jvnet.substance.theme.SubstanceTheme;
0052: import org.jvnet.substance.utils.*;
0053: import org.jvnet.substance.utils.icon.SubstanceIconFactory;
0054:
0055: /**
0056: * UI for lists in <b>Substance</b> look and feel.
0057: *
0058: * @author Kirill Grouchnikov
0059: */
0060: public class SubstanceTreeUI extends BasicTreeUI {
0061: /**
0062: * Holds the list of currently selected paths.
0063: */
0064: protected Map<TreePathId, Object> selectedPaths;
0065:
0066: /**
0067: * Holds the currently rolled-over path or <code>null</code> if none such.
0068: */
0069: protected TreePathId currRolloverPathId;
0070:
0071: /**
0072: * Delegate for painting the background of list rows.
0073: */
0074: private static SubstanceFillBackgroundDelegate backgroundDelegate = new SubstanceFillBackgroundDelegate();
0075:
0076: /**
0077: * Listener that listens to changes on tree properties.
0078: */
0079: protected PropertyChangeListener substancePropertyChangeListener;
0080:
0081: /**
0082: * Listener for selection animations.
0083: */
0084: protected TreeSelectionListener substanceSelectionFadeListener;
0085:
0086: /**
0087: * Listener for fade animations on tree rollovers.
0088: */
0089: protected RolloverFadeListener substanceFadeRolloverListener;
0090:
0091: /**
0092: * Listener for selection of an entire row.
0093: */
0094: protected MouseListener substanceRowSelectionListener;
0095:
0096: /**
0097: * If <code>true</code>, the mouse pointer is in the bounds of the
0098: * associated tree.
0099: */
0100: private boolean isInside = false;
0101:
0102: /**
0103: * Map of previous fade states (for state-aware theme transitions).
0104: */
0105: private Map<TreePathId, ComponentState> prevStateMap;
0106:
0107: /**
0108: * Map of next fade states (for state-aware theme transitions).
0109: */
0110: private Map<TreePathId, ComponentState> nextStateMap;
0111:
0112: /*
0113: * (non-Javadoc)
0114: *
0115: * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
0116: */
0117: public static ComponentUI createUI(JComponent tree) {
0118: return new SubstanceTreeUI();
0119: }
0120:
0121: /**
0122: * Creates a UI delegate for tree.
0123: */
0124: public SubstanceTreeUI() {
0125: super ();
0126: this .selectedPaths = new HashMap<TreePathId, Object>();
0127: this .prevStateMap = new HashMap<TreePathId, ComponentState>();
0128: this .nextStateMap = new HashMap<TreePathId, ComponentState>();
0129: }
0130:
0131: /*
0132: * (non-Javadoc)
0133: *
0134: * @see javax.swing.plaf.basic.BasicTreeUI#installDefaults()
0135: */
0136: @Override
0137: protected void installDefaults() {
0138: super .installDefaults();
0139: if (SubstanceCoreUtilities.toBleedWatermark(this .tree))
0140: this .tree.setOpaque(false);
0141:
0142: if (this .tree.getSelectionPaths() != null) {
0143: for (TreePath selectionPath : this .tree.getSelectionPaths()) {
0144: TreePathId pathId = new TreePathId(selectionPath);
0145: selectedPaths.put(pathId, selectionPath
0146: .getLastPathComponent());
0147: prevStateMap.put(pathId, ComponentState.SELECTED);
0148: }
0149: }
0150:
0151: setExpandedIcon(new IconUIResource(SubstanceIconFactory
0152: .getTreeIcon(this .tree, false)));
0153: setCollapsedIcon(new IconUIResource(SubstanceIconFactory
0154: .getTreeIcon(this .tree, true)));
0155: }
0156:
0157: /*
0158: * (non-Javadoc)
0159: *
0160: * @see javax.swing.plaf.basic.BasicTreeUI#uninstallDefaults()
0161: */
0162: @Override
0163: protected void uninstallDefaults() {
0164: this .selectedPaths.clear();
0165: super .uninstallDefaults();
0166: }
0167:
0168: /*
0169: * (non-Javadoc)
0170: *
0171: * @see javax.swing.plaf.basic.BasicTreeUI#paintRow(java.awt.Graphics,
0172: * java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0173: * javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0174: */
0175: @Override
0176: protected void paintRow(Graphics g, Rectangle clipBounds,
0177: Insets insets, Rectangle bounds, TreePath path, int row,
0178: boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
0179: // Don't paint the renderer if editing this row.
0180: if ((this .editingComponent != null) && (this .editingRow == row))
0181: return;
0182:
0183: int leadIndex;
0184:
0185: if (this .tree.hasFocus()) {
0186: TreePath leadPath = this .tree.getLeadSelectionPath();
0187: leadIndex = this .getRowForPath(this .tree, leadPath);
0188: } else {
0189: leadIndex = -1;
0190: }
0191:
0192: final Component renderer = this .currentCellRenderer
0193: .getTreeCellRendererComponent(this .tree, path
0194: .getLastPathComponent(), this .tree
0195: .isRowSelected(row), isExpanded, isLeaf, row,
0196: (leadIndex == row));
0197:
0198: // // second part - fix for defect 214 (rollover effects on non-opaque
0199: // // trees resulted in inconsistent behaviour)
0200: // boolean isWatermarkBleed = SubstanceCoreUtilities
0201: // .toBleedWatermark(tree)
0202: // || !tree.isOpaque();
0203:
0204: TreePathId pathId = new TreePathId(path);
0205:
0206: // Respect the current composite set on the graphics - for
0207: // JXPanel alpha channel
0208: float currFactor = 1.0f;
0209: Composite currComposite = ((Graphics2D) g).getComposite();
0210: if (currComposite instanceof AlphaComposite) {
0211: AlphaComposite ac = (AlphaComposite) currComposite;
0212: if (ac.getRule() == AlphaComposite.SRC_OVER)
0213: currFactor = ac.getAlpha();
0214: }
0215:
0216: Graphics2D g2d = (Graphics2D) g.create();
0217: // fix for issue 183 - passing the original Graphics context
0218: // to compute the alpha composite. If the tree is in a JXPanel
0219: // (component from SwingX) and it has custom alpha value set,
0220: // then the original graphics context will have a SRC_OVER
0221: // alpha composite applied to it.
0222: g2d.setComposite(TransitionLayout.getAlphaComposite(this .tree,
0223: currFactor));
0224:
0225: Color background = renderer.getBackground();
0226: if (background == null)
0227: background = tree.getBackground();
0228:
0229: final ComponentState prevState = this .getPrevPathState(pathId);
0230: final ComponentState currState = this .getPathState(pathId);
0231:
0232: final SubstanceTheme prevTheme = SubstanceThemeUtilities
0233: .getHighlightTheme(tree, prevState);
0234: final SubstanceTheme currTheme = SubstanceThemeUtilities
0235: .getHighlightTheme(tree, currState);
0236:
0237: // Compute the alpha values for the animation.
0238: float startAlpha = SubstanceThemeUtilities.getHighlightAlpha(
0239: this .tree, prevState);
0240: float endAlpha = SubstanceThemeUtilities.getHighlightAlpha(
0241: this .tree, currState);
0242:
0243: FadeState state = SubstanceFadeUtilities.getFadeState(
0244: this .tree, pathId, FadeKind.SELECTION,
0245: FadeKind.ROLLOVER);
0246: float totalAlpha = endAlpha;
0247: float fadeCoef = 0.0f;
0248: if (state != null) {
0249: fadeCoef = state.getFadePosition();
0250:
0251: // compute the total alpha of the overlays.
0252: if (state.isFadingIn()) {
0253: totalAlpha = startAlpha + (endAlpha - startAlpha)
0254: * fadeCoef / 10.0f;
0255: } else {
0256: totalAlpha = startAlpha + (endAlpha - startAlpha)
0257: * (10.0f - fadeCoef) / 10.0f;
0258: }
0259:
0260: if (state.isFadingIn())
0261: fadeCoef = 10.0f - fadeCoef;
0262: }
0263:
0264: // System.out.println(row + ":" + prevTheme.getDisplayName() + "["
0265: // + alphaForPrevBackground + "]:" + currTheme.getDisplayName()
0266: // + "[" + alphaForCurrBackground + "]");
0267:
0268: // The DefaultTreeCellRenderer overrides the isOpaque method
0269: // so that there is no point in trying to make it non-opaque.
0270: // Fix for defect 181.
0271: final boolean canHaveSubstanceEffects = !(renderer instanceof DefaultTreeCellRenderer);
0272: SubstanceTextPainter textPainter = SubstanceLookAndFeel
0273: .getCurrentTextPainter();
0274: if (canHaveSubstanceEffects && (totalAlpha > 0.0f)) {
0275: g2d.setComposite(TransitionLayout.getAlphaComposite(
0276: this .tree, currFactor * totalAlpha, g));
0277: // Fix for defect 180 - painting the
0278: // highlight beneath the entire row
0279: SubstanceHighlightUtils.paintHighlight(g2d, renderer,
0280: new Rectangle(this .tree.getInsets().left, bounds.y,
0281: this .tree.getWidth()
0282: - this .tree.getInsets().right
0283: - this .tree.getInsets().left,
0284: bounds.height), 0.8f, null, currTheme
0285: .getColorScheme(), prevTheme
0286: .getColorScheme(), fadeCoef);
0287: g2d.setComposite(TransitionLayout.getAlphaComposite(
0288: this .tree, currFactor));
0289: }
0290:
0291: // System.out.println("Painting row " + row);
0292: final boolean isWatermarkBleed = SubstanceCoreUtilities
0293: .toBleedWatermark(this .tree);
0294: if (textPainter.needsBackgroundImage()) {
0295: final float finalTotalAlpha = totalAlpha;
0296: final float finalCurrFactor = currFactor;
0297: final float finalFadeCoef = fadeCoef;
0298: final Rectangle cellRect = new Rectangle(this .tree
0299: .getInsets().left
0300: - bounds.x, 0, this .tree.getWidth()
0301: - this .tree.getInsets().right
0302: - this .tree.getInsets().left, bounds.height);
0303: textPainter.init(this .tree, cellRect, true);
0304: textPainter.setBackgroundFill(this .tree, background, true,
0305: bounds.x, bounds.y);
0306:
0307: textPainter
0308: .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
0309: public void paintBackground(Graphics g) {
0310: Graphics2D g2d = (Graphics2D) g.create();
0311: if (!isWatermarkBleed) {
0312: // fill with the renderer
0313: // background color
0314: g2d.setColor(renderer.getBackground());
0315: g2d.fillRect(0, 0, cellRect.width,
0316: cellRect.height);
0317: } else {
0318: backgroundDelegate.fillAndWatermark(
0319: g2d, tree, renderer
0320: .getBackground(),
0321: cellRect);
0322: }
0323: g2d.dispose();
0324: }
0325: });
0326:
0327: textPainter
0328: .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
0329: public void paintBackground(Graphics g) {
0330: Graphics2D g2d = (Graphics2D) g.create();
0331: if (canHaveSubstanceEffects
0332: && (finalTotalAlpha > 0.0f)) {
0333: g2d
0334: .setComposite(TransitionLayout
0335: .getAlphaComposite(
0336: tree,
0337: finalCurrFactor
0338: * finalTotalAlpha,
0339: g));
0340: // Fix for defect 180 - painting the
0341: // highlight beneath the entire row
0342: SubstanceHighlightUtils.paintHighlight(
0343: g2d, renderer, cellRect, 0.8f,
0344: null, currTheme
0345: .getColorScheme(),
0346: prevTheme.getColorScheme(),
0347: finalFadeCoef);
0348: g2d.setComposite(TransitionLayout
0349: .getAlphaComposite(tree,
0350: finalCurrFactor));
0351: }
0352: }
0353: });
0354: } else {
0355: }
0356:
0357: this .tree.putClientProperty(
0358: SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND,
0359: Boolean.TRUE);
0360: if (renderer instanceof JComponent) {
0361: // Play with opacity to make our own gradient background
0362: // on selected elements to show.
0363: JComponent jRenderer = (JComponent) renderer;
0364: synchronized (jRenderer) {
0365: boolean newOpaque = !this .tree.isRowSelected(row);
0366: if (SubstanceCoreUtilities.toBleedWatermark(this .tree))
0367: newOpaque = false;
0368:
0369: // fix for defect 181 - no highlight on renderers
0370: // that extend DefaultTreeCellRenderer
0371: newOpaque = newOpaque && canHaveSubstanceEffects;
0372:
0373: Map<Component, Boolean> opacity = new HashMap<Component, Boolean>();
0374: if (!newOpaque)
0375: SubstanceCoreUtilities.makeNonOpaque(jRenderer,
0376: opacity);
0377: this .rendererPane.paintComponent(g2d, renderer,
0378: this .tree, bounds.x, bounds.y, Math.max(
0379: this .tree.getWidth()
0380: - this .tree.getInsets().right
0381: - this .tree.getInsets().left
0382: - bounds.x, bounds.width),
0383: bounds.height, true);
0384: if (!newOpaque)
0385: SubstanceCoreUtilities.restoreOpaque(jRenderer,
0386: opacity);
0387: }
0388: } else {
0389: this .rendererPane.paintComponent(g2d, renderer, this .tree,
0390: bounds.x, bounds.y, Math.max(clipBounds.width,
0391: bounds.width), bounds.height, true);
0392: }
0393: this .tree.putClientProperty(
0394: SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND, null);
0395:
0396: // Paint the expand control now after the row background has been
0397: // overlayed by the highlight background on selected and rolled over
0398: // rows. See comments on paintExpandControlEnforce().
0399: if (shouldPaintExpandControl(path, row, isExpanded,
0400: hasBeenExpanded, isLeaf)) {
0401: if (!this .tree.getComponentOrientation().isLeftToRight()
0402: && LookUtils.IS_JAVA_5) {
0403: bounds.x -= 4;
0404: }
0405: paintExpandControlEnforce(g2d, clipBounds, insets, bounds,
0406: path, row, isExpanded, hasBeenExpanded, isLeaf);
0407: }
0408:
0409: g2d.dispose();
0410: }
0411:
0412: /*
0413: * (non-Javadoc)
0414: *
0415: * @see javax.swing.plaf.basic.BasicTreeUI#paintExpandControl(java.awt.Graphics,
0416: * java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0417: * javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0418: */
0419: @Override
0420: protected void paintExpandControl(Graphics g, Rectangle clipBounds,
0421: Insets insets, Rectangle bounds, TreePath path, int row,
0422: boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
0423: // This does nothing. The base implementation of paint() paints
0424: // the tree lines and tree expand controls *before* painting the
0425: // renderer. In Substance, the highlights are painted in the
0426: // paintRow, and thus would overlay the expand controls. This results
0427: // in expand controls being much less visible under most of the skins.
0428: // So, Substance paints the expand controls *after* painting the
0429: // highlights (and the renderer which doesn't overlap with the expand
0430: // controls in any case). This is done in paintRow() by calling
0431: // the paintExpandControlEnforce() instead (that eventually calls the
0432: // super implementation of paintExpandControl().
0433: }
0434:
0435: protected void paintExpandControlEnforce(Graphics g,
0436: Rectangle clipBounds, Insets insets, Rectangle bounds,
0437: TreePath path, int row, boolean isExpanded,
0438: boolean hasBeenExpanded, boolean isLeaf) {
0439: boolean toPaint = (!this .tree.isEnabled())
0440: || this .isInside
0441: || !FadeConfigurationManager
0442: .getInstance()
0443: .fadeAllowed(
0444: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0445: tree);
0446:
0447: SubstanceTheme theme = SubstanceThemeUtilities
0448: .getTheme(this .tree);
0449: float alpha = theme.getThemeAlpha(this .tree, this .tree
0450: .isEnabled() ? ComponentState.DEFAULT
0451: : ComponentState.DISABLED_UNSELECTED);
0452:
0453: Graphics2D graphics = (Graphics2D) g.create();
0454: if (FadeTracker.getInstance().isTracked(this .tree,
0455: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0456: toPaint = true;
0457: alpha *= FadeTracker
0458: .getInstance()
0459: .getFade10(
0460: this .tree,
0461: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0462: }
0463: if (toPaint) {
0464: graphics.setComposite(TransitionLayout.getAlphaComposite(
0465: this .tree, alpha, g));
0466: super .paintExpandControl(graphics, clipBounds, insets,
0467: bounds, path, row, isExpanded, hasBeenExpanded,
0468: isLeaf);
0469: }
0470: graphics.dispose();
0471: }
0472:
0473: /*
0474: * (non-Javadoc)
0475: *
0476: * @see javax.swing.plaf.basic.BasicTreeUI#paintHorizontalPartOfLeg(java.awt.Graphics,
0477: * java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0478: * javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0479: */
0480: @Override
0481: protected void paintHorizontalPartOfLeg(Graphics g,
0482: Rectangle clipBounds, Insets insets, Rectangle bounds,
0483: TreePath path, int row, boolean isExpanded,
0484: boolean hasBeenExpanded, boolean isLeaf) {
0485: Graphics2D graphics = (Graphics2D) g.create();
0486: float strokeWidth = SubstanceSizeUtils
0487: .getBorderStrokeWidth(SubstanceSizeUtils
0488: .getComponentFontSize(this .tree));
0489: graphics.setStroke(new BasicStroke(strokeWidth,
0490: BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
0491: graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0492: RenderingHints.VALUE_ANTIALIAS_ON);
0493:
0494: boolean toPaint = (!this .tree.isEnabled())
0495: || this .isInside
0496: || !FadeConfigurationManager
0497: .getInstance()
0498: .fadeAllowed(
0499: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0500: tree);
0501:
0502: SubstanceTheme theme = SubstanceThemeUtilities
0503: .getTheme(this .tree);
0504: float alpha = theme.getThemeAlpha(this .tree, this .tree
0505: .isEnabled() ? ComponentState.DEFAULT
0506: : ComponentState.DISABLED_UNSELECTED);
0507:
0508: if (FadeTracker.getInstance().isTracked(this .tree,
0509: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0510: toPaint = true;
0511: alpha *= FadeTracker
0512: .getInstance()
0513: .getFade10(
0514: this .tree,
0515: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0516: }
0517: if (toPaint) {
0518: graphics.setComposite(TransitionLayout.getAlphaComposite(
0519: this .tree, alpha, g));
0520: super .paintHorizontalPartOfLeg(graphics, clipBounds,
0521: insets, bounds, path, row, isExpanded,
0522: hasBeenExpanded, isLeaf);
0523: }
0524: graphics.dispose();
0525: }
0526:
0527: /*
0528: * (non-Javadoc)
0529: *
0530: * @see javax.swing.plaf.basic.BasicTreeUI#paintVerticalPartOfLeg(java.awt.Graphics,
0531: * java.awt.Rectangle, java.awt.Insets, javax.swing.tree.TreePath)
0532: */
0533: @Override
0534: protected void paintVerticalPartOfLeg(Graphics g,
0535: Rectangle clipBounds, Insets insets, TreePath path) {
0536: Graphics2D graphics = (Graphics2D) g.create();
0537: float strokeWidth = SubstanceSizeUtils
0538: .getBorderStrokeWidth(SubstanceSizeUtils
0539: .getComponentFontSize(this .tree));
0540: graphics.setStroke(new BasicStroke(strokeWidth,
0541: BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
0542: graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0543: RenderingHints.VALUE_ANTIALIAS_ON);
0544:
0545: boolean toPaint = (!this .tree.isEnabled())
0546: || this .isInside
0547: || !FadeConfigurationManager
0548: .getInstance()
0549: .fadeAllowed(
0550: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0551: tree);
0552:
0553: SubstanceTheme theme = SubstanceThemeUtilities
0554: .getTheme(this .tree);
0555: float alpha = theme.getThemeAlpha(this .tree, this .tree
0556: .isEnabled() ? ComponentState.DEFAULT
0557: : ComponentState.DISABLED_UNSELECTED);
0558:
0559: if (FadeTracker.getInstance().isTracked(this .tree,
0560: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0561: toPaint = true;
0562: alpha *= FadeTracker
0563: .getInstance()
0564: .getFade10(
0565: this .tree,
0566: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0567: }
0568: if (toPaint) {
0569: graphics.setComposite(TransitionLayout.getAlphaComposite(
0570: this .tree, alpha, g));
0571: super .paintVerticalPartOfLeg(graphics, clipBounds, insets,
0572: path);
0573: }
0574: graphics.dispose();
0575: }
0576:
0577: /*
0578: * (non-Javadoc)
0579: *
0580: * @see javax.swing.plaf.basic.BasicTreeUI#createDefaultCellRenderer()
0581: */
0582: @Override
0583: protected TreeCellRenderer createDefaultCellRenderer() {
0584: return new SubstanceDefaultTreeCellRenderer();
0585: }
0586:
0587: /*
0588: * (non-Javadoc)
0589: *
0590: * @see javax.swing.plaf.basic.BasicTreeUI#installListeners()
0591: */
0592: @Override
0593: protected void installListeners() {
0594: super .installListeners();
0595: this .substancePropertyChangeListener = new PropertyChangeListener() {
0596: public void propertyChange(PropertyChangeEvent evt) {
0597: if (SubstanceLookAndFeel.WATERMARK_TO_BLEED.equals(evt
0598: .getPropertyName())) {
0599: tree.setOpaque(!SubstanceCoreUtilities
0600: .toBleedWatermark(tree));
0601: }
0602: if ("font".equals(evt.getPropertyName())) {
0603: SwingUtilities.invokeLater(new Runnable() {
0604: public void run() {
0605: tree.updateUI();
0606: }
0607: });
0608: }
0609: }
0610: };
0611: this .tree
0612: .addPropertyChangeListener(this .substancePropertyChangeListener);
0613:
0614: this .substanceSelectionFadeListener = new MyTreeSelectionListener();
0615: this .tree.getSelectionModel().addTreeSelectionListener(
0616: this .substanceSelectionFadeListener);
0617:
0618: this .substanceRowSelectionListener = new RowSelectionListener();
0619: this .tree.addMouseListener(this .substanceRowSelectionListener);
0620:
0621: // Add listener for the fade animation
0622: this .substanceFadeRolloverListener = new RolloverFadeListener();
0623: this .tree
0624: .addMouseMotionListener(this .substanceFadeRolloverListener);
0625: this .tree.addMouseListener(this .substanceFadeRolloverListener);
0626: }
0627:
0628: /*
0629: * (non-Javadoc)
0630: *
0631: * @see javax.swing.plaf.basic.BasicTreeUI#uninstallListeners()
0632: */
0633: @Override
0634: protected void uninstallListeners() {
0635: this .tree
0636: .removeMouseListener(this .substanceRowSelectionListener);
0637: this .substanceRowSelectionListener = null;
0638:
0639: this .tree.getSelectionModel().removeTreeSelectionListener(
0640: this .substanceSelectionFadeListener);
0641: this .substanceSelectionFadeListener = null;
0642:
0643: this .tree
0644: .removePropertyChangeListener(this .substancePropertyChangeListener);
0645: this .substancePropertyChangeListener = null;
0646:
0647: // Remove listener for the fade animation
0648: this .tree
0649: .removeMouseMotionListener(this .substanceFadeRolloverListener);
0650: this .tree
0651: .removeMouseListener(this .substanceFadeRolloverListener);
0652: this .substanceFadeRolloverListener = null;
0653:
0654: super .uninstallListeners();
0655: }
0656:
0657: /**
0658: * ID of a single tree path.
0659: *
0660: * @author Kirill Grouchnikov
0661: */
0662: @SuppressWarnings("unchecked")
0663: protected static class TreePathId implements Comparable {
0664: /**
0665: * Tree path.
0666: */
0667: protected TreePath path;
0668:
0669: /**
0670: * Creates a tree path ID.
0671: *
0672: * @param path
0673: * Tree path.
0674: */
0675: public TreePathId(TreePath path) {
0676: this .path = path;
0677: }
0678:
0679: /*
0680: * (non-Javadoc)
0681: *
0682: * @see java.lang.Comparable#compareTo(java.lang.Object)
0683: */
0684: public int compareTo(Object o) {
0685: if (o instanceof TreePathId) {
0686: TreePathId otherId = (TreePathId) o;
0687: if ((this .path == null) && (otherId.path != null))
0688: return 1;
0689: if ((otherId.path == null) && (this .path != null))
0690: return -1;
0691: Object[] path1Objs = this .path.getPath();
0692: Object[] path2Objs = otherId.path.getPath();
0693: if (path1Objs.length != path2Objs.length)
0694: return 1;
0695: for (int i = 0; i < path1Objs.length; i++)
0696: if (!path1Objs[i].equals(path2Objs[i]))
0697: return 1;
0698: return 0;
0699: }
0700: return -1;
0701: }
0702:
0703: /*
0704: * (non-Javadoc)
0705: *
0706: * @see java.lang.Object#equals(java.lang.Object)
0707: */
0708: @Override
0709: public boolean equals(Object obj) {
0710: return this .compareTo(obj) == 0;
0711: }
0712:
0713: /*
0714: * (non-Javadoc)
0715: *
0716: * @see java.lang.Object#hashCode()
0717: */
0718: @Override
0719: public int hashCode() {
0720: if (this .path == null)
0721: return 0;
0722: Object[] pathObjs = this .path.getPath();
0723: int result = pathObjs[0].hashCode();
0724: for (int i = 1; i < pathObjs.length; i++)
0725: result = result ^ pathObjs[i].hashCode();
0726: return result;
0727: }
0728: }
0729:
0730: /**
0731: * Selection listener for selection animation effects.
0732: *
0733: * @author Kirill Grouchnikov
0734: */
0735: protected class MyTreeSelectionListener implements
0736: TreeSelectionListener {
0737: /*
0738: * (non-Javadoc)
0739: *
0740: * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
0741: */
0742: @SuppressWarnings("unchecked")
0743: public void valueChanged(TreeSelectionEvent e) {
0744: // Map<TreePathId, Object> currSelected = (Map<TreePathId, Object>)
0745: // tree
0746: // .getClientProperty(SELECTED_INDICES);
0747: if (tree.getSelectionPaths() != null) {
0748: for (TreePath selectionPath : tree.getSelectionPaths()) {
0749: TreePathId pathId = new TreePathId(selectionPath);
0750:
0751: // check if was selected before
0752: if (!selectedPaths.containsKey(pathId)) {
0753: // start fading in
0754: // System.out.println("Fade in on index " + i);
0755: FadeTracker.getInstance().trackFadeIn(
0756: FadeKind.SELECTION,
0757: tree,
0758: pathId,
0759: false,
0760: new PathRepaintCallback(tree,
0761: selectionPath));
0762: selectedPaths.put(pathId, selectionPath
0763: .getLastPathComponent());
0764: }
0765: }
0766: }
0767:
0768: for (Iterator<Map.Entry<TreePathId, Object>> it = selectedPaths
0769: .entrySet().iterator(); it.hasNext();) {
0770: Map.Entry<TreePathId, Object> entry = it.next();
0771: if (tree.getSelectionModel().isPathSelected(
0772: entry.getKey().path))
0773: continue;
0774: // fade out for deselected path
0775: FadeTracker.getInstance().trackFadeOut(
0776: FadeKind.SELECTION,
0777: tree,
0778: entry.getKey(),
0779: false,
0780: new PathRepaintCallback(tree,
0781: entry.getKey().path));
0782: it.remove();
0783: }
0784: }
0785: }
0786:
0787: /**
0788: * Repaints a single path during the fade animation cycle.
0789: *
0790: * @author Kirill Grouchnikov
0791: */
0792: protected class PathRepaintCallback extends FadeTrackerAdapter {
0793: /**
0794: * Associated tree.
0795: */
0796: protected JTree tree;
0797:
0798: /**
0799: * Associated (animated) path.
0800: */
0801: protected TreePath treePath;
0802:
0803: /**
0804: * Creates a new animation repaint callback.
0805: *
0806: * @param tree
0807: * Associated tree.
0808: * @param treePath
0809: * Associated (animated) path.
0810: */
0811: public PathRepaintCallback(JTree tree, TreePath treePath) {
0812: super ();
0813: this .tree = tree;
0814: this .treePath = treePath;
0815: }
0816:
0817: /*
0818: * (non-Javadoc)
0819: *
0820: * @see org.jvnet.lafwidget.utils.FadeTracker$FadeTrackerCallback#fadeEnded(org.jvnet.lafwidget.utils.FadeTracker.FadeKind)
0821: */
0822: @Override
0823: public void fadeEnded(FadeKind fadeKind) {
0824: if (SubstanceTreeUI.this .tree == tree) {
0825: TreePathId pathId = new TreePathId(treePath);
0826: ComponentState currState = getPathState(pathId);
0827: if (currState == ComponentState.DEFAULT) {
0828: prevStateMap.remove(pathId);
0829: nextStateMap.remove(pathId);
0830: } else {
0831: prevStateMap.put(pathId, currState);
0832: nextStateMap.put(pathId, currState);
0833: }
0834: // System.out.println(tabIndex + "->"
0835: // + prevStateMap.get(tabIndex).name());
0836: }
0837: this .repaintPath();
0838: }
0839:
0840: /*
0841: * (non-Javadoc)
0842: *
0843: * @see org.jvnet.lafwidget.utils.FadeTracker$FadeTrackerCallback#fadePerformed(org.jvnet.lafwidget.utils.FadeTracker.FadeKind,
0844: * float)
0845: */
0846: @Override
0847: public void fadePerformed(FadeKind fadeKind, float fade10) {
0848: if (SubstanceTreeUI.this .tree == tree) {
0849: TreePathId pathId = new TreePathId(treePath);
0850: nextStateMap.put(pathId, getPathState(pathId));
0851: }
0852: this .repaintPath();
0853: }
0854:
0855: /*
0856: * (non-Javadoc)
0857: *
0858: * @see org.jvnet.lafwidget.animation.FadeTrackerAdapter#fadeReversed(org.jvnet.lafwidget.animation.FadeKind,
0859: * boolean, float)
0860: */
0861: @Override
0862: public void fadeReversed(FadeKind fadeKind, boolean isFadingIn,
0863: float fadeCycle10) {
0864: if (SubstanceTreeUI.this .tree == tree) {
0865: TreePathId pathId = new TreePathId(treePath);
0866: ComponentState nextState = nextStateMap.get(pathId);
0867: if (nextState == null) {
0868: prevStateMap.remove(pathId);
0869: } else {
0870: prevStateMap.put(pathId, nextState);
0871: }
0872: // System.out.println(tabIndex + "->"
0873: // + prevStateMap.get(tabIndex).name());
0874: }
0875: this .repaintPath();
0876: }
0877:
0878: /**
0879: * Repaints the associated path.
0880: */
0881: private void repaintPath() {
0882: SwingUtilities.invokeLater(new Runnable() {
0883: public void run() {
0884: if (SubstanceTreeUI.this .tree == null) {
0885: // may happen if the LAF was switched in the meantime
0886: return;
0887: }
0888:
0889: Rectangle boundsBuffer = new Rectangle();
0890: Rectangle bounds = treeState.getBounds(treePath,
0891: boundsBuffer);
0892:
0893: if (bounds != null) {
0894: // still visible
0895:
0896: // fix for defect 180 - refresh the entire row
0897: bounds.x = 0;
0898: bounds.width = tree.getWidth();
0899:
0900: // fix for defect 188 - rollover effects for trees
0901: // with insets
0902: Insets insets = tree.getInsets();
0903: bounds.x += insets.left;
0904: bounds.y += insets.top;
0905:
0906: tree.repaint(bounds);
0907: }
0908: }
0909: });
0910: }
0911: }
0912:
0913: /**
0914: * Listener for rollover animation effects.
0915: *
0916: * @author Kirill Grouchnikov
0917: */
0918: private class RolloverFadeListener implements MouseListener,
0919: MouseMotionListener {
0920:
0921: public void mouseClicked(MouseEvent e) {
0922: }
0923:
0924: public void mouseEntered(MouseEvent e) {
0925: if (!tree.isEnabled())
0926: return;
0927: isInside = true;
0928: if (FadeConfigurationManager
0929: .getInstance()
0930: .fadeAllowed(
0931: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0932: tree)) {
0933: FadeTracker
0934: .getInstance()
0935: .trackFadeIn(
0936: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0937: tree, false, null);
0938: }
0939: }
0940:
0941: public void mousePressed(MouseEvent e) {
0942: }
0943:
0944: public void mouseReleased(MouseEvent e) {
0945: }
0946:
0947: public void mouseExited(MouseEvent e) {
0948: if (!tree.isEnabled())
0949: return;
0950: isInside = false;
0951: if (FadeConfigurationManager
0952: .getInstance()
0953: .fadeAllowed(
0954: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0955: tree)) {
0956: FadeTracker
0957: .getInstance()
0958: .trackFadeOut(
0959: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0960: tree, false, null);
0961: }
0962: this .fadeOut();
0963: // System.out.println("Nulling RO index");
0964: currRolloverPathId = null;
0965: }
0966:
0967: public void mouseMoved(MouseEvent e) {
0968: if (!tree.isEnabled())
0969: return;
0970: isInside = true;
0971: handleMove(e);
0972: }
0973:
0974: public void mouseDragged(MouseEvent e) {
0975: if (!tree.isEnabled())
0976: return;
0977: handleMove(e);
0978: }
0979:
0980: /**
0981: * Handles various mouse move events and initiates the fade animation if
0982: * necessary.
0983: *
0984: * @param e
0985: * Mouse event.
0986: */
0987: private void handleMove(MouseEvent e) {
0988: TreePath closestPath = tree.getClosestPathForLocation(e
0989: .getX(), e.getY());
0990: Rectangle bounds = tree.getPathBounds(closestPath);
0991: if (bounds == null) {
0992: this .fadeOut();
0993: currRolloverPathId = null;
0994: return;
0995: }
0996: if ((e.getY() < bounds.y)
0997: || (e.getY() > (bounds.y + bounds.height))) {
0998: this .fadeOut();
0999: currRolloverPathId = null;
1000: return;
1001: }
1002: // check if this is the same index
1003: TreePathId newPathId = new TreePathId(closestPath);
1004: if ((currRolloverPathId != null)
1005: && newPathId.equals(currRolloverPathId)) {
1006: // System.out.println("Same location " +
1007: // System.currentTimeMillis());
1008: // System.out.print("Current : ");
1009: // for (Object o1 : currPathId.path.getPath()) {
1010: // System.out.print(o1);
1011: // }
1012: // System.out.println("");
1013: // System.out.print("Closest : ");
1014: // for (Object o2 : newPathId.path.getPath()) {
1015: // System.out.print(o2);
1016: // }
1017: // System.out.println("");
1018: return;
1019: }
1020:
1021: this .fadeOut();
1022: FadeTracker.getInstance().trackFadeIn(FadeKind.ROLLOVER,
1023: tree, newPathId, false,
1024: new PathRepaintCallback(tree, closestPath));
1025: // System.out.println("Setting RO index to " + roIndex);
1026: currRolloverPathId = newPathId;
1027: }
1028:
1029: /**
1030: * Initiates the fade out effect.
1031: */
1032: private void fadeOut() {
1033: if (currRolloverPathId == null)
1034: return;
1035:
1036: FadeTracker.getInstance().trackFadeOut(
1037: FadeKind.ROLLOVER,
1038: tree,
1039: currRolloverPathId,
1040: false,
1041: new PathRepaintCallback(tree,
1042: currRolloverPathId.path));
1043: }
1044: }
1045:
1046: /**
1047: * Listener for selecting the entire rows.
1048: *
1049: * @author Kirill Grouchnikov
1050: */
1051: private class RowSelectionListener extends MouseAdapter {
1052: /*
1053: * (non-Javadoc)
1054: *
1055: * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
1056: */
1057: @Override
1058: public void mousePressed(MouseEvent e) {
1059: if (!tree.isEnabled())
1060: return;
1061: TreePath closestPath = tree.getClosestPathForLocation(e
1062: .getX(), e.getY());
1063: if (closestPath == null)
1064: return;
1065: Rectangle bounds = tree.getPathBounds(closestPath);
1066: // Process events outside the immediate bounds - fix for defect
1067: // 19 on substance-netbeans. This properly handles Ctrl and Shift
1068: // selections on trees.
1069: if ((e.getY() >= bounds.y)
1070: && (e.getY() < (bounds.y + bounds.height))
1071: && ((e.getX() < bounds.x) || (e.getX() > (bounds.x + bounds.width)))) {
1072: // tree.setSelectionPath(closestPath);
1073:
1074: // fix - don't select a node if the click was on the
1075: // expand control
1076: if (isLocationInExpandControl(closestPath, e.getX(), e
1077: .getY()))
1078: return;
1079: selectPathForEvent(closestPath, e);
1080: }
1081: }
1082: }
1083:
1084: /**
1085: * Returns the pivot X for the cells rendered in the specified area. Used
1086: * for the smart tree scroll ({@link SubstanceLookAndFeel#TREE_SMART_SCROLL_ANIMATION_KIND}).
1087: *
1088: * @param paintBounds
1089: * Area bounds.
1090: * @return Pivot X for the cells rendered in the specified area
1091: */
1092: public int getPivotRendererX(Rectangle paintBounds) {
1093: TreePath initialPath = getClosestPathForLocation(tree, 0,
1094: paintBounds.y);
1095: Enumeration<?> paintingEnumerator = treeState
1096: .getVisiblePathsFrom(initialPath);
1097: int endY = paintBounds.y + paintBounds.height;
1098:
1099: int totalY = 0;
1100: int count = 0;
1101:
1102: if (initialPath != null && paintingEnumerator != null) {
1103: boolean done = false;
1104: Rectangle boundsBuffer = new Rectangle();
1105: Rectangle bounds;
1106: TreePath path;
1107: Insets insets = tree.getInsets();
1108:
1109: while (!done && paintingEnumerator.hasMoreElements()) {
1110: path = (TreePath) paintingEnumerator.nextElement();
1111: if (path != null) {
1112: bounds = treeState.getBounds(path, boundsBuffer);
1113: bounds.x += insets.left;
1114: bounds.y += insets.top;
1115:
1116: int currMedianX = bounds.x;// + bounds.width / 2;
1117: totalY += currMedianX;
1118: count++;
1119: if ((bounds.y + bounds.height) >= endY)
1120: done = true;
1121: } else {
1122: done = true;
1123: }
1124: }
1125: }
1126: if (count == 0)
1127: return -1;
1128: return totalY
1129: / count
1130: - 2
1131: * SubstanceSizeUtils.getTreeIconSize(SubstanceSizeUtils
1132: .getComponentFontSize(tree));
1133: }
1134:
1135: /**
1136: * Returns the previous state for the specified path.
1137: *
1138: * @param pathId
1139: * Path index.
1140: * @return The previous state for the specified path.
1141: */
1142: public ComponentState getPrevPathState(TreePathId pathId) {
1143: if (this .prevStateMap.containsKey(pathId))
1144: return this .prevStateMap.get(pathId);
1145: return ComponentState.DEFAULT;
1146: }
1147:
1148: /**
1149: * Returns the current state for the specified path.
1150: *
1151: * @param pathId
1152: * Path index.
1153: * @return The current state for the specified path.
1154: */
1155: public ComponentState getPathState(TreePathId pathId) {
1156: ButtonModel synthModel = new DefaultButtonModel();
1157: synthModel.setEnabled(this .tree.isEnabled());
1158: synthModel.setRollover((this .currRolloverPathId != null)
1159: && pathId.equals(this .currRolloverPathId));
1160: int rowIndex = this .tree.getRowForPath(pathId.path);
1161: synthModel.setSelected(this .tree.isRowSelected(rowIndex));
1162: return ComponentState.getState(synthModel, null);
1163: }
1164:
1165: /*
1166: * (non-Javadoc)
1167: *
1168: * @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
1169: * javax.swing.JComponent)
1170: */
1171: @Override
1172: public void update(Graphics g, JComponent c) {
1173: SubstanceFillBackgroundDelegate.GLOBAL_INSTANCE.updateIfOpaque(
1174: g, c);
1175:
1176: // Should never happen if installed for a UI
1177: if (treeState == null) {
1178: return;
1179: }
1180:
1181: Rectangle paintBounds = g.getClipBounds();
1182: Insets insets = tree.getInsets();
1183:
1184: TreePath initialPath = getClosestPathForLocation(tree, 0,
1185: paintBounds.y);
1186: Enumeration paintingEnumerator = treeState
1187: .getVisiblePathsFrom(initialPath);
1188: int row = treeState.getRowForPath(initialPath);
1189: int endY = paintBounds.y + paintBounds.height;
1190:
1191: // second part - fix for defect 214 (rollover effects on non-opaque
1192: // trees resulted in inconsistent behaviour)
1193: boolean isWatermarkBleed = SubstanceCoreUtilities
1194: .toBleedWatermark(tree)
1195: || !tree.isOpaque();
1196:
1197: Graphics2D g2d = (Graphics2D) g.create();
1198:
1199: if (initialPath != null && paintingEnumerator != null) {
1200: boolean done = false;
1201: Rectangle boundsBuffer = new Rectangle();
1202: Rectangle bounds;
1203: TreePath path;
1204:
1205: while (!done && paintingEnumerator.hasMoreElements()) {
1206: path = (TreePath) paintingEnumerator.nextElement();
1207: if (path != null) {
1208: // respect the background color of the renderer.
1209: boolean isLeaf = treeModel.isLeaf(path
1210: .getLastPathComponent());
1211: boolean isExpanded = isLeaf ? false : treeState
1212: .getExpandedState(path);
1213: Component renderer = this .currentCellRenderer
1214: .getTreeCellRendererComponent(
1215: this .tree,
1216: path.getLastPathComponent(),
1217: this .tree.isRowSelected(row),
1218: isExpanded,
1219: isLeaf,
1220: row,
1221: tree.hasFocus() ? (tree
1222: .getLeadSelectionRow() == row)
1223: : false);
1224: Color background = renderer.getBackground();
1225: if (background == null)
1226: background = tree.getBackground();
1227: bounds = treeState.getBounds(path, boundsBuffer);
1228: bounds.x += insets.left;
1229: bounds.y += insets.top;
1230: if (!isWatermarkBleed) {
1231: g2d.setColor(background);
1232: g2d.fillRect(paintBounds.x, bounds.y,
1233: paintBounds.width, bounds.height);
1234: } else {
1235: if (this .tree.getComponentOrientation()
1236: .isLeftToRight()) {
1237: backgroundDelegate.fillAndWatermark(g2d,
1238: this .tree, background,
1239: new Rectangle(paintBounds.x,
1240: bounds.y,
1241: paintBounds.width,
1242: bounds.height));
1243: } else {
1244: backgroundDelegate.fillAndWatermark(g2d,
1245: this .tree, background,
1246: new Rectangle(paintBounds.x,
1247: bounds.y,
1248: paintBounds.width,
1249: bounds.height));
1250: }
1251: }
1252: if ((bounds.y + bounds.height) >= endY)
1253: done = true;
1254: } else {
1255: done = true;
1256: }
1257: row++;
1258: }
1259: }
1260:
1261: this .paint(g2d, c);
1262: g2d.dispose();
1263: }
1264:
1265: /*
1266: * (non-Javadoc)
1267: *
1268: * @see javax.swing.plaf.basic.BasicTreeUI#getHashColor()
1269: */
1270: @Override
1271: protected Color getHashColor() {
1272: SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
1273: this .tree,
1274: this .tree.isEnabled() ? ComponentState.DEFAULT
1275: : ComponentState.DISABLED_UNSELECTED);
1276: Color curr = theme.getLineColor();
1277:
1278: // // support for enhancement 256 - colorization of controls.
1279: // boolean hasColorization = SubstanceCoreUtilities
1280: // .hasColorization(this.tree);
1281: // if (hasColorization) {
1282: // Color backgr = this.tree.getBackground();
1283: // if (!(backgr instanceof UIResource)) {
1284: // double colorizationFactor = SubstanceCoreUtilities
1285: // .getColorizationFactor(this.tree);
1286: // if (!tree.isEnabled())
1287: // colorizationFactor /= 2.0;
1288: // Color toShiftTo = SubstanceColorUtilities.deriveByBrightness(
1289: // backgr, curr);
1290: // curr = SubstanceColorUtilities.getInterpolatedColor(toShiftTo,
1291: // curr, colorizationFactor);
1292: // }
1293: // }
1294:
1295: return curr;
1296: }
1297: }
|