diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/AgentManagerPanel.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/AgentManagerPanel.kt index d6d7b0b4bca..5f199ce61dc 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/AgentManagerPanel.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/AgentManagerPanel.kt @@ -24,7 +24,6 @@ import ai.kilocode.client.diff.ensureDiffEditorKind import ai.kilocode.client.plugin.KiloBundle import ai.kilocode.client.session.SessionActivityKind import ai.kilocode.client.ui.UiStyle -import ai.kilocode.client.util.bindTheme import ai.kilocode.client.ui.list.ActiveList import ai.kilocode.client.ui.list.ActiveListBadge import ai.kilocode.client.ui.list.ActiveListConfig @@ -108,7 +107,6 @@ class AgentManagerPanel( list.installPopup(group) sync() bindModel() - bindTheme(this, this) controller.onSelect = { key -> // Focus the list so the freshly created worktree renders as an active selection rather // than the inactive highlight it would get while focus stays on the toolbar. diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanel.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanel.kt index 1eee956f1cb..022a475f1f8 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanel.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanel.kt @@ -13,7 +13,6 @@ import ai.kilocode.client.session.history.HistoryTime import ai.kilocode.client.session.history.LocalHistoryItem import ai.kilocode.client.plugin.KiloPluginSettings import ai.kilocode.client.telemetry.Telemetry -import ai.kilocode.client.util.bindTheme import ai.kilocode.client.ui.list.ActiveList import ai.kilocode.client.ui.list.ActiveListBadge import ai.kilocode.client.ui.list.ActiveListConfig @@ -116,7 +115,9 @@ class WorktreeSessionEditorPanel( Disposer.register(parent, this) isOpaque = true toolbar.targetComponent = this - toolbar.component.background = activeListToolWindowBackground() + // Keep the toolbar transparent so it shows its themed parent background and tracks + // Look-and-Feel changes automatically, instead of caching a color that goes stale. + toolbar.component.isOpaque = false toolbar.updateActionsImmediately() list.installPopup(group) splitter.firstComponent = list @@ -141,7 +142,6 @@ class WorktreeSessionEditorPanel( } } bindStatus() - bindTheme(this, this) sync() } diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/util/Theme.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/util/Theme.kt deleted file mode 100644 index 446d2eefad9..00000000000 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/util/Theme.kt +++ /dev/null @@ -1,21 +0,0 @@ -package ai.kilocode.client.util - -import com.intellij.ide.ui.LafManagerListener -import com.intellij.openapi.Disposable -import com.intellij.openapi.application.ApplicationManager -import javax.swing.JComponent -import javax.swing.SwingUtilities - -/** - * Refresh [roots] on Look-and-Feel changes. The subscription is tied to [parent], so it is removed - * when the owning component is disposed. Replaces the copy/pasted `LafManagerListener` blocks that - * each panel used to carry. - */ -internal fun bindTheme(parent: Disposable, vararg roots: JComponent) { - val bus = ApplicationManager.getApplication().messageBus.connect(parent) - bus.subscribe(LafManagerListener.TOPIC, LafManagerListener { - ApplicationManager.getApplication().invokeLater { - roots.forEach { SwingUtilities.updateComponentTreeUI(it) } - } - }) -} diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanelTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanelTest.kt index 5fe9e94c811..d8809cfdc19 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanelTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/agentManager/worktree/WorktreeSessionEditorPanelTest.kt @@ -36,6 +36,7 @@ import com.intellij.ui.SearchTextField import com.intellij.ui.components.JBList import com.intellij.ui.components.JBScrollPane import com.intellij.util.ui.UIUtil +import java.awt.Color import java.awt.Container import java.awt.Point import java.awt.event.ActionEvent @@ -46,6 +47,7 @@ import javax.swing.JButton import javax.swing.JComponent import javax.swing.KeyStroke import javax.swing.SwingUtilities +import javax.swing.UIManager @Suppress("UnstableApiUsage") class WorktreeSessionEditorPanelTest : BasePlatformTestCase() { @@ -110,7 +112,7 @@ class WorktreeSessionEditorPanelTest : BasePlatformTestCase() { assertEquals(activeListToolWindowBackground(), edt { scroll.background }) assertEquals(activeListToolWindowBackground(), edt { scroll.viewport.background }) assertEquals(activeListToolWindowBackground(), edt { (scroll.viewport.view as JComponent).background }) - assertEquals(activeListToolWindowBackground(), edt { toolbar.background }) + assertFalse(edt { toolbar.isOpaque }) assertEquals(activeListToolWindowBackground(), edt { toolbarPanel.background }) assertEquals(activeListToolWindowBackground(), edt { header.background }) assertEquals(0, edt { scroll.border.getBorderInsets(scroll).left }) @@ -119,6 +121,24 @@ class WorktreeSessionEditorPanelTest : BasePlatformTestCase() { assertTrue(edt { header.border.getBorderInsets(header).bottom > 0 }) } + fun `test toolbar background tracks the theme automatically`() { + val button = edt { components(panel).filterIsInstance().single { it.presentation.text == "New session" } } + val toolbar = edt { button.parent as JComponent } + val toolbarPanel = edt { toolbar.parent as JComponent } + val old = UIManager.get("ToolWindow.background") + val next = Color(17, 34, 51) + + try { + // The toolbar is transparent, so its themed background comes from the parent and follows + // the theme's ToolWindow.background live -- no listener or manual assignment required. + assertFalse(edt { toolbar.isOpaque }) + edt { UIManager.put("ToolWindow.background", next) } + assertEquals(next, edt { toolbarPanel.background }) + } finally { + UIManager.put("ToolWindow.background", old) + } + } + fun `test expand collapse hides session list and edit toolbar but keeps header actions`() { edt { val splitter = UIUtil.findComponentOfType(panel, OnePixelSplitter::class.java)!!