org.pushingpixels.radiance.theming.internal.utils.combo.ComboBoxBackgroundDelegate Maven / Gradle / Ivy
/*
* Copyright (c) 2005-2021 Radiance 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 the copyright holder 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.radiance.theming.internal.utils.combo;
import org.pushingpixels.radiance.common.api.RadianceCommonCortex;
import org.pushingpixels.radiance.theming.api.ComponentState;
import org.pushingpixels.radiance.theming.api.RadianceThemingSlices;
import org.pushingpixels.radiance.theming.api.colorscheme.RadianceColorScheme;
import org.pushingpixels.radiance.theming.api.painter.border.RadianceBorderPainter;
import org.pushingpixels.radiance.theming.api.painter.fill.RadianceFillPainter;
import org.pushingpixels.radiance.theming.internal.animation.StateTransitionTracker;
import org.pushingpixels.radiance.theming.internal.animation.TransitionAwareUI;
import org.pushingpixels.radiance.theming.internal.utils.*;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
/**
* Delegate class for painting backgrounds of buttons in Radiance look and feel. This class
* is for internal use only.
*
* @author Kirill Grouchnikov
*/
public class ComboBoxBackgroundDelegate {
/**
* Cache for background images.
*/
private static LazyResettableHashMap regularBackgrounds = new LazyResettableHashMap<>(
"ComboBoxBackgroundDelegate");
public static BufferedImage getFullAlphaBackground(JComboBox combo,
RadianceFillPainter fillPainter, RadianceBorderPainter borderPainter, int width,
int height) {
double scale = RadianceCommonCortex.getScaleFactor(combo);
TransitionAwareUI transitionAwareUI = (TransitionAwareUI) combo.getUI();
StateTransitionTracker.ModelStateInfo modelStateInfo = transitionAwareUI
.getTransitionTracker().getModelStateInfo();
ComponentState currState = modelStateInfo.getCurrModelState();
Map activeStates = modelStateInfo
.getStateContributionMap();
int comboFontSize = RadianceSizeUtils.getComponentFontSize(combo);
float radius = RadianceSizeUtils.getClassicButtonCornerRadius(comboFontSize);
RadianceColorScheme baseFillScheme = RadianceColorSchemeUtilities.getColorScheme(combo,
currState);
RadianceColorScheme baseBorderScheme = RadianceColorSchemeUtilities.getColorScheme(combo,
RadianceThemingSlices.ColorSchemeAssociationKind.BORDER, currState);
ImageHashMapKey keyBase = RadianceCoreUtilities.getScaleAwareHashKey(
scale, width, height,
baseFillScheme.getDisplayName(), baseBorderScheme.getDisplayName(),
fillPainter.getDisplayName(), borderPainter.getDisplayName(),
combo.getClass().getName(), radius, comboFontSize);
BufferedImage layerBase = regularBackgrounds.get(keyBase);
if (layerBase == null) {
layerBase = createBackgroundImage(combo, fillPainter, borderPainter, width,
height, baseFillScheme, baseBorderScheme, radius);
regularBackgrounds.put(keyBase, layerBase);
}
if (currState.isDisabled() || (activeStates.size() == 1)) {
return layerBase;
}
BufferedImage result = RadianceCoreUtilities.getBlankUnscaledImage(layerBase);
Graphics2D g2d = result.createGraphics();
// draw the base layer
g2d.drawImage(layerBase, 0, 0, layerBase.getWidth(), layerBase.getHeight(), null);
// System.out.println("\nPainting base state " + currState);
// draw the other active layers
for (Map.Entry activeEntry : activeStates
.entrySet()) {
ComponentState activeState = activeEntry.getKey();
// System.out.println("Painting state " + activeState + "[curr is "
// + currState + "] with " + activeEntry.getValue());
if (activeState == currState)
continue;
float stateContribution = activeEntry.getValue().getContribution();
if (stateContribution > 0.0f) {
g2d.setComposite(AlphaComposite.SrcOver.derive(stateContribution));
RadianceColorScheme fillScheme = RadianceColorSchemeUtilities
.getColorScheme(combo, activeState);
RadianceColorScheme borderScheme = RadianceColorSchemeUtilities
.getColorScheme(combo, RadianceThemingSlices.ColorSchemeAssociationKind.BORDER, activeState);
ImageHashMapKey key = RadianceCoreUtilities.getScaleAwareHashKey(
scale, width, height,
fillScheme.getDisplayName(), borderScheme.getDisplayName(),
fillPainter.getDisplayName(), borderPainter.getDisplayName(),
combo.getClass().getName(), radius, comboFontSize);
BufferedImage layer = regularBackgrounds.get(key);
if (layer == null) {
layer = createBackgroundImage(combo, fillPainter, borderPainter, width,
height, fillScheme, borderScheme, radius);
regularBackgrounds.put(key, layer);
}
g2d.drawImage(layer, 0, 0, layer.getWidth(), layer.getHeight(), null);
}
}
g2d.dispose();
return result;
}
private static BufferedImage createBackgroundImage(JComboBox combo,
RadianceFillPainter fillPainter,
RadianceBorderPainter borderPainter, int width, int height,
RadianceColorScheme fillScheme, RadianceColorScheme borderScheme, float radius) {
double scale = RadianceCommonCortex.getScaleFactor(combo);
float borderDelta = RadianceSizeUtils.getBorderStrokeWidth(combo) / 2.0f;
Shape contour = RadianceOutlineUtilities.getBaseOutline(width, height, radius, null,
borderDelta);
BufferedImage newBackground = RadianceCoreUtilities.getBlankImage(scale, width, height);
Graphics2D finalGraphics = (Graphics2D) newBackground.getGraphics();
fillPainter.paintContourBackground(finalGraphics, combo, width, height, contour, false,
fillScheme, true);
float borderThickness = RadianceSizeUtils.getBorderStrokeWidth(combo);
Shape contourInner = borderPainter.isPaintingInnerContour()
? RadianceOutlineUtilities.getBaseOutline(width, height, radius - borderThickness,
null, borderDelta + borderThickness)
: null;
borderPainter.paintBorder(finalGraphics, combo, width, height, contour, contourInner,
borderScheme);
return newBackground;
}
/**
* Simple constructor.
*/
public ComboBoxBackgroundDelegate() {
super();
}
public void updateBackground(Graphics g, JComboBox combo) {
// failsafe for LAF change
if (!RadianceCoreUtilities.isCurrentLookAndFeel())
return;
int width = combo.getWidth();
int height = combo.getHeight();
int y = 0;
RadianceFillPainter fillPainter = RadianceCoreUtilities.getFillPainter(combo);
RadianceBorderPainter borderPainter = RadianceCoreUtilities.getBorderPainter(combo);
BufferedImage bgImage = getFullAlphaBackground(combo, fillPainter, borderPainter, width, height);
TransitionAwareUI transitionAwareUI = (TransitionAwareUI) combo.getUI();
StateTransitionTracker stateTransitionTracker = transitionAwareUI.getTransitionTracker();
StateTransitionTracker.ModelStateInfo modelStateInfo = stateTransitionTracker
.getModelStateInfo();
Map activeStates = modelStateInfo
.getStateContributionMap();
// Two special cases here:
// 1. Combobox has flat appearance.
// 2. Combobox is disabled.
// For both cases, we need to set custom translucency.
boolean isFlat = RadianceCoreUtilities.hasFlatAppearance(combo, false);
boolean isSpecial = isFlat || !combo.isEnabled();
float extraAlpha = 1.0f;
if (isSpecial) {
if (isFlat) {
// Special handling of flat combos
extraAlpha = 0.0f;
for (Map.Entry activeEntry : activeStates
.entrySet()) {
ComponentState activeState = activeEntry.getKey();
if (activeState.isDisabled())
continue;
if (activeState == ComponentState.ENABLED)
continue;
extraAlpha += activeEntry.getValue().getContribution();
}
} else {
if (!combo.isEnabled()) {
extraAlpha = RadianceColorSchemeUtilities.getAlpha(combo,
modelStateInfo.getCurrModelState());
}
}
}
if (extraAlpha > 0.0f) {
Graphics2D graphics = (Graphics2D) g.create();
graphics.setComposite(WidgetUtilities.getAlphaComposite(combo, extraAlpha, g));
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
RadianceCommonCortex.drawImageWithScale(graphics, RadianceCommonCortex.getScaleFactor(combo),
bgImage, 0, y);
graphics.dispose();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy