Skip to content

Match IntelliJ's zoom setting in the embedded DevTools panels #7933

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 6 commits into from
Feb 6, 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
18 changes: 0 additions & 18 deletions flutter-idea/src/io/flutter/devtools/DevToolsUrl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public class DevToolsUrl {
public String colorHexCode;
public Boolean isBright;
public String widgetId;
public Float fontSize;
public String hide;
private final FlutterSdkVersion flutterSdkVersion;
private final FlutterSdkUtil sdkUtil;
Expand All @@ -45,7 +44,6 @@ public static class Builder {
private String page;
private Boolean embed;
private String widgetId;
private Float fontSize;
private String hide;

private FlutterSdkVersion flutterSdkVersion;
Expand Down Expand Up @@ -88,11 +86,6 @@ public Builder setWidgetId(String widgetId) {
return this;
}

public Builder setFontSize(Float fontSize) {
this.fontSize = fontSize;
return this;
}

public Builder setHide(String hide) {
this.hide = hide;
return this;
Expand Down Expand Up @@ -147,7 +140,6 @@ private DevToolsUrl(Builder builder) {
if (builder.embed) {
this.colorHexCode = builder.devToolsUtils.getColorHexCode();
this.isBright = builder.devToolsUtils.getIsBackgroundBright();
this.fontSize = builder.devToolsUtils.getFontSize();
}
this.hide = builder.hide;
this.widgetId = builder.widgetId;
Expand Down Expand Up @@ -196,9 +188,6 @@ public String getUrlString() {
}
}
}
if (fontSize != null) {
params.add("fontSize=" + fontSize);
}
if (ideFeature != null) {
params.add("ideFeature=" + ideFeature.value);
}
Expand Down Expand Up @@ -226,11 +215,4 @@ public void maybeUpdateColor() {
colorHexCode = newColor;
isBright = devToolsUtils.getIsBackgroundBright();
}

public void maybeUpdateFontSize() {
final Float newFontSize = devToolsUtils.getFontSize();
if (fontSize == null || !fontSize.equals(newFontSize)) {
fontSize = newFontSize;
}
}
}
21 changes: 21 additions & 0 deletions flutter-idea/src/io/flutter/jxbrowser/EmbeddedJxBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
import io.flutter.settings.FlutterSettings;
import io.flutter.utils.AsyncUtils;
import io.flutter.utils.JxBrowserUtils;
import io.flutter.utils.ZoomLevelSelector;
import io.flutter.view.EmbeddedBrowser;
import io.flutter.view.EmbeddedTab;
import io.flutter.utils.LabelInput;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.teamdev.jxbrowser.zoom.Zoom;
import com.teamdev.jxbrowser.zoom.ZoomLevel;
import com.intellij.ide.ui.UISettingsUtils;

import javax.swing.*;
import java.awt.*;
Expand All @@ -43,13 +47,16 @@
class EmbeddedJxBrowserTab implements EmbeddedTab {
private final Engine engine;
private Browser browser;
private Zoom zoom;
private final ZoomLevelSelector zoomSelector = new ZoomLevelSelector();
private static final Logger LOG = Logger.getInstance(EmbeddedJxBrowserTab.class);

public EmbeddedJxBrowserTab(Engine engine) {
this.engine = engine;

try {
this.browser = engine.newBrowser();
this.zoom = this.browser.zoom();
this.browser.settings().enableTransparentBackground();
this.browser.on(ConsoleMessageReceived.class, event -> {
final ConsoleMessage consoleMessage = event.consoleMessage();
Expand All @@ -74,6 +81,20 @@ public void close() {
this.browser.close();
}

@Override
public void matchIdeZoom() {
if (this.zoom != null) {
final ZoomLevel zoomLevel = zoomSelector.getClosestZoomLevel(getIdeZoomPercent());
this.zoom.level(zoomLevel);
}
}

private int getIdeZoomPercent() {
final UISettingsUtils uiSettingsUtils = UISettingsUtils.getInstance();
final float ideScale = uiSettingsUtils.getCurrentIdeScale();
return Math.round(ideScale * 100);
}

@Override
public JComponent getTabComponent(ContentManager contentManager) {
// Creating Swing component for rendering web content
Expand Down
49 changes: 49 additions & 0 deletions flutter-idea/src/io/flutter/utils/ZoomLevelSelector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2025 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
package io.flutter.utils;

import com.teamdev.jxbrowser.zoom.ZoomLevel;
import org.jetbrains.annotations.NotNull;

import java.util.Map;

import static java.util.Map.entry;

public class ZoomLevelSelector {
@NotNull final Map<Integer, ZoomLevel> zoomLevels = Map.ofEntries(
entry(25, ZoomLevel.P_25),
entry(33, ZoomLevel.P_33),
entry(50, ZoomLevel.P_50),
entry(67, ZoomLevel.P_67),
entry(75, ZoomLevel.P_75),
entry(80, ZoomLevel.P_80),
entry(90, ZoomLevel.P_90),
entry(100, ZoomLevel.P_100),
entry(110, ZoomLevel.P_110),
entry(125, ZoomLevel.P_125),
entry(150, ZoomLevel.P_150),
entry(175, ZoomLevel.P_175),
entry(200, ZoomLevel.P_200),
entry(250, ZoomLevel.P_250),
entry(300, ZoomLevel.P_300),
entry(400, ZoomLevel.P_400),
entry(500, ZoomLevel.P_500)
);

public @NotNull ZoomLevel getClosestZoomLevel(int zoomPercent) {
ZoomLevel closest = ZoomLevel.P_100;
int minDifference = Integer.MAX_VALUE;

for (Map.Entry<Integer, ZoomLevel> entry : zoomLevels.entrySet()) {
int currentDifference = Math.abs(zoomPercent - entry.getKey());
if (currentDifference < minDifference) {
minDifference = currentDifference;
closest = entry.getValue();
}
}

return closest;
}}
4 changes: 3 additions & 1 deletion flutter-idea/src/io/flutter/view/EmbeddedBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public void openPanel(ToolWindow toolWindow, String tabName, DevToolsUrl devTool
tab.content.setIcon(FlutterIcons.Phone);
tab.contentManager.addContent(tab.content);
tab.contentManager.setSelectedContent(tab.content, true);
tab.embeddedTab.matchIdeZoom();
});
}

Expand Down Expand Up @@ -262,8 +263,8 @@ public void refresh(String toolWindowId) {
tab.devToolsUrlFuture.thenAccept(devToolsUrl -> {
if (devToolsUrl == null) return;
devToolsUrl.maybeUpdateColor();
devToolsUrl.maybeUpdateFontSize();
tab.embeddedTab.loadUrl(devToolsUrl.getUrlString());
tab.embeddedTab.matchIdeZoom();
});
});
}
Expand All @@ -290,6 +291,7 @@ private void updateUrlAndReload(Function<DevToolsUrl, DevToolsUrl> newDevToolsUr
return;
}
tab.embeddedTab.loadUrl(devToolsUrl.getUrlString());
tab.embeddedTab.matchIdeZoom();
});
});
});
Expand Down
5 changes: 5 additions & 0 deletions flutter-idea/src/io/flutter/view/EmbeddedJcefBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public void close() {

}

@Override
public void matchIdeZoom() {

Copy link
Member

Choose a reason for hiding this comment

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

Is this intentionally empty?

Copy link
Member Author

Choose a reason for hiding this comment

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

Chatted offline, this is an experimental browser, does not need implementation here.

}

@Override
public JComponent getTabComponent(ContentManager contentManager) {
browser.getComponent().setPreferredSize(new Dimension(contentManager.getComponent().getWidth(), contentManager.getComponent().getHeight()));
Expand Down
2 changes: 2 additions & 0 deletions flutter-idea/src/io/flutter/view/EmbeddedTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ public interface EmbeddedTab {

void close();

void matchIdeZoom();

JComponent getTabComponent(ContentManager contentManager);
}
18 changes: 18 additions & 0 deletions flutter-idea/testSrc/unit/io/flutter/FlutterUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
*/
package io.flutter;

import com.teamdev.jxbrowser.zoom.ZoomLevel;
import io.flutter.utils.ZoomLevelSelector;
import org.junit.Test;

import static io.flutter.FlutterUtils.isValidDartIdentifier;
import static io.flutter.FlutterUtils.isValidPackageName;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

public class FlutterUtilsTest {
Expand Down Expand Up @@ -39,4 +42,19 @@ public void validPackageNames() {
assertFalse("expected " + name + " to be invalid", isValidPackageName(name));
}
}

@Test
public void zoomLevelSelector() {
final ZoomLevelSelector zoomLevelSelector = new ZoomLevelSelector();
assertSame(zoomLevelSelector.getClosestZoomLevel(-70), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(-10), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(0), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(1), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(20), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(28), ZoomLevel.P_25);
assertSame(zoomLevelSelector.getClosestZoomLevel(35), ZoomLevel.P_33);
assertSame(zoomLevelSelector.getClosestZoomLevel(222), ZoomLevel.P_200);
assertSame(zoomLevelSelector.getClosestZoomLevel(226), ZoomLevel.P_250);
assertSame(zoomLevelSelector.getClosestZoomLevel(700), ZoomLevel.P_500);
}
}
20 changes: 0 additions & 20 deletions flutter-idea/testSrc/unit/io/flutter/devtools/DevToolsUrlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public void testGetUrlStringWithoutColor() {
final DevToolsUtils noColorUtils = mock(DevToolsUtils.class);
when(noColorUtils.getColorHexCode()).thenReturn(null);
when(noColorUtils.getIsBackgroundBright()).thenReturn(null);
when(noColorUtils.getFontSize()).thenReturn(null);

assertEquals(
"http://127.0.0.1:9100/timeline?ide=IntelliJ-IDEA&uri=http%3A%2F%2F127.0.0.1%3A50224%2FWTFTYus3IPU%3D%2F",
Expand Down Expand Up @@ -163,7 +162,6 @@ public final void testGetUrlStringWithColor() {
final DevToolsUtils lightUtils = mock(DevToolsUtils.class);
when(lightUtils.getColorHexCode()).thenReturn("ffffff");
when(lightUtils.getIsBackgroundBright()).thenReturn(true);
when(lightUtils.getFontSize()).thenReturn(null);

assertEquals(
"http://127.0.0.1:9100/timeline?ide=IntelliJ-IDEA&backgroundColor=ffffff&theme=light&embed=true&uri=http%3A%2F%2F127.0.0.1%3A50224%2FWTFTYus3IPU%3D%2F",
Expand All @@ -181,29 +179,11 @@ public final void testGetUrlStringWithColor() {
.getUrlString()
);

when(lightUtils.getFontSize()).thenReturn(12f);
assertEquals(
"http://127.0.0.1:9100/timeline?ide=IntelliJ-IDEA&backgroundColor=ffffff&theme=light&embed=true&fontSize=12.0&uri=http%3A%2F%2F127.0.0.1%3A50224%2FWTFTYus3IPU%3D%2F",
new DevToolsUrl.Builder()
.setDevToolsHost(devtoolsHost)
.setDevToolsPort(devtoolsPort)
.setVmServiceUri(serviceProtocolUri)
.setEmbed(true)
.setPage(page)
.setFlutterSdkVersion(newVersion)
.setWorkspaceCache(notBazelWorkspaceCache)
.setFlutterSdkUtil(mockSdkUtil)
.setDevToolsUtils(lightUtils)
.build()
.getUrlString()
);

when(mockSdkUtil.getFlutterHostEnvValue()).thenReturn("Android-Studio");

final DevToolsUtils darkUtils = mock(DevToolsUtils.class);
when(darkUtils.getColorHexCode()).thenReturn("3c3f41");
when(darkUtils.getIsBackgroundBright()).thenReturn(false);
when(darkUtils.getFontSize()).thenReturn(null);

assertEquals(
"http://127.0.0.1:9100/timeline?ide=Android-Studio&backgroundColor=3c3f41&theme=dark&embed=true&uri=http%3A%2F%2F127.0.0.1%3A50224%2FWTFTYus3IPU%3D%2F",
Expand Down