Skip to content

Commit

Permalink
First pass for default visuals of active states
Browse files Browse the repository at this point in the history
For #400
  • Loading branch information
kirill-grouchnikov committed Dec 1, 2024
1 parent 2fe3a83 commit 028a961
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ public final ContainerRenderColorTokens getColorRenderTokens(Component comp,
throw new IllegalStateException("Color scheme shouldn't be null here. Please "
+ "report this issue");
}
return componentState.isActive() ? registered.getPrimaryContainerTokens()

return componentState.isActive() ? registered.getStateRenderTokens(componentState)
: registered.getMutedContainerTokens();
}
}
Expand All @@ -432,7 +433,9 @@ public final ContainerRenderColorTokens getColorRenderTokens(Component comp,
if (registered == null) {
throw new IllegalStateException("Color scheme shouldn't be null here. Please report " + "this issue");
}
return componentState.isActive() ? registered.getPrimaryContainerTokens()


return componentState.isActive() ? registered.getStateRenderTokens(componentState)
: registered.getMutedContainerTokens();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
package org.pushingpixels.radiance.theming.api.palette;

import org.pushingpixels.radiance.theming.api.ComponentState;
import org.pushingpixels.radiance.theming.internal.utils.RadianceColorUtilities;

import java.awt.*;
import java.util.HashMap;

public class ColorSchemeUtils {
public static RadianceColorScheme2 getLightColorScheme(Palettes palettes) {
Expand Down Expand Up @@ -295,6 +297,8 @@ public Color getContainerOutlineVariant() {
};

return new RadianceColorScheme2() {
private HashMap<ComponentState, ContainerRenderColorTokens> stateTokens = new HashMap<>();

@Override
public Color getSurface() {
return paletteColorResolver.getSurface(palettes);
Expand Down Expand Up @@ -332,7 +336,71 @@ public ContainerRenderColorTokens getPrimaryContainerTokens() {

@Override
public ContainerRenderColorTokens getStateRenderTokens(ComponentState componentState) {
return null;
// TODO: TONAL - configurable at the skin definition level
ContainerRenderColorTokens defaultActive = this.getPrimaryContainerTokens();
// TODO: TONAL - configurable at the component state level
int mixinAmount = 40;
if (componentState == ComponentState.PRESSED_UNSELECTED) {
// surface dim on top of muted
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
getMutedContainerTokens(),
getSurfaceDim(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.PRESSED_SELECTED) {
// surface dim on top of active
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
defaultActive,
getSurfaceDim(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.SELECTED) {
return defaultActive;
}
if (componentState == ComponentState.ROLLOVER_UNSELECTED) {
// surface on top of muted
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
getMutedContainerTokens(),
getSurface(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.ROLLOVER_SELECTED) {
// surface bright on top of active
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
defaultActive,
getSurfaceBright(),
mixinAmount));
}
return stateTokens.get(componentState);
}

ComponentState hardFallback = componentState.getHardFallback();
if (hardFallback != null) {
return this.getStateRenderTokens(hardFallback);
}

if (componentState == ComponentState.ENABLED) {
return getMutedContainerTokens();
}
if (componentState.isDisabled()) {
// TODO: TONAL - revisit
return getMutedContainerTokens();
}
return defaultActive;
}
};
}
Expand Down Expand Up @@ -598,6 +666,8 @@ public Color getContainerOutlineVariant() {
};

return new RadianceColorScheme2() {
private HashMap<ComponentState, ContainerRenderColorTokens> stateTokens = new HashMap<>();

@Override
public Color getSurface() {
return paletteColorResolver.getSurface(palettes);
Expand Down Expand Up @@ -635,7 +705,156 @@ public ContainerRenderColorTokens getPrimaryContainerTokens() {

@Override
public ContainerRenderColorTokens getStateRenderTokens(ComponentState componentState) {
return null;
// TODO: TONAL - configurable at the skin definition level
ContainerRenderColorTokens defaultActive = this.getPrimaryContainerTokens();
// TODO: TONAL - configurable at the component state level
int mixinAmount = 40;
if (componentState == ComponentState.PRESSED_UNSELECTED) {
// surface dim on top of muted
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
getMutedContainerTokens(),
getSurfaceDim(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.PRESSED_SELECTED) {
// surface dim on top of active
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
defaultActive,
getSurfaceDim(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.SELECTED) {
return defaultActive;
}
if (componentState == ComponentState.ROLLOVER_UNSELECTED) {
// surface on top of muted
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
getMutedContainerTokens(),
getSurface(),
mixinAmount));
}
return stateTokens.get(componentState);
}
if (componentState == ComponentState.ROLLOVER_SELECTED) {
// surface bright on top of active
if (!stateTokens.containsKey(componentState)) {
stateTokens.put(componentState,
ColorSchemeUtils.overlay(
defaultActive,
getSurfaceBright(),
mixinAmount));
}
return stateTokens.get(componentState);
}

ComponentState hardFallback = componentState.getHardFallback();
if (hardFallback != null) {
return this.getStateRenderTokens(hardFallback);
}

if (componentState == ComponentState.ENABLED) {
return getMutedContainerTokens();
}
if (componentState.isDisabled()) {
// TODO: TONAL - revisit
return getMutedContainerTokens();
}
return defaultActive;
}
};
}

private static ContainerRenderColorTokens overlay(ContainerRenderColorTokens original, Color overlay,
int overlayAmount) {
Color overlayWithAlpha = RadianceColorUtilities.getAlphaColor(overlay, overlayAmount);

// Apply overlay on the container tokens
Color containerLowest = RadianceColorUtilities.overlayColor(
original.getContainerColorTokens().getContainerLowest(), overlayWithAlpha);
Color containerLow = RadianceColorUtilities.overlayColor(
original.getContainerColorTokens().getContainerLow(), overlayWithAlpha);
Color container = RadianceColorUtilities.overlayColor(
original.getContainerColorTokens().getContainer(), overlayWithAlpha);
Color containerHigh = RadianceColorUtilities.overlayColor(
original.getContainerColorTokens().getContainerHigh(), overlayWithAlpha);
Color containerHighest = RadianceColorUtilities.overlayColor(
original.getContainerColorTokens().getContainerHighest(), overlayWithAlpha);

// Leave on container and container outline tokens as they are
Color onContainer = original.getOnContainerColorTokens().getOnContainer();
Color onContainerVariant = original.getOnContainerColorTokens().getOnContainerVariant();
Color containerOutline = original.getContainerOutlineColorTokens().getContainerOutline();
Color containerOutlineVariant = original.getContainerOutlineColorTokens().getContainerOutlineVariant();

return new ContainerRenderColorTokens() {
@Override
public ContainerColorTokens getContainerColorTokens() {
return new ContainerColorTokens() {
@Override
public Color getContainerLowest() {
return containerLowest;
}

@Override
public Color getContainerLow() {
return containerLow;
}

@Override
public Color getContainer() {
return container;
}

@Override
public Color getContainerHigh() {
return containerHigh;
}

@Override
public Color getContainerHighest() {
return containerHighest;
}
};
}

@Override
public OnContainerColorTokens getOnContainerColorTokens() {
return new OnContainerColorTokens() {
@Override
public Color getOnContainer() {
return onContainer;
}

@Override
public Color getOnContainerVariant() {
return onContainerVariant;
}
};
}

@Override
public ContainerOutlineColorTokens getContainerOutlineColorTokens() {
return new ContainerOutlineColorTokens() {
@Override
public Color getContainerOutline() {
return containerOutline;
}

@Override
public Color getContainerOutlineVariant() {
return containerOutlineVariant;
}
};
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,5 +684,4 @@ public static void populateColorScheme(

bladeColorScheme.displayName = nameBuilder.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,33 @@ public static Color getInterpolatedColor(Color color1, Color color2,
return new Color(getInterpolatedRGB(color1, color2, color1Likeness), true);
}

public static Color overlayColor(Color base, Color overlay) {
float baseAlpha = base.getAlpha() / 255.0f;
float overlayAlpha = overlay.getAlpha() / 255.0f;
float finalAlpha = overlayAlpha + baseAlpha * (1.0f - overlayAlpha);

if (finalAlpha == 0.0f) {
return new Color(0, 0, 0, 0);
}

int baseR = base.getRed();
int overlayR = overlay.getRed();
int finalR = (int) ((overlayR * overlayAlpha +
(baseR * baseAlpha) * (1.0f - overlayAlpha)) / finalAlpha);

int baseG = base.getGreen();
int overlayG = overlay.getGreen();
int finalG = (int) ((overlayG * overlayAlpha +
(baseG * baseAlpha) * (1.0f - overlayAlpha)) / finalAlpha);

int baseB = base.getBlue();
int overlayB = overlay.getBlue();
int finalB = (int) ((overlayB * overlayAlpha +
(baseB * baseAlpha) * (1.0f - overlayAlpha)) / finalAlpha);

return new Color(finalR, finalG, finalB, (int) (255 * finalAlpha));
}

/**
* Inverts the specified color.
*
Expand Down

0 comments on commit 028a961

Please sign in to comment.