Skip to content

Commit 6dff1f5

Browse files
authored
Add button to refresh tool windows (flutter#7633)
Fixes flutter#7617 In my first pass, I'm having trouble finding the right IntelliJ/Java API that would allow us to attach a refresh action to only one tab within a tool window (for example, if there are multiple apps running, there will be an inspector tab for each app). So I'll probably try to land this as refreshing all tabs in a tool window for now. I also can't find how to add the action to the menu (`toolWindow.setAdditionalGearActions` seems like the obvious method, but didn't work), so I just made it a separate button. I figure that's more visible anyway: <img width="575" alt="Screenshot 2024-08-29 at 1 05 24 PM" src="https://github.com/user-attachments/assets/b479d326-80b2-443c-b2c4-1c1835dd30a7"> I'm going to open a separate issue to further discuss multiple app / multiple tab per tool window situations.
1 parent 0d9d69e commit 6dff1f5

File tree

8 files changed

+96
-20
lines changed

8 files changed

+96
-20
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2024 The Chromium Authors. All rights reserved.
3+
* Use of this source code is governed by a BSD-style license that can be
4+
* found in the LICENSE file.
5+
*/
6+
package io.flutter.actions;
7+
8+
import com.intellij.icons.AllIcons;
9+
import com.intellij.openapi.actionSystem.AnActionEvent;
10+
import com.intellij.openapi.project.DumbAwareAction;
11+
import com.intellij.openapi.project.Project;
12+
import io.flutter.FlutterUtils;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
import java.util.Optional;
16+
17+
public class RefreshToolWindowAction extends DumbAwareAction {
18+
private String toolWindowId;
19+
20+
public RefreshToolWindowAction() {
21+
super(AllIcons.Actions.Refresh);
22+
}
23+
24+
public RefreshToolWindowAction(@NotNull String toolWindowId) {
25+
super(AllIcons.Actions.Refresh);
26+
this.toolWindowId = toolWindowId;
27+
}
28+
@Override
29+
public void actionPerformed(@NotNull AnActionEvent event) {
30+
final Project project = event.getProject();
31+
if (project == null) {
32+
return;
33+
}
34+
35+
Optional.ofNullable(
36+
FlutterUtils.embeddedBrowser(project))
37+
.ifPresent(embeddedBrowser -> embeddedBrowser.refresh(toolWindowId));
38+
}
39+
}

flutter-idea/src/io/flutter/deeplinks/DeepLinksViewFactory.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,27 @@
55
*/
66
package io.flutter.deeplinks;
77

8-
import com.intellij.ide.util.PropertiesComponent;
98
import com.intellij.openapi.application.ApplicationManager;
109
import com.intellij.openapi.project.Project;
1110
import com.intellij.openapi.wm.ToolWindow;
1211
import com.intellij.openapi.wm.ToolWindowFactory;
13-
import com.intellij.openapi.wm.ToolWindowManager;
14-
import com.intellij.ui.content.ContentManager;
15-
import icons.FlutterIcons;
1612
import io.flutter.FlutterUtils;
13+
import io.flutter.actions.RefreshToolWindowAction;
1714
import io.flutter.bazel.WorkspaceCache;
1815
import io.flutter.devtools.DevToolsIdeFeature;
1916
import io.flutter.devtools.DevToolsUrl;
20-
import io.flutter.performance.FlutterPerformanceView;
2117
import io.flutter.run.daemon.DevToolsService;
2218
import io.flutter.sdk.FlutterSdk;
2319
import io.flutter.sdk.FlutterSdkVersion;
2420
import io.flutter.utils.AsyncUtils;
25-
import io.flutter.utils.UIUtils;
26-
import io.flutter.view.FlutterViewMessages;
2721
import kotlin.coroutines.Continuation;
2822
import org.jetbrains.annotations.NotNull;
2923

24+
import java.util.List;
3025
import java.util.Optional;
3126

3227
public class DeepLinksViewFactory implements ToolWindowFactory {
33-
private static String TOOL_WINDOW_ID = "Flutter Deep Links";
28+
@NotNull private static String TOOL_WINDOW_ID = "Flutter Deep Links";
3429

3530
@Override
3631
public Object isApplicableAsync(@NotNull Project project, @NotNull Continuation<? super Boolean> $completion) {
@@ -41,7 +36,6 @@ public Object isApplicableAsync(@NotNull Project project, @NotNull Continuation<
4136

4237
@Override
4338
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
44-
final ContentManager contentManager = toolWindow.getContentManager();
4539
FlutterSdk sdk = FlutterSdk.getFlutterSdk(project);
4640
FlutterSdkVersion sdkVersion = sdk == null ? null : sdk.getVersion();
4741

@@ -78,5 +72,9 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
7872
});
7973
}
8074
);
75+
76+
// TODO(helin24): It may be better to add this to the gear actions or to attach as a mouse event on individual tabs within a tool
77+
// window, but I wasn't able to get either working immediately.
78+
toolWindow.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID)));
8179
}
8280
}

flutter-idea/src/io/flutter/devtools/DevToolsExtensionsViewFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.intellij.ui.content.ContentManager;
1414
import icons.FlutterIcons;
1515
import io.flutter.FlutterUtils;
16+
import io.flutter.actions.RefreshToolWindowAction;
1617
import io.flutter.bazel.WorkspaceCache;
1718
import io.flutter.run.daemon.DevToolsService;
1819
import io.flutter.sdk.FlutterSdk;
@@ -24,9 +25,12 @@
2425
import org.jetbrains.annotations.NotNull;
2526
import org.jetbrains.annotations.Nullable;
2627

28+
import java.util.List;
2729
import java.util.Optional;
2830

2931
public class DevToolsExtensionsViewFactory implements ToolWindowFactory {
32+
@NotNull private static String TOOL_WINDOW_ID = "Flutter DevTools Extensions";
33+
3034
public static void init(Project project) {
3135
project.getMessageBus().connect().subscribe(
3236
FlutterViewMessages.FLUTTER_DEBUG_TOPIC, (FlutterViewMessages.FlutterDebugNotifier)event -> initView(project, event)
@@ -84,6 +88,8 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
8488
});
8589
}
8690
);
91+
92+
window.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID)));
8793
}
8894

8995
@Nullable

flutter-idea/src/io/flutter/devtools/RemainingDevToolsViewFactory.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,24 @@
99
import com.intellij.openapi.project.Project;
1010
import com.intellij.openapi.wm.ToolWindow;
1111
import com.intellij.openapi.wm.ToolWindowFactory;
12-
import com.intellij.openapi.wm.ToolWindowManager;
1312
import com.intellij.ui.content.ContentManager;
14-
import icons.FlutterIcons;
1513
import io.flutter.FlutterUtils;
14+
import io.flutter.actions.RefreshToolWindowAction;
1615
import io.flutter.bazel.WorkspaceCache;
1716
import io.flutter.run.daemon.DevToolsService;
1817
import io.flutter.sdk.FlutterSdk;
1918
import io.flutter.sdk.FlutterSdkVersion;
2019
import io.flutter.utils.AsyncUtils;
21-
import io.flutter.utils.UIUtils;
2220
import io.flutter.view.FlutterViewMessages;
2321
import kotlin.coroutines.Continuation;
2422
import org.jetbrains.annotations.NotNull;
2523
import org.jetbrains.annotations.Nullable;
2624

25+
import java.util.List;
2726
import java.util.Optional;
2827

2928
public class RemainingDevToolsViewFactory implements ToolWindowFactory {
30-
private static String TOOL_WINDOW_ID = "Flutter DevTools";
29+
@NotNull private static String TOOL_WINDOW_ID = "Flutter DevTools";
3130
public static void init(Project project) {
3231
project.getMessageBus().connect().subscribe(
3332
FlutterViewMessages.FLUTTER_DEBUG_TOPIC, (FlutterViewMessages.FlutterDebugNotifier)event -> initView(project, event)
@@ -86,6 +85,8 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
8685
});
8786
}
8887
);
88+
89+
window.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID)));
8990
}
9091

9192
@Nullable

flutter-idea/src/io/flutter/view/EmbeddedBrowser.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import io.flutter.analytics.Analytics;
2323
import io.flutter.devtools.DevToolsUrl;
2424
import io.flutter.utils.AsyncUtils;
25-
import org.jetbrains.annotations.NotNull;
2625
import io.flutter.utils.LabelInput;
26+
import org.jetbrains.annotations.NotNull;
2727

2828
import javax.swing.*;
2929
import java.awt.*;
@@ -270,6 +270,25 @@ public void updateVmServiceUri(@NotNull String newVmServiceUri) {
270270
});
271271
}
272272

273+
// This will refresh all the browser tabs within a tool window (e.g. if there are multiple apps running and the inspector tool window is
274+
// refreshed, an inspector tab will refresh for each app.)
275+
// TODO(helin24): Consider allowing refresh for single browser tabs within tool windows.
276+
public void refresh(String toolWindowId) {
277+
Map<String, BrowserTab> tabs = windows.get(toolWindowId);
278+
279+
if (tabs == null) {
280+
return;
281+
}
282+
283+
tabs.forEach((tabName, tab) -> {
284+
if (tab == null || tab.devToolsUrlFuture == null) return;
285+
tab.devToolsUrlFuture.thenAccept(devToolsUrl -> {
286+
if (devToolsUrl == null) return;
287+
tab.embeddedTab.loadUrl(devToolsUrl.getUrlString());
288+
});
289+
});
290+
}
291+
273292
private void updateUrlAndReload(Function<DevToolsUrl, DevToolsUrl> newDevToolsUrlFn) {
274293
this.windows.forEach((window, tabs) -> {
275294
tabs.forEach((tabName, tab) -> {

flutter-idea/src/io/flutter/view/FlutterView.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package io.flutter.view;
77

88
import com.google.common.annotations.VisibleForTesting;
9-
import com.intellij.execution.runners.ExecutionUtil;
109
import com.intellij.ide.browsers.BrowserLauncher;
1110
import com.intellij.ide.ui.UISettingsListener;
1211
import com.intellij.openapi.Disposable;
@@ -17,7 +16,6 @@
1716
import com.intellij.openapi.editor.colors.EditorColorsListener;
1817
import com.intellij.openapi.editor.colors.EditorColorsManager;
1918
import com.intellij.openapi.progress.EmptyProgressIndicator;
20-
import com.intellij.openapi.progress.ProgressIndicator;
2119
import com.intellij.openapi.progress.ProgressManager;
2220
import com.intellij.openapi.project.Project;
2321
import com.intellij.openapi.ui.VerticalFlowLayout;
@@ -35,18 +33,21 @@
3533
import com.intellij.util.ui.JBUI;
3634
import com.intellij.util.ui.UIUtil;
3735
import com.intellij.xdebugger.XSourcePosition;
38-
import icons.FlutterIcons;
3936
import io.flutter.FlutterBundle;
4037
import io.flutter.FlutterInitializer;
4138
import io.flutter.FlutterUtils;
39+
import io.flutter.actions.RefreshToolWindowAction;
4240
import io.flutter.bazel.WorkspaceCache;
4341
import io.flutter.devtools.DevToolsIdeFeature;
4442
import io.flutter.devtools.DevToolsUrl;
4543
import io.flutter.inspector.DiagnosticsNode;
4644
import io.flutter.inspector.InspectorGroupManagerService;
4745
import io.flutter.inspector.InspectorService;
4846
import io.flutter.inspector.InspectorSourceLocation;
49-
import io.flutter.jxbrowser.*;
47+
import io.flutter.jxbrowser.FailureType;
48+
import io.flutter.jxbrowser.InstallationFailedReason;
49+
import io.flutter.jxbrowser.JxBrowserManager;
50+
import io.flutter.jxbrowser.JxBrowserStatus;
5051
import io.flutter.run.FlutterDevice;
5152
import io.flutter.run.daemon.DevToolsInstance;
5253
import io.flutter.run.daemon.DevToolsService;
@@ -64,10 +65,12 @@
6465

6566
import javax.swing.*;
6667
import java.awt.*;
68+
import java.util.ArrayList;
69+
import java.util.Arrays;
6770
import java.util.List;
68-
import java.util.*;
69-
import java.util.concurrent.atomic.AtomicReference;
71+
import java.util.Optional;
7072
import java.util.concurrent.TimeoutException;
73+
import java.util.concurrent.atomic.AtomicReference;
7174

7275
@com.intellij.openapi.components.State(
7376
name = "FlutterView",
@@ -244,6 +247,8 @@ private void addBrowserInspectorViewContent(FlutterApp app,
244247
);
245248
busSubscribed = true;
246249
}
250+
251+
toolWindow.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID)));
247252
} else {
248253
BrowserLauncher.getInstance().browse(
249254
new DevToolsUrl.Builder()

resources/META-INF/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@
546546
text="Open Flutter DevTools" description="Open Flutter DevTools" icon="FlutterIcons.Dart_16">
547547
</action>
548548

549+
<action id="io.flutter.RefreshToolWindow" class="io.flutter.actions.RefreshToolWindowAction" text="Refresh Tool Window"
550+
description="Refresh current tool window contents">
551+
</action>
552+
549553
<!-- action
550554
id="DeveloperServices.FlutterNewsAssistant"
551555
class="io.flutter.actions.OpenFlutterNewsSidePanelAction"

resources/META-INF/plugin_template.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@
245245
text="Open Flutter DevTools" description="Open Flutter DevTools" icon="FlutterIcons.Dart_16">
246246
</action>
247247

248+
<action id="io.flutter.RefreshToolWindow" class="io.flutter.actions.RefreshToolWindowAction" text="Refresh Tool Window"
249+
description="Refresh current tool window contents">
250+
</action>
251+
248252
<!-- action
249253
id="DeveloperServices.FlutterNewsAssistant"
250254
class="io.flutter.actions.OpenFlutterNewsSidePanelAction"

0 commit comments

Comments
 (0)