Package org.pushingpixels.substance.api.renderers

Source Code of org.pushingpixels.substance.api.renderers.SubstanceDefaultTreeCellRenderer

/*
* Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  o Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*    
*  o Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*    
*  o Neither the name of Substance Kirill Grouchnikov nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*    
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.substance.api.renderers;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.util.Map;

import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.TreeUI;
import javax.swing.tree.TreeCellRenderer;

import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker.StateContributionInfo;
import org.pushingpixels.substance.internal.ui.SubstanceTreeUI;
import org.pushingpixels.substance.internal.ui.SubstanceTreeUI.TreePathId;
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceImageCreator;
import org.pushingpixels.substance.internal.utils.SubstanceStripingUtils;

/**
* Default renderer for tree cells.
*
* @author Kirill Grouchnikov
*/
@SubstanceRenderer
public class SubstanceDefaultTreeCellRenderer extends JLabel implements
    TreeCellRenderer {
  /** Last tree the renderer was painted in. */
  private JTree tree;

  /** Is the value currently selected. */
  protected boolean selected;

  /** True if has focus. */
  protected boolean hasFocus;

  /**
   * Returns a new instance of SubstanceDefaultTreeCellRenderer. Alignment is
   * set to left aligned. Icons and text color are determined from the
   * UIManager.
   */
  public SubstanceDefaultTreeCellRenderer() {
    this.setHorizontalAlignment(SwingConstants.LEFT);
    this.putClientProperty(SubstanceLookAndFeel.COLORIZATION_FACTOR, 1.0);
  }

  /**
   * Returns the default icon that is used to represent non-leaf nodes that
   * are expanded.
   *
   * @return The default icon for non-leaf expanded nodes.
   */
  public Icon getDefaultOpenIcon() {
    return UIManager.getIcon("Tree.openIcon");
  }

  /**
   * Returns the default icon that is used to represent non-leaf nodes that
   * are not expanded.
   *
   * @return The default icon for non-leaf non-expanded nodes.
   */
  public Icon getDefaultClosedIcon() {
    return UIManager.getIcon("Tree.closedIcon");
  }

  /**
   * Returns the default icon that is used to represent leaf nodes.
   *
   * @return The default icon for leaf nodes.
   */
  public Icon getDefaultLeafIcon() {
    return UIManager.getIcon("Tree.leafIcon");
  }

  /**
   * Subclassed to map <code>FontUIResource</code>s to null. If
   * <code>font</code> is null, or a <code>FontUIResource</code>, this has the
   * effect of letting the font of the JTree show through. On the other hand,
   * if <code>font</code> is non-null, and not a <code>FontUIResource</code>,
   * the font becomes <code>font</code>.
   */
  @Override
  public void setFont(Font font) {
    if (font instanceof FontUIResource)
      font = null;
    super.setFont(font);
  }

  /**
   * Gets the font of this component.
   *
   * @return this component's font; if a font has not been set for this
   *         component, the font of its parent is returned
   */
  @Override
  public Font getFont() {
    Font font = super.getFont();

    if ((font == null) && (this.tree != null)) {
      // Strive to return a non-null value, otherwise the html support
      // will typically pick up the wrong font in certain situations.
      font = this.tree.getFont();
    }
    return font;
  }

  /**
   * Configures the renderer based on the passed in components. The value is
   * set from messaging the tree with <code>convertValueToText</code>, which
   * ultimately invokes <code>toString</code> on <code>value</code>. The
   * foreground color is set based on the selection and the icon is set based
   * on on leaf and expanded.
   */
  public Component getTreeCellRendererComponent(JTree tree, Object value,
      boolean sel, boolean expanded, boolean leaf, int row,
      boolean hasFocus) {
    String stringValue = tree.convertValueToText(value, sel, expanded,
        leaf, row, hasFocus);

    this.tree = tree;
    this.hasFocus = hasFocus;
    this.setText(stringValue);

    TreeUI treeUI = tree.getUI();
    if (treeUI instanceof SubstanceTreeUI) {
      SubstanceTreeUI ui = (SubstanceTreeUI) treeUI;
      TreePathId pathId = new TreePathId(tree.getPathForRow(row));

      StateTransitionTracker.ModelStateInfo modelStateInfo = ui
          .getModelStateInfo(pathId);
      ComponentState currState = ui.getPathState(pathId);

      // special case for drop location
      JTree.DropLocation dropLocation = tree.getDropLocation();
      boolean isDropLocation = (dropLocation != null
          && dropLocation.getChildIndex() == -1 && tree
          .getRowForPath(dropLocation.getPath()) == row);

      if (!isDropLocation && (modelStateInfo != null)) {
        Map<ComponentState, StateContributionInfo> activeStates = modelStateInfo
            .getStateContributionMap();
        SubstanceColorScheme colorScheme = getColorSchemeForState(tree,
            ui, currState);
        if (currState.isDisabled() || (activeStates == null)
            || (activeStates.size() == 1)) {
          super.setForeground(new ColorUIResource(colorScheme
              .getForegroundColor()));
        } else {
          float aggrRed = 0;
          float aggrGreen = 0;
          float aggrBlue = 0;

          for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry : modelStateInfo
              .getStateContributionMap().entrySet()) {
            ComponentState activeState = activeEntry.getKey();
            SubstanceColorScheme scheme = getColorSchemeForState(
                tree, ui, activeState);
            Color schemeFg = scheme.getForegroundColor();
            float contribution = activeEntry.getValue()
                .getContribution();
            aggrRed += schemeFg.getRed() * contribution;
            aggrGreen += schemeFg.getGreen() * contribution;
            aggrBlue += schemeFg.getBlue() * contribution;
          }
          super.setForeground(new ColorUIResource(new Color(
              (int) aggrRed, (int) aggrGreen, (int) aggrBlue)));
        }
      } else {
        SubstanceColorScheme scheme = getColorSchemeForState(tree, ui,
            currState);
        if (isDropLocation) {
          scheme = SubstanceColorSchemeUtilities.getColorScheme(tree,
              ColorSchemeAssociationKind.TEXT_HIGHLIGHT,
              currState);
        }
        super.setForeground(new ColorUIResource(scheme
            .getForegroundColor()));
      }
    } else {
      if (sel)
        this.setForeground(UIManager
            .getColor("Tree.selectionForeground"));
      else
        this.setForeground(UIManager.getColor("Tree.textForeground"));
    }

    if (SubstanceLookAndFeel.isCurrentLookAndFeel())
      SubstanceStripingUtils.applyStripedBackground(tree, row, this);

    // There needs to be a way to specify disabled icons.
    if (!tree.isEnabled()) {
      this.setEnabled(false);
      if (leaf) {
        this.setDisabledIcon(SubstanceImageCreator
            .toGreyscale(SubstanceImageCreator.makeTransparent(
                tree, this.getDefaultLeafIcon(), 0.5)));
      } else if (expanded) {
        this.setDisabledIcon(SubstanceImageCreator
            .toGreyscale(SubstanceImageCreator.makeTransparent(
                tree, this.getDefaultOpenIcon(), 0.5)));
        // setIcon(SubstanceImageCreator.toGreyscale(
        // SubstanceImageCreator
        // .makeTransparent(getDefaultOpenIcon(), 0.5)));
      } else {
        this.setDisabledIcon(SubstanceImageCreator
            .toGreyscale(SubstanceImageCreator.makeTransparent(
                tree, this.getDefaultClosedIcon(), 0.5)));
        // setIcon(SubstanceImageCreator.toGreyscale(
        // SubstanceImageCreator
        // .makeTransparent(getDefaultClosedIcon(), 0.5)));
      }
    } else {
      this.setEnabled(true);
      if (leaf) {
        this.setIcon(this.getDefaultLeafIcon());
      } else if (expanded) {
        this.setIcon(this.getDefaultOpenIcon());
      } else {
        this.setIcon(this.getDefaultClosedIcon());
      }
    }
    this.setComponentOrientation(tree.getComponentOrientation());

    this.setOpaque(false);

    this.selected = sel;

    if (treeUI instanceof SubstanceTreeUI) {
      SubstanceTreeUI ui = (SubstanceTreeUI) treeUI;
      Insets regInsets = ui.getCellRendererInsets();
      this
          .setBorder(new BorderUIResource.EmptyBorderUIResource(
              regInsets));
    }

    return this;
  }

  private SubstanceColorScheme getColorSchemeForState(JTree tree,
      SubstanceTreeUI ui, ComponentState activeState) {
    SubstanceColorScheme scheme = (activeState == ComponentState.ENABLED) ? ui
        .getDefaultColorScheme()
        : SubstanceColorSchemeUtilities.getColorScheme(tree,
            ColorSchemeAssociationKind.HIGHLIGHT, activeState);
    if (scheme == null) {
      scheme = SubstanceColorSchemeUtilities.getColorScheme(tree,
          ColorSchemeAssociationKind.HIGHLIGHT, activeState);
    }
    return scheme;
  }

  /**
   * Overrides <code>JComponent.getPreferredSize</code> to return slightly
   * wider preferred size value.
   */
  @Override
  public Dimension getPreferredSize() {
    Dimension retDimension = super.getPreferredSize();

    if (retDimension != null)
      retDimension = new Dimension(retDimension.width + 3,
          retDimension.height);
    return retDimension;
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void validate() {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   *
   * @since 1.5
   */
  @Override
  public void invalidate() {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void revalidate() {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void repaint(long tm, int x, int y, int width, int height) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void repaint(Rectangle r) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   *
   * @since 1.5
   */
  @Override
  public void repaint() {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  protected void firePropertyChange(String propertyName, Object oldValue,
      Object newValue) {
    if ("text".equals(propertyName))
      super.firePropertyChange(propertyName, oldValue, newValue);
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, byte oldValue,
      byte newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, char oldValue,
      char newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, short oldValue,
      short newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, int oldValue,
      int newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, long oldValue,
      long newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, float oldValue,
      float newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, double oldValue,
      double newValue) {
  }

  /**
   * Overridden for performance reasons. See the <a
   * href="#override">Implementation Note</a> for more information.
   */
  @Override
  public void firePropertyChange(String propertyName, boolean oldValue,
      boolean newValue) {
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.JComponent#paint(java.awt.Graphics)
   */
  @Override
  public final void paint(Graphics g) {
    super.paint(g);
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
   */
  @Override
  protected final void paintComponent(Graphics g) {
    super.paintComponent(g);
  }
}
TOP

Related Classes of org.pushingpixels.substance.api.renderers.SubstanceDefaultTreeCellRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.