Skip to content

Commit

Permalink
Animations on tonal icons
Browse files Browse the repository at this point in the history
For #400
  • Loading branch information
kirill-grouchnikov committed Dec 1, 2024
1 parent f21f77d commit 2fe3a83
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ComponentState, StateTransitionTracker.StateContributionInfo> activeStates =
(modelStateInfo == null) ? null :
(useNoSelectionStateContributionMap ? modelStateInfo.getStateNoSelectionContributionMap()
: modelStateInfo.getStateContributionMap());

if (!currState.isDisabled() && (activeStates != null) && (activeStates.size() > 1)) {
for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> 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,
Expand Down

0 comments on commit 2fe3a83

Please sign in to comment.