Skip to content

[CQ] remove experimental BadgeIcon dependency #8365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ intellijPlatform {
VerifyPluginTask.FailureLevel.COMPATIBILITY_PROBLEMS,
// VerifyPluginTask.FailureLevel.DEPRECATED_API_USAGES, // https://github.com/flutter/flutter-intellij/issues/7718
// VerifyPluginTask.FailureLevel.SCHEDULED_FOR_REMOVAL_API_USAGES,
// VerifyPluginTask.FailureLevel.EXPERIMENTAL_API_USAGES,
VerifyPluginTask.FailureLevel.EXPERIMENTAL_API_USAGES,
// VerifyPluginTask.FailureLevel.INTERNAL_API_USAGES,
// VerifyPluginTask.FailureLevel.OVERRIDE_ONLY_API_USAGES,
VerifyPluginTask.FailureLevel.NON_EXTENDABLE_API_USAGES,
Expand Down
54 changes: 44 additions & 10 deletions src/io/flutter/toolwindow/ToolWindowBadgeUpdater.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,81 @@
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.BadgeIcon;
import io.flutter.run.common.RunMode;
import io.flutter.run.daemon.FlutterApp;

import java.awt.Color;
import java.awt.Paint;
import javax.swing.*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression that we avoid * imports, but I'm not sure if that's enforced somewhere in java settings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting! This is what the IDE did on-save. Doing a quick grep I see we've got 104+ * imports in 74+ files so we're definitely not consistently avoiding them.

That could be this inspection?

https://www.jetbrains.com/help/inspectopedia/OnDemandImport.html

Happy to discuss enabling!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick search suggests to me it is better to avoid * imports (avoids potential naming conflicts, avoids indexing classes that aren't needed). Is enabling the inspection something we do individually or can we save it to the repository?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking a bit about it, I tend to agree. Wildcard imports are probably best to avoid. Could you add some discussion to #8098?

We do have a checked in inspection set and think we should probably enable it there but we should discuss. It would also be great to get the inspections run in the CI, if not as part of the verifier, as a separate task. I've poked at that a bit but got distracted. (Some info here: https://www.jetbrains.com/help/idea/command-line-code-inspector.html#inspection-profiles.)

import java.awt.*;
import java.util.Objects;
import javax.swing.Icon;

public class ToolWindowBadgeUpdater {
public static final Paint BADGE_PAINT = Color.decode("#5ca963");
public static final Color BADGE_PAINT = Color.decode("#5ca963");

/**
* Updates the tool window icons for RUN or DEBUG mode with a green badge.
*
* @param app The FlutterApp instance running in a given mode.
* @param app The FlutterApp instance running in a given mode.
* @param project The current IntelliJ project context.
*/
public static void updateBadgedIcon(FlutterApp app, Project project) {
final ToolWindowManager manager = ToolWindowManager.getInstance(Objects.requireNonNull(project));
final ToolWindow runToolWindow = manager.getToolWindow(ToolWindowId.RUN);
final ToolWindow debugToolWindow = manager.getToolWindow(ToolWindowId.DEBUG);

if(Objects.requireNonNull(app).getMode() == RunMode.RUN) {
if (Objects.requireNonNull(app).getMode() == RunMode.RUN) {
if (runToolWindow != null) {
manager.invokeLater(() -> {
Icon baseIcon = AllIcons.Toolwindows.ToolWindowRun;
BadgeIcon iconWithBadge = new BadgeIcon(baseIcon, BADGE_PAINT);

runToolWindow.setIcon(iconWithBadge);
});
}
}
else if(app.getMode() == RunMode.DEBUG) {
else if (app.getMode() == RunMode.DEBUG) {
manager.invokeLater(() -> {
Icon baseIcon = AllIcons.Toolwindows.ToolWindowDebugger;
BadgeIcon iconWithBadge = new BadgeIcon(baseIcon, BADGE_PAINT);

Objects.requireNonNull(debugToolWindow).setIcon(iconWithBadge);
});
}
}

private static class BadgeIcon implements Icon {
private final Icon baseIcon;
private final Color overlayColor;
private static final float alpha = 1.0F;

public BadgeIcon(Icon baseIcon, Color overlayColor) {
this.baseIcon = baseIcon;
this.overlayColor = overlayColor;
}

@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
baseIcon.paintIcon(c, g, x, y);

Graphics2D g2d = (Graphics2D)g.create();
try {
g2d.translate(x, y);

g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));

g2d.setColor(overlayColor);
g2d.fillRect(0, 0, getIconWidth(), getIconHeight());
}
finally {
g2d.dispose();
}
}

@Override
public int getIconWidth() {
return baseIcon.getIconWidth();
}

@Override
public int getIconHeight() {
return baseIcon.getIconHeight();
}
}
}