/* * $Id$ * * Copyright 2007 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jdesktop.swingx.renderer; import java.awt.BorderLayout; import java.awt.Color; import java.awt.ComponentOrientation; import java.awt.Font; import java.awt.Rectangle; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.border.Border; import org.jdesktop.swingx.JXPanel; import org.jdesktop.swingx.painter.Painter; /** * Compound component for usage in tree renderer. <p> * * Supports setting an icon for the node and a delegate component * which is used to show the text/content of the node. The delegate * component can be shared across renderers. <p> * * This implements the PainterAware by delegating to the delegate component if that * is of type PainterAware. Does nothing if not. */ public class WrappingIconPanel extends JXPanel implements PainterAware, IconAware { protected JComponent delegate; JLabel iconLabel; String labelPosition = BorderLayout.CENTER; //2; int iconLabelGap; private Border ltorBorder; private Border rtolBorder; private boolean dropHackEnabled; private boolean extendsComponentOpacity; /** * Instantiates and configures a WrappingIconPanel with the dropHack * enabled. * */ public WrappingIconPanel() { this(true); } /** * Instantiates and configures a WrappingIconPanel with the dropHack * property set as indicated by the boolean. * * @param dropHackEnabled a boolean indicating whether the drop hack should * be enabled. * * @see #isVisible() */ public WrappingIconPanel(boolean dropHackEnabled) { setOpaque(false); iconLabel = new JRendererLabel(); iconLabelGap = iconLabel.getIconTextGap(); iconLabel.setOpaque(false); updateIconBorder(); setBorder(null); setLayout(new BorderLayout()); add(iconLabel, BorderLayout.LINE_START); setDropHackEnabled(dropHackEnabled); } /** * {@inheritDoc} <p> * * Overridden to update the icon position. */ @Override public void setComponentOrientation(ComponentOrientation o) { super.setComponentOrientation(o); updateIconBorder(); } /** * Updates the icon position according to ComponentOrientation. */ private void updateIconBorder() { if (ltorBorder == null) { ltorBorder = BorderFactory.createEmptyBorder(0, 0, 0, iconLabelGap); rtolBorder = BorderFactory.createEmptyBorder(0, iconLabelGap, 0, 0); } if (getComponentOrientation().isLeftToRight()) { iconLabel.setBorder(ltorBorder); } else { iconLabel.setBorder(rtolBorder); } } /** * Sets the icon. * * @param icon the icon to use. */ @Override public void setIcon(Icon icon) { iconLabel.setIcon(icon); iconLabel.setText(null); validate(); } /** * Returns the icon used in this panel, may be null. * * @return the icon used in this panel, may be null. */ @Override public Icon getIcon() { return iconLabel.getIcon(); } /** * Sets the delegate component. * * @param comp the component to add as delegate. */ public void setComponent(JComponent comp) { JComponent old = getComponent(); if (delegate != null) { remove(delegate); } delegate = comp; if (extendsComponentOpacity) { iconLabel.setOpaque(comp.isOpaque()); } else { iconLabel.setOpaque(false); } add(delegate, labelPosition); validate(); firePropertyChange("component", old, getComponent()); } /** * Returns the delegate component. * * @return the delegate component. */ public JComponent getComponent() { return delegate; } /** * {@inheritDoc} <p> * * Overridden to set the background of the delegate and icon label as well. */ @Override public void setBackground(Color bg) { super.setBackground(bg); if (iconLabel != null) { iconLabel.setBackground(bg); } if (delegate != null) { delegate.setBackground(bg); } } /** * {@inheritDoc} <p> * * Overridden to set the foreground of the delegate and icon label as well. */ @Override public void setForeground(Color bg) { super.setForeground(bg); if (iconLabel != null) { iconLabel.setForeground(bg); } if (delegate != null) { delegate.setForeground(bg); } } /** * {@inheritDoc} <p> * * Overridden to set the Font of the delegate as well. */ @Override public void setFont(Font font) { if (delegate != null) { delegate.setFont(font); } super.setFont(font); } /** * {@inheritDoc} * <p> * * Overridden to hack around #766-swingx: cursor flickering in DnD when * dragging over tree column. This is a core bug (#6700748) related to * painting the rendering component on a CellRendererPane. A trick around is * to let this return false. * <p> * * Some LayoutManagers don't layout an invisible component, so need to make * the hack-enabled configurable. This implementation will return false * if isDropHackEnabled, super.isVisible otherwise. */ @Override public boolean isVisible() { return dropHackEnabled ? false : super.isVisible(); } /** * {@inheritDoc} * <p> * * Returns the delegate's Painter if it is of type PainterAware or null * otherwise. * * @return the delegate's Painter or null. */ @Override public Painter<?> getPainter() { if (delegate instanceof PainterAware) { return ((PainterAware) delegate).getPainter(); } return null; } /** * Sets the delegate's Painter if it is of type PainterAware. Does nothing otherwise. * * @param painter the Painter to apply to the delegate. */ @Override public void setPainter(Painter<?> painter) { if (delegate instanceof PainterAware) { ((PainterAware) delegate).setPainter(painter); } } /** * * Returns the bounds of the delegate component or null if the delegate is null. * * PENDING JW: where do we use it? Maybe it was for testing only? * * @return the bounds of the delegate, or null if the delegate is null. */ public Rectangle getDelegateBounds() { if (delegate == null) return null; return delegate.getBounds(); } /** * Sets the dropHackEnabled property. <p> * * The default value is true. * * @param dropHackEnabled * * @see #isVisible() */ public void setDropHackEnabled(boolean dropHackEnabled) { this.dropHackEnabled = dropHackEnabled; } /** * Sets a boolean indicating whether or not the main component's opacity * should be applied to the Icon region.<p> * * The default value is false. This covers the main use case in a JTree. * * @param extendsComponentOpacity */ public void setExtendsComponentOpacity(boolean extendsComponentOpacity) { this.extendsComponentOpacity = extendsComponentOpacity; } /** * @return the extendsComponentOpacity */ public boolean getExtendsComponentOpacity() { return extendsComponentOpacity; } }