Skip to content

Commit

Permalink
fix: Don't highlight frames that are not in a focused flame
Browse files Browse the repository at this point in the history
Fix #171
  • Loading branch information
bric3 committed May 21, 2024
1 parent 366065f commit 6e08baf
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ public static boolean isBright(Color color) {

/**
* Produce a new color with the given alpha value.
*
*
* @param color The color
* @param alpha The alpha value [0; 1]
* @return The new color
Expand Down Expand Up @@ -491,6 +491,35 @@ public static Color dim(Color color) {
);
}

/**
* Half-Dim the given color and returns a {@link #darkMode} aware color.
*
* @param color The color to half-dim
* @return The half-dimmed color ({@link #darkMode} aware)
*/
public static Color halfDim(Color color) {
var hslaLight = hslaComponents(color);
var hslaDark = Arrays.copyOf(hslaLight, hslaLight.length);

{
// dark mode
// if color is grayish, keep the saturation, otherwise set it to 0.2
hslaDark[S] = hslaDark[S] < 0.1f ? hslaDark[S] : 0.2f;
hslaDark[L] = 0.48f;
}
{
// light mode
// if color is grayish, keep the saturation, otherwise set it to 0.4
hslaLight[S] = hslaLight[S] < 0.2 ? hslaLight[S] : 0.4f;
hslaLight[L] = 0.68f;
}

return new LightDarkColor(
hsla(hslaLight[H], hslaLight[S], hslaLight[L], hslaLight[ALPHA]),
hsla(hslaDark[H], hslaDark[S], hslaDark[L], hslaDark[ALPHA])
);
}

private static final float DARKER_FACTOR = 0.7f;
private static final float BRIGHTER_FACTOR = 1 / DARKER_FACTOR;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isFocusedFrame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isFocusing;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHighlightedFrame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHighlighting;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHovered;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHoveredSibling;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isInFocusedFlame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isMinimapMode;

/**
Expand Down Expand Up @@ -68,6 +68,7 @@ public class DimmingFrameColorProvider<T> implements FrameColorProvider<@NotNull
private final ColorModel reusedColorModelForMinimap = new ColorModel();

private final ConcurrentHashMap<Color, Color> dimmedColorCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Color, Color> halfDimmedColorCache = new ConcurrentHashMap<>();

private Color rootBackGroundColor = ROOT_BACKGROUND_COLOR;
private Color dimmedTextColor = DIMMED_TEXT_COLOR;
Expand Down Expand Up @@ -105,9 +106,17 @@ public ColorModel getColors(@NotNull FrameBox<@NotNull T> frame, int flags) {
);
}

if (!rootNode && shouldDim(flags)) {
backgroundColor = dimmedBackground(backgroundColor);
boolean shouldDimFocusedFlame = isFocusing(flags) && isInFocusedFlame(flags) && !isHighlightedFrame(flags);
if (!rootNode && shouldDim(flags) && !shouldDimFocusedFlame) {
backgroundColor = dimmedBackground(baseBackgroundColor);
foreground = dimmedTextColor;
} else if (!rootNode && shouldDimFocusedFlame) {
backgroundColor = halfDimmedBackground(baseBackgroundColor);
if (isHighlighting(flags) && !isHighlightedFrame(flags)) {
foreground = dimmedTextColor;
} else {
foreground = Colors.withAlpha(Colors.foregroundColor(backgroundColor), Colors.isDarkMode() ? 0.61f : 0.74f);
}
} else {
foreground = Colors.foregroundColor(backgroundColor);
}
Expand Down Expand Up @@ -137,7 +146,7 @@ public ColorModel getColors(@NotNull FrameBox<@NotNull T> frame, int flags) {
private @NotNull Color hoverBackground(@NotNull Color backgroundColor) {
return Colors.isDarkMode() ?
Colors.brighter(backgroundColor, 1.1f, 0.95f) :
Colors.darker(backgroundColor, 1.25f);
Colors.darker(backgroundColor, 1.15f);
}

/**
Expand All @@ -157,37 +166,38 @@ public ColorModel getColors(@NotNull FrameBox<@NotNull T> frame, int flags) {
* @return The dimmed color.
*/
protected @NotNull Color dimmedBackground(@NotNull Color backgroundColor) {
return cachedDim(backgroundColor);
return dimmedColorCache.computeIfAbsent(backgroundColor, Colors::dim);
}

private @NotNull Color halfDimmedBackground(Color backgroundColor) {
return halfDimmedColorCache.computeIfAbsent(backgroundColor, Colors::halfDim);
}

/**
* Dim only if not highlighted or not focused
* <p>
* - highlighting and not highlighted => dim
* - focusing and not focused => dim
* - highlighting and focusing
* - highlighted => nope
* - focusing => nope
* <ul>
* <li>highlighting and not highlighted frames => dim</li>
* <li>focusing and not in focused flames => dim</li>
* <li>highlighting and focusing and in focused flame => dim</li>
* <li>highlighting and focusing and not focused flame => nope</li>
* <li>highlighted => nope</li>
* <li>focusing => nope</li>
* </ul>
*/
private boolean shouldDim(int flags) {
var highlighting = isHighlighting(flags);
var highlightedFrame = isHighlightedFrame(flags);
var focusing = isFocusing(flags);
var focusedFrame = isFocusedFrame(flags);

var inFocusedFlame = isInFocusedFlame(flags);

var dimmedForHighlighting = highlighting && !highlightedFrame;
var dimmedForFocus = focusing && !focusedFrame;

var dimmedForFocus = focusing && !inFocusedFlame;

return (dimmedForHighlighting || dimmedForFocus)
&& !(highlighting
&& focusing
&& (highlightedFrame || focusedFrame));
}

private @NotNull Color cachedDim(@NotNull Color color) {
return dimmedColorCache.computeIfAbsent(color, Colors::dim);
&& !(focusing && inFocusedFlame) // don't dim frames that are in focused flame
// && !(highlighting && highlightedFrame) // this dim highlighted that are not in focused flame
;
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ public int computeVisibleFlamegraphMinimapHeight(int thumbnailWidth) {
assert thumbnailWidth > 0 : "minimap width must be superior to 0";

// Somewhat it is a best-effort to draw something that shows
// something representative. The canvas recompute this, if its
// size change so there's a chance the minimap can be updated
// something representative. The canvas recomputes this value if its
// size changes, so there's a chance the minimap can be updated
// with higher details (previously invisible frames)
return visibleDepth * minimapFrameBoxHeight;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ public void setModel(@NotNull FrameModel<@NotNull T> frameModel) {
* <li>The frame background and foreground colors.</li>
* </ul>
* <p>
* Deprecated, use {@link #setFrameRender(FrameRenderer)} with a ${@link DefaultFrameRenderer}.
* Deprecated, use {@link #setFrameRender(FrameRenderer)} with a {@link DefaultFrameRenderer}.
*
* @param frameTextsProvider The function to display label in frames.
* @param frameColorProvider The frame to background color function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
import java.util.Objects;
import java.util.function.Function;

import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isFocusedFrame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isFocusing;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHighlightedFrame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHighlighting;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHovered;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isInFocusedFlame;

/**
* Strategy for choosing the colors of a frame.
Expand Down Expand Up @@ -91,6 +91,16 @@ public ColorModel copy() {
@NotNull
ColorModel getColors(@NotNull FrameBox<@NotNull T> frame, int flags) ;


/**
* Creates a default color provider that uses the given function to compute the base color of a frame.
*
* @param frameBaseColorFunction The function that computes the base color of a frame.
* @param <T> The type of the frame node (depends on the source of profiling data).
* @return A default color provider.
*
* @see DimmingFrameColorProvider
*/
@NotNull
static <T> FrameColorProvider<@NotNull T> defaultColorProvider(@NotNull Function<@NotNull FrameBox<@NotNull T>, @NotNull Color> frameBaseColorFunction) {
Objects.requireNonNull(frameBaseColorFunction, "frameColorFunction");
Expand All @@ -105,18 +115,26 @@ public ColorModel copy() {
@Override
@NotNull
public ColorModel getColors(@NotNull FrameBox<@NotNull T> frame, int flags) {
Color baseBackgroundColor = frameBaseColorFunction.apply(frame);
Color backgroundColor = baseBackgroundColor;
var baseBackgroundColor = frameBaseColorFunction.apply(frame);
var backgroundColor = baseBackgroundColor;

if (isFocusing(flags) && !isFocusedFrame(flags)) {
if (isFocusing(flags) && !isInFocusedFlame(flags)) {
backgroundColor = Colors.blend(baseBackgroundColor, Colors.translucent_black_80);
}

if (isHighlighting(flags)) {
backgroundColor = Colors.isDarkMode() ?
Colors.blend(backgroundColor, Colors.translucent_black_B0) :
Colors.blend(backgroundColor, Color.WHITE);

if (isHighlightedFrame(flags)) {
backgroundColor = baseBackgroundColor;
if (!isFocusing(flags)) {
backgroundColor = baseBackgroundColor;
} else if (isFocusing(flags) && isInFocusedFlame(flags)) {
backgroundColor = baseBackgroundColor;
}

// backgroundColor = baseBackgroundColor;
}
}
if (isHovered(flags)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

import java.awt.*;

import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isFocusing;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isHighlightedFrame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isInFocusedFlame;
import static io.github.bric3.fireplace.flamegraph.FrameRenderingFlags.isPartialFrame;

/**
Expand Down Expand Up @@ -75,10 +77,14 @@ public Font getFont(@Nullable FrameBox<@NotNull T> frame, int flags) {
return bold;
}

// if no focused frame, highlight any frame matching isHighlightedFrame
// else if focused frame, highlight the frame matching only if isFocusing
if (isHighlightedFrame(flags)) {
// when parent frames are larger than view port
return isPartialFrame(flags) ? italicBold : bold;
if (!isFocusing(flags) || isInFocusedFlame(flags)) {
return isPartialFrame(flags) ? italicBold : bold;
}
}

// when parent frames are larger than view port
return isPartialFrame(flags) ? italic : regular;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public abstract class FrameRenderingFlags {
public static final int PARTIAL_FRAME = 1 << 7;


public static int toFlags(
static int toFlags(
boolean minimapMode,
boolean highlightingOn,
boolean highlighted,
Expand Down Expand Up @@ -122,7 +122,7 @@ public static boolean isFocusing(int flags) {
return (flags & FOCUSING) != 0;
}

public static boolean isFocusedFrame(int flags) {
public static boolean isInFocusedFlame(int flags) {
return (flags & FOCUSED_FRAME) != 0;
}

Expand Down

0 comments on commit 6e08baf

Please sign in to comment.