From e766f48c75bc5a5cfee390fda5c26b5b1c9d7e48 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 24 Apr 2025 22:44:42 +0400 Subject: [PATCH] IJPL-183770 Fix excessive toolbar iterations Do not iterate components: 1. On paint 2. When adding a new toolbar (cherry picked from commit 0e387c189d60107a09ea950c53c184b900733a27) IJ-CR-161198 GitOrigin-RevId: a74da26116dc32a9aaf5c57eb9e2ff7e30513981 --- .../platform-impl/api-dump-unreviewed.txt | 3 +- .../ide/actions/ToggleToolbarAction.java | 46 +++++++++++-------- .../openapi/wm/impl/ToolWindowImpl.kt | 20 +++++--- .../intellij/toolWindow/ToolWindowHeader.kt | 3 +- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/platform/platform-impl/api-dump-unreviewed.txt b/platform/platform-impl/api-dump-unreviewed.txt index a89fc038e218..a422cf10541e 100644 --- a/platform/platform-impl/api-dump-unreviewed.txt +++ b/platform/platform-impl/api-dump-unreviewed.txt @@ -2956,7 +2956,6 @@ f:com.intellij.ide.actions.ToggleToolbarAction - s:createToggleToolbarGroup(com.intellij.openapi.project.Project,com.intellij.openapi.wm.ToolWindow):com.intellij.openapi.actionSystem.DefaultActionGroup - s:createToolWindowAction(com.intellij.openapi.wm.ToolWindow,com.intellij.ide.util.PropertiesComponent):com.intellij.ide.actions.ToggleToolbarAction - getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread -- s:hasVisibleToolwindowToolbars(com.intellij.openapi.wm.ToolWindow):Z - isSelected(com.intellij.openapi.actionSystem.AnActionEvent):Z - s:isToolbarVisible(com.intellij.openapi.wm.ToolWindow):Z - s:isToolbarVisible(com.intellij.openapi.wm.ToolWindow,com.intellij.ide.util.PropertiesComponent):Z @@ -2969,7 +2968,7 @@ f:com.intellij.ide.actions.ToggleToolbarAction - s:setToolbarVisible(java.lang.Iterable,Z):V - s:setToolbarVisible(java.lang.String,com.intellij.ide.util.PropertiesComponent,java.lang.Iterable,java.lang.Boolean):V - update(com.intellij.openapi.actionSystem.AnActionEvent):V -- s:updateToolbarsVisibility(com.intellij.openapi.wm.ToolWindow,com.intellij.ide.util.PropertiesComponent):V +- s:updateToolbarVisibility(com.intellij.openapi.wm.ToolWindow,com.intellij.openapi.actionSystem.ActionToolbar,com.intellij.ide.util.PropertiesComponent):V f:com.intellij.ide.actions.ToggleZenModeAction - com.intellij.openapi.project.DumbAwareAction - sf:Companion:com.intellij.ide.actions.ToggleZenModeAction$Companion diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleToolbarAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleToolbarAction.java index c92cace90c1e..c46ee53b8c45 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ToggleToolbarAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleToolbarAction.java @@ -27,7 +27,6 @@ import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.function.Supplier; @@ -46,7 +45,8 @@ public final class ToggleToolbarAction extends ToggleAction implements DumbAware return new ToggleToolbarAction(properties, getShowToolbarProperty(id), components); } - public static @NotNull ToggleToolbarAction createToolWindowAction(@NotNull ToolWindow toolWindow, @NotNull PropertiesComponent properties) { + public static @NotNull ToggleToolbarAction createToolWindowAction(@NotNull ToolWindow toolWindow, + @NotNull PropertiesComponent properties) { updateToolbarsVisibility(toolWindow, properties); toolWindow.addContentManagerListener(new ContentManagerListener() { @Override @@ -74,10 +74,16 @@ public final class ToggleToolbarAction extends ToggleAction implements DumbAware }); } - public static void updateToolbarsVisibility(@NotNull ToolWindow toolWindow, @NotNull PropertiesComponent properties) { - if (toolWindow.getContentManagerIfCreated() != null) { - setToolbarVisible(Collections.singletonList(toolWindow.getComponent()), isToolbarVisible(toolWindow, properties)); - } + private static void updateToolbarsVisibility(@NotNull ToolWindow toolWindow, + @NotNull PropertiesComponent properties) { + if (toolWindow.getContentManagerIfCreated() == null) return; + setToolbarVisible(Collections.singletonList(toolWindow.getComponent()), isToolbarVisible(toolWindow, properties)); + } + + public static void updateToolbarVisibility(@NotNull ToolWindow toolWindow, + @NotNull ActionToolbar toolbar, + @NotNull PropertiesComponent properties) { + setToolbarVisible(toolbar, isToolbarVisible(toolWindow, properties)); } public static void setToolbarVisible(@NotNull ToolWindow toolWindow, @@ -95,14 +101,19 @@ public final class ToggleToolbarAction extends ToggleAction implements DumbAware setToolbarVisibleImpl(getShowToolbarProperty(id), properties, components, state); } - public static void setToolbarVisible(@NotNull Iterable roots, boolean state) { + public static void setToolbarVisible(@NotNull Iterable roots, + boolean state) { for (ActionToolbar toolbar : iterateToolbars(roots)) { - JComponent c = toolbar.getComponent(); - c.setVisible(state); - Container parent = c.getParent(); - if (parent instanceof EditorHeaderComponent) { - parent.setVisible(state); - } + setToolbarVisible(toolbar, state); + } + } + + private static void setToolbarVisible(ActionToolbar toolbar, boolean state) { + JComponent c = toolbar.getComponent(); + c.setVisible(state); + Container parent = c.getParent(); + if (parent instanceof EditorHeaderComponent) { + parent.setVisible(state); } } @@ -155,11 +166,6 @@ public final class ToggleToolbarAction extends ToggleAction implements DumbAware return ActionUpdateThread.EDT; } - public static boolean hasVisibleToolwindowToolbars(@NotNull ToolWindow toolWindow) { - Iterator iterator = iterateToolbars(Collections.singletonList(toolWindow.getContentManager().getComponent())).iterator(); - return iterator.hasNext() && iterator.next().getComponent().isVisible(); - } - @Override public boolean isSelected(@NotNull AnActionEvent e) { return isSelected(); @@ -199,8 +205,8 @@ public final class ToggleToolbarAction extends ToggleAction implements DumbAware .filter(ActionToolbar.class) .filter(toolbar -> { var c = toolbar.getComponent(); - return !Boolean.TRUE.equals(c.getClientProperty(ActionToolbarImpl.IMPORTANT_TOOLBAR_KEY)) - && !(c instanceof FloatingToolbarComponent); + return !Boolean.TRUE.equals(c.getClientProperty(ActionToolbarImpl.IMPORTANT_TOOLBAR_KEY)) && + !(c instanceof FloatingToolbarComponent); }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.kt index 91cfdd09e9c5..32899c6eeada 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.kt @@ -177,7 +177,7 @@ internal class ToolWindowImpl( return decorator!! } - fun createCellDecorator() : InternalDecoratorImpl { + fun createCellDecorator(): InternalDecoratorImpl { val cellContentManager = ContentManagerImpl(canCloseContent, toolWindowManager.project, parentDisposable, ContentManagerImpl.ContentUiProducer { contentManager, componentGetter -> ToolWindowContentUi(this, contentManager, componentGetter.get()) }) @@ -221,10 +221,11 @@ internal class ToolWindowImpl( }) object : ComponentTreeWatcher(ArrayUtil.EMPTY_CLASS_ARRAY) { override fun processComponent(component: Component) { - if (component is ActionToolbar) { - updateToolbarsVisibility() - } + if (component !is ActionToolbar) return + ToggleToolbarAction.updateToolbarVisibility( + this@ToolWindowImpl, component, PropertiesComponent.getInstance(project)) } + override fun unprocessComponent(component: Component) = Unit }.register(decorator) if (ExperimentalUI.isNewUI()) { @@ -251,8 +252,13 @@ internal class ToolWindowImpl( return contentManager } - private fun updateToolbarsVisibility() { - ToggleToolbarAction.updateToolbarsVisibility(this, PropertiesComponent.getInstance(project)) + internal fun hasTopToolbar(): Boolean { + val decorator = decorator ?: return false + val header = decorator.header + val headerBounds = SwingUtilities.convertRectangle(header.parent, header.bounds, decorator) + val component = UIUtil.getDeepestComponentAt( + decorator, headerBounds.width/2, headerBounds.height * 3 / 2) + return UIUtil.getParentOfType(ActionToolbar::class.java, component) != null } private fun updateScrolledState() { @@ -363,7 +369,7 @@ internal class ToolWindowImpl( toolWindowFocusWatcher?.setFocusedComponentImpl(component) } - fun getLastFocusedContent() : Content? { + fun getLastFocusedContent(): Content? { val lastFocusedComponent = toolWindowFocusWatcher?.focusedComponent if (lastFocusedComponent is JComponent) { if (!lastFocusedComponent.isShowing) return null diff --git a/platform/platform-impl/src/com/intellij/toolWindow/ToolWindowHeader.kt b/platform/platform-impl/src/com/intellij/toolWindow/ToolWindowHeader.kt index 4b2d116f7134..8363cb84937c 100644 --- a/platform/platform-impl/src/com/intellij/toolWindow/ToolWindowHeader.kt +++ b/platform/platform-impl/src/com/intellij/toolWindow/ToolWindowHeader.kt @@ -3,7 +3,6 @@ package com.intellij.toolWindow import com.intellij.icons.AllIcons import com.intellij.ide.IdeBundle -import com.intellij.ide.actions.ToggleToolbarAction import com.intellij.ide.actions.ToolwindowFusEventFields import com.intellij.ide.ui.UISettings.Companion.setupAntialiasing import com.intellij.internal.statistic.eventLog.events.EventPair @@ -302,7 +301,7 @@ abstract class ToolWindowHeader internal constructor( val contentCount = (nearestDecorator?.contentManager ?: toolWindow.contentManager).contentCount drawBottomLine = (toolWindow.anchor == ToolWindowAnchor.BOTTOM || (toolWindow.windowInfo.contentUiType == ToolWindowContentUiType.TABBED && contentCount > 1) - || ToggleToolbarAction.hasVisibleToolwindowToolbars(toolWindow) + || toolWindow.hasTopToolbar() || scrolled) }