/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.gui.component.renderer;
import java.awt.Color;
import java.awt.Component;
import java.awt.Insets;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.ListUI;
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.ComponentStateFacet;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.renderers.SubstanceDefaultComboBoxRenderer;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker.ModelStateInfo;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker.StateContributionInfo;
import org.pushingpixels.substance.internal.ui.SubstanceComboBoxUI;
import org.pushingpixels.substance.internal.ui.SubstanceListUI;
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
import org.pushingpixels.substance.internal.utils.SubstanceStripingUtils;
import org.pushingpixels.substance.internal.utils.SubstanceTextUtilities;
import org.pushingpixels.substance.internal.utils.UpdateOptimizationInfo;
/**
* CustomComboBox renderer, based on Substance look and feel code.<br>
* Override the getListCellRendererComponent() or updateItem() methods to do your own rendering.
*
* @author Stephane
*/
public class CustomComboBoxRenderer extends SubstanceDefaultComboBoxRenderer
{
/**
*
*/
private static final long serialVersionUID = -3392789033779535472L;
private final JComboBox combo;
public CustomComboBoxRenderer(JComboBox combo)
{
super(combo);
this.combo = combo;
}
public JComboBox getComboBox()
{
return combo;
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus)
{
JComponent result = (JComponent) getRendererComponent(list, value, index, isSelected);
ListUI baseListUI = list.getUI();
ComboBoxUI baseComboUI = combo.getUI();
if ((baseListUI instanceof SubstanceListUI) && (baseComboUI instanceof SubstanceComboBoxUI))
{
SubstanceListUI listUI = (SubstanceListUI) baseListUI;
SubstanceComboBoxUI comboUI = (SubstanceComboBoxUI) baseComboUI;
// special case for the combobox. The selected value is
// painted using the renderer of the list, and the index
// is -1.
if (index == -1)
{
StateTransitionTracker stateTransitionTracker = comboUI.getTransitionTracker();
ModelStateInfo modelStateInfo = stateTransitionTracker.getModelStateInfo();
ComponentState currState = modelStateInfo.getCurrModelState();
float comboAlpha = SubstanceColorSchemeUtilities.getAlpha(combo, currState);
Color fg = SubstanceTextUtilities.getForegroundColor(combo, ((JLabel) result).getText(),
modelStateInfo, comboAlpha);
result.setForeground(fg);
}
else
{
// use highlight color scheme for selected and rollover
// elements in the drop down list
StateTransitionTracker.ModelStateInfo modelStateInfo = listUI.getModelStateInfo(index, result);
ComponentState currState = listUI.getCellState(index, result);
if (modelStateInfo == null)
{
SubstanceColorScheme scheme = getColorSchemeForState(list, index, listUI, currState);
result.setForeground(new ColorUIResource(scheme.getForegroundColor()));
}
else
{
Map<ComponentState, StateContributionInfo> activeStates = modelStateInfo.getStateContributionMap();
SubstanceColorScheme colorScheme = getColorSchemeForState(list, index, listUI, currState);
if (currState.isDisabled() || (activeStates == null) || (activeStates.size() == 1))
{
super.setForeground(new ColorUIResource(colorScheme.getForegroundColor()));
}
else
{
float aggrRed = 0.0f;
float aggrGreen = 0.0f;
float aggrBlue = 0.0f;
for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry : modelStateInfo
.getStateContributionMap().entrySet())
{
ComponentState activeState = activeEntry.getKey();
float activeContribution = activeEntry.getValue().getContribution();
if (activeContribution == 0.0f)
continue;
SubstanceColorScheme scheme = getColorSchemeForState(list, index, listUI, activeState);
Color schemeFg = scheme.getForegroundColor();
aggrRed += schemeFg.getRed() * activeContribution;
aggrGreen += schemeFg.getGreen() * activeContribution;
aggrBlue += schemeFg.getBlue() * activeContribution;
}
result.setForeground(new ColorUIResource(new Color((int) aggrRed, (int) aggrGreen,
(int) aggrBlue)));
}
}
}
SubstanceStripingUtils.applyStripedBackground(list, index, this);
}
result.setEnabled(combo.isEnabled() & isEnabled());
return result;
}
protected Component getRendererComponent(JList list, Object value, int index, boolean isSelected)
{
setComponentOrientation(list.getComponentOrientation());
ListUI listUI = list.getUI();
if (listUI instanceof SubstanceListUI)
{
SubstanceListUI ui = (SubstanceListUI) listUI;
StateTransitionTracker.ModelStateInfo modelStateInfo = ui.getModelStateInfo(index, this);
ComponentState currState = ui.getCellState(index, this);
// special case for drop location
JList.DropLocation dropLocation = list.getDropLocation();
boolean isDropLocation = (dropLocation != null && !dropLocation.isInsert() && dropLocation.getIndex() == index);
if (!isDropLocation && (modelStateInfo != null))
{
Map<ComponentState, StateContributionInfo> activeStates = modelStateInfo.getStateContributionMap();
SubstanceColorScheme colorScheme = getColorSchemeForState(list, 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(list, 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(list, ui, currState);
if (isDropLocation)
{
scheme = SubstanceColorSchemeUtilities.getColorScheme(list,
ColorSchemeAssociationKind.TEXT_HIGHLIGHT, currState);
}
super.setForeground(new ColorUIResource(scheme.getForegroundColor()));
}
}
else
{
if (isSelected)
setForeground(list.getSelectionForeground());
else
setForeground(list.getForeground());
}
if (SubstanceLookAndFeel.isCurrentLookAndFeel() && (list.getLayoutOrientation() == JList.VERTICAL))
SubstanceStripingUtils.applyStripedBackground(list, index, this);
updateItem(list, value);
Insets ins = SubstanceSizeUtils.getListCellRendererInsets(SubstanceSizeUtils.getComponentFontSize(list));
setBorder(new EmptyBorder(ins.top, ins.left, ins.bottom, ins.right));
setOpaque(false);
return this;
}
protected void updateItem(JList list, Object value)
{
if (value instanceof Icon)
{
setIcon((Icon) value);
setText("");
}
else
{
setIcon(null);
setText((value == null) ? "" : value.toString());
setToolTipText((value == null) ? "" : value.toString());
}
setEnabled(list.isEnabled());
setFont(list.getFont());
}
private SubstanceColorScheme getColorSchemeForState(JList list, SubstanceListUI ui, ComponentState state)
{
final UpdateOptimizationInfo updateOptimizationInfo = ui.getUpdateOptimizationInfo();
if (state == ComponentState.ENABLED)
{
if (updateOptimizationInfo == null)
return SubstanceColorSchemeUtilities.getColorScheme(list, state);
return updateOptimizationInfo.getDefaultScheme();
}
if (updateOptimizationInfo == null)
return SubstanceColorSchemeUtilities.getColorScheme(list, ColorSchemeAssociationKind.HIGHLIGHT, state);
return updateOptimizationInfo.getHighlightColorScheme(state);
}
private SubstanceColorScheme getColorSchemeForState(JList list, int index, SubstanceListUI listUI,
ComponentState state)
{
final boolean toUseHighlightKindForCurrState = (index >= 0)
&& (state.isFacetActive(ComponentStateFacet.ROLLOVER) || state
.isFacetActive(ComponentStateFacet.SELECTION));
final UpdateOptimizationInfo updateOptimizationInfo = listUI.getUpdateOptimizationInfo();
if (toUseHighlightKindForCurrState)
{
if (updateOptimizationInfo == null)
return SubstanceColorSchemeUtilities.getColorScheme(list, ColorSchemeAssociationKind.HIGHLIGHT, state);
return updateOptimizationInfo.getHighlightColorScheme(state);
}
if (updateOptimizationInfo == null)
return SubstanceColorSchemeUtilities.getColorScheme(list, state);
return updateOptimizationInfo.getDefaultScheme();
}
}