diff --git a/theming/src/main/java/org/pushingpixels/radiance/theming/api/RadianceSkin.java b/theming/src/main/java/org/pushingpixels/radiance/theming/api/RadianceSkin.java index c963055c9..ac5a5a89f 100644 --- a/theming/src/main/java/org/pushingpixels/radiance/theming/api/RadianceSkin.java +++ b/theming/src/main/java/org/pushingpixels/radiance/theming/api/RadianceSkin.java @@ -39,6 +39,7 @@ import org.pushingpixels.radiance.theming.api.painter.overlay.RadianceOverlayPainter; import org.pushingpixels.radiance.theming.api.palette.ContainerRenderColorTokens; import org.pushingpixels.radiance.theming.api.palette.RadianceColorScheme2; +import org.pushingpixels.radiance.theming.api.palette.TonalSkin; import org.pushingpixels.radiance.theming.api.shaper.RadianceButtonShaper; import org.pushingpixels.radiance.theming.api.trait.RadianceTrait; import org.pushingpixels.radiance.theming.internal.utils.RadianceColorSchemeUtilities; @@ -492,6 +493,14 @@ public final float getHighlightAlpha(Component comp, ComponentState componentSta * @return Color scheme alpha channel. */ public final float getAlpha(Component comp, ComponentState componentState) { + if (this instanceof TonalSkin) { + // TODO: TONAL - finalize this + if (componentState.isDisabled()) { + return 0.4f; + } else { + return 1.0f; + } + } // optimization - if the state does not have hard fallback, and it is not registered in any // scheme bundle with custom alpha, return 1.0 ComponentState fallback = componentState.getHardFallback(); diff --git a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeArrowButtonTransitionAwareIcon.java b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeArrowButtonTransitionAwareIcon.java index 14b4e3ee1..e4ec0b3da 100644 --- a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeArrowButtonTransitionAwareIcon.java +++ b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeArrowButtonTransitionAwareIcon.java @@ -75,6 +75,8 @@ public class BladeArrowButtonTransitionAwareIcon implements Icon { private BladeColorScheme mutableColorScheme = new BladeColorScheme(); + private BladeContainerRenderColorTokens mutableRenderColorTokens = new BladeContainerRenderColorTokens(); + public BladeArrowButtonTransitionAwareIcon(final AbstractButton button, final Dimension iconDimension, final int orientation) { @@ -135,12 +137,12 @@ public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D graphics = (Graphics2D) g.create(); graphics.translate(x, y); if (skin instanceof TonalSkin) { - // TODO: TONAL - add animations - this.delegate.drawColorSchemeIcon(graphics, - BladeUtils.getDefaultColorSchemeDelegate(this.component, - this.colorSchemeAssociationKindDelegate) - .getRenderColorTokensForCurrentState(currState), - iconAlpha); + BladeUtils.populateColorTokens(mutableRenderColorTokens, modelStateInfo, currState, + BladeUtils.getDefaultColorSchemeDelegate(c, + this.colorSchemeAssociationKindDelegate), + false); + + this.delegate.drawColorSchemeIcon(graphics, mutableRenderColorTokens, iconAlpha); } else { BladeUtils.populateColorScheme(mutableColorScheme, modelStateInfo, currState, diff --git a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeHighlightableTransitionAwareIcon.java b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeHighlightableTransitionAwareIcon.java index dd60d58b5..7e2651fa5 100644 --- a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeHighlightableTransitionAwareIcon.java +++ b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeHighlightableTransitionAwareIcon.java @@ -70,6 +70,8 @@ public class BladeHighlightableTransitionAwareIcon implements Icon { private BladeColorScheme mutableColorScheme = new BladeColorScheme(); + private BladeContainerRenderColorTokens mutableRenderColorTokens = new BladeContainerRenderColorTokens(); + private BladeTransitionAwareIcon.ColorSchemeAssociationKindDelegate colorSchemeAssociationKindDelegate; public BladeHighlightableTransitionAwareIcon(final JComponent component, @@ -103,12 +105,12 @@ public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D graphics = (Graphics2D) g.create(); graphics.translate(x, y); if (skin instanceof TonalSkin) { - // TODO: TONAL - add animations - this.delegate.drawColorSchemeIcon(graphics, - BladeUtils.getDefaultColorSchemeDelegate(this.component, - this.colorSchemeAssociationKindDelegate) - .getRenderColorTokensForCurrentState(currState), - iconAlpha); + BladeUtils.populateColorTokens(mutableRenderColorTokens, modelStateInfo, currState, + BladeUtils.getDefaultColorSchemeDelegate(c, + this.colorSchemeAssociationKindDelegate), + false); + + this.delegate.drawColorSchemeIcon(graphics, mutableRenderColorTokens, iconAlpha); } else { // Use HIGHLIGHT when necessary and MARK for the rest BladeUtils.populateColorScheme(mutableColorScheme, modelStateInfo, diff --git a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeTransitionAwareIcon.java b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeTransitionAwareIcon.java index 0d698be91..ee3468f47 100644 --- a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeTransitionAwareIcon.java +++ b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeTransitionAwareIcon.java @@ -91,6 +91,8 @@ public interface ColorSchemeAssociationKindDelegate { private BladeColorScheme mutableColorScheme = new BladeColorScheme(); + private BladeContainerRenderColorTokens mutableRenderColorTokens = new BladeContainerRenderColorTokens(); + public BladeTransitionAwareIcon(final AbstractButton button, Delegate delegate) { this((button == null) ? null : () -> (TransitionAwareUI) button.getUI(), delegate, null); @@ -162,12 +164,12 @@ public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D graphics = (Graphics2D) g.create(); graphics.translate(x, y); if (skin instanceof TonalSkin) { - // TODO: TONAL - add animations - this.delegate.drawColorSchemeIcon(graphics, + BladeUtils.populateColorTokens(mutableRenderColorTokens, modelStateInfo, currState, BladeUtils.getDefaultColorSchemeDelegate(c, - this.colorSchemeAssociationKindDelegate) - .getRenderColorTokensForCurrentState(currState), - iconAlpha); + this.colorSchemeAssociationKindDelegate), + false); + + this.delegate.drawColorSchemeIcon(graphics, mutableRenderColorTokens, iconAlpha); } else { BladeUtils.populateColorScheme(mutableColorScheme, modelStateInfo, currState, BladeUtils.getDefaultColorSchemeDelegate(c, diff --git a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeUtils.java b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeUtils.java index 21668dd4e..a8bd3dfb0 100644 --- a/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeUtils.java +++ b/theming/src/main/java/org/pushingpixels/radiance/theming/internal/blade/BladeUtils.java @@ -472,6 +472,95 @@ public static void populateColorScheme( bladeColorScheme.displayName = nameBuilder.toString(); } + public static void populateColorTokens( + BladeContainerRenderColorTokens bladeRenderColorTokens, + StateTransitionTracker.ModelStateInfo modelStateInfo, + ComponentState currState, + ColorSchemeDelegate colorSchemeDelegate, + boolean useNoSelectionStateContributionMap) { + if (!SwingUtilities.isEventDispatchThread()) { + UiThreadingViolationException uiThreadingViolationError = new UiThreadingViolationException( + "Color scheme population must be done on Event Dispatch Thread"); + uiThreadingViolationError.printStackTrace(System.err); + throw uiThreadingViolationError; + } + + StringBuilder nameBuilder = new StringBuilder(); + + ContainerRenderColorTokens currColorTokens = + colorSchemeDelegate.getRenderColorTokensForCurrentState(currState); + + Color containerLowest = currColorTokens.getContainerColorTokens().getContainerLowest(); + Color containerLow = currColorTokens.getContainerColorTokens().getContainerLow(); + Color container = currColorTokens.getContainerColorTokens().getContainer(); + Color containerHigh = currColorTokens.getContainerColorTokens().getContainerHigh(); + Color containerHighest = currColorTokens.getContainerColorTokens().getContainerHighest(); + Color onContainer = currColorTokens.getOnContainerColorTokens().getOnContainer(); + Color onContainerVariant = currColorTokens.getOnContainerColorTokens().getOnContainerVariant(); + Color containerOutline = currColorTokens.getContainerOutlineColorTokens().getContainerOutline(); + Color containerOutlineVariant = currColorTokens.getContainerOutlineColorTokens().getContainerOutlineVariant(); + + nameBuilder.append(currColorTokens.hashCode()); + + Map activeStates = + (modelStateInfo == null) ? null : + (useNoSelectionStateContributionMap ? modelStateInfo.getStateNoSelectionContributionMap() + : modelStateInfo.getStateContributionMap()); + + if (!currState.isDisabled() && (activeStates != null) && (activeStates.size() > 1)) { + for (Map.Entry activeEntry : activeStates.entrySet()) { + if (activeEntry.getKey() == currState) { + // Already accounted for the currently active state + continue; + } + float amount = activeEntry.getValue().getContribution(); + if (amount == 0.0f) { + // Skip a zero-amount contribution + continue; + } + // Get the color tokens that match the contribution state + ContainerRenderColorTokens contributionColorTokens = + colorSchemeDelegate.getRenderColorTokensForActiveState(activeEntry.getKey()); + + // And interpolate the colors + containerLowest = RadianceColorUtilities.getInterpolatedColor(containerLowest, + contributionColorTokens.getContainerColorTokens().getContainerLowest(), 1.0f - amount); + containerLow = RadianceColorUtilities.getInterpolatedColor(containerLow, + contributionColorTokens.getContainerColorTokens().getContainerLow(), 1.0f - amount); + container = RadianceColorUtilities.getInterpolatedColor(container, + contributionColorTokens.getContainerColorTokens().getContainer(), 1.0f - amount); + containerHigh = RadianceColorUtilities.getInterpolatedColor(containerHigh, + contributionColorTokens.getContainerColorTokens().getContainerHigh(), 1.0f - amount); + containerHighest = RadianceColorUtilities.getInterpolatedColor(containerHighest, + contributionColorTokens.getContainerColorTokens().getContainerHighest(), 1.0f - amount); + onContainer = RadianceColorUtilities.getInterpolatedColor(onContainer, + contributionColorTokens.getOnContainerColorTokens().getOnContainer(), 1.0f - amount); + onContainerVariant = RadianceColorUtilities.getInterpolatedColor(onContainerVariant, + contributionColorTokens.getOnContainerColorTokens().getOnContainerVariant(), 1.0f - amount); + containerOutline = RadianceColorUtilities.getInterpolatedColor(containerOutline, + contributionColorTokens.getContainerOutlineColorTokens().getContainerOutline(), 1.0f - amount); + containerOutlineVariant = RadianceColorUtilities.getInterpolatedColor(containerOutlineVariant, + contributionColorTokens.getContainerOutlineColorTokens().getContainerOutlineVariant(), 1.0f - amount); + + nameBuilder.append(", [").append(contributionColorTokens.hashCode()).append(":") + .append(amount).append("]"); + } + } + + // Update the mutable color scheme with the interpolated colors + bladeRenderColorTokens.containerLowest = containerLowest; + bladeRenderColorTokens.containerLow = containerLow; + bladeRenderColorTokens.container = container; + bladeRenderColorTokens.containerHigh = containerHigh; + bladeRenderColorTokens.containerHighest = containerHighest; + bladeRenderColorTokens.onContainer = onContainer; + bladeRenderColorTokens.onContainerVariant = onContainerVariant; + bladeRenderColorTokens.containerOutline = containerOutline; + bladeRenderColorTokens.containerOutlineVariant = containerOutlineVariant; + + bladeRenderColorTokens.combinedName = nameBuilder.toString(); + } + public static void populateColorScheme( BladeColorScheme bladeColorScheme, JTabbedPane tabbedPane, int tabIndex,