mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-194950 Get rid of restart when switching island themes
GitOrigin-RevId: a3e60a4ef67bd3b1d2699512279a52affd1dc761
This commit is contained in:
committed by
intellij-monorepo-bot
parent
37aae16170
commit
168ff042b7
@@ -523,6 +523,7 @@ private class ProjectWindowCustomizerListener : ProjectActivity, UISettingsListe
|
||||
}
|
||||
|
||||
override fun uiSettingsChanged(uiSettings: UISettings) {
|
||||
InternalUICustomization.getInstance()?.updateBackgroundPainter()
|
||||
ProjectWindowCustomizerService.getInstance().update(uiSettings.differentiateProjects)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.ui.LafManager;
|
||||
import com.intellij.ide.ui.LafManagerListener;
|
||||
import com.intellij.ide.ui.TargetUIType;
|
||||
import com.intellij.ide.ui.ThemeListProvider;
|
||||
import com.intellij.ide.ui.laf.UIThemeLookAndFeelInfo;
|
||||
import com.intellij.ide.ui.laf.UiThemeProviderListManager;
|
||||
@@ -43,6 +44,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implements ActionRemoteBehaviorSpecification.Frontend {
|
||||
@@ -72,9 +74,13 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
|
||||
@Override
|
||||
protected @NotNull ListPopup createPopup(AnActionEvent e, DefaultActionGroup group, JBPopupFactory.ActionSelectionAid aid) {
|
||||
UiThemeProviderListManager themeManager = UiThemeProviderListManager.Companion.getInstance();
|
||||
List<UIThemeLookAndFeelInfo> islandThemes = themeManager.getBundledThemeListForTargetUI(TargetUIType.ISLANDS);
|
||||
|
||||
if (WelcomeFrame.getInstance() == null &&
|
||||
ContainerUtil.exists(group.getChildren(e),
|
||||
action -> action instanceof LafChangeAction lafAction && lafAction.myLookAndFeelInfo.isRestartRequired())) {
|
||||
ContainerUtil.exists(group.getChildren(e), action -> action instanceof LafChangeAction lafAction &&
|
||||
(lafAction.myLookAndFeelInfo.isRestartRequired() ||
|
||||
islandThemes.contains(lafAction.myLookAndFeelInfo)))) {
|
||||
return new PopupFactoryImpl.ActionGroupPopup(null, getPopupTitle(e), group, e.getDataContext(),
|
||||
myActionPlace == null ? ActionPlaces.POPUP : myActionPlace, new PresentationFactory(),
|
||||
ActionPopupOptions.forAid(aid, true, -1, preselectAction()), null) {
|
||||
@@ -113,7 +119,7 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
if (value instanceof PopupFactoryImpl.ActionItem item) {
|
||||
AnAction action = item.getAction();
|
||||
if (action instanceof LafChangeAction lafAction) {
|
||||
checkRestartRequired(lafAction, infos, isSelected, icon1, icon2);
|
||||
checkRestartRequired(lafAction, infos, islandThemes, isSelected, icon1, icon2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,6 +132,7 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
|
||||
private static boolean checkRestartRequired(@NotNull LafChangeAction lafAction,
|
||||
@NotNull List<Groups.GroupInfo<UIThemeLookAndFeelInfo>> infos,
|
||||
@NotNull List<UIThemeLookAndFeelInfo> islandThemes,
|
||||
boolean isSelected,
|
||||
@Nullable JLabel icon1,
|
||||
@Nullable JLabel icon2) {
|
||||
@@ -154,6 +161,9 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (icon1 != null && islandThemes.contains(lafAction.myLookAndFeelInfo)) {
|
||||
icon1.setIcon(AllIcons.General.Beta);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -232,7 +242,8 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
Object item = ((JList<?>)event.getSource()).getSelectedValue();
|
||||
if (item instanceof AnActionHolder) {
|
||||
AnAction anAction = ((AnActionHolder)item).getAction();
|
||||
if (anAction instanceof LafChangeAction action && !checkRestartRequired(action, infos, false, null, null)) {
|
||||
if (anAction instanceof LafChangeAction action &&
|
||||
!checkRestartRequired(action, infos, Collections.emptyList(), false, null, null)) {
|
||||
switchAlarm.cancelAllRequests();
|
||||
switchAlarm.addRequest(() -> {
|
||||
switchLafAndUpdateUI(LafManager.getInstance(), action.myLookAndFeelInfo);
|
||||
|
||||
@@ -64,7 +64,6 @@ import com.intellij.util.IJSwingUtilities
|
||||
import com.intellij.util.SVGLoader.colorPatcherProvider
|
||||
import com.intellij.util.concurrency.SynchronizedClearableLazy
|
||||
import com.intellij.util.ui.*
|
||||
import com.intellij.util.ui.StartupUiUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
@@ -499,7 +498,10 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
}
|
||||
|
||||
override fun getLookAndFeelCellRenderer(component: JComponent): ListCellRenderer<LafReference> {
|
||||
val themeManager = UiThemeProviderListManager.getInstance()
|
||||
val islandThemes = themeManager.getBundledThemeListForTargetUI(TargetUIType.ISLANDS)
|
||||
val welcomeMode = WelcomeFrame.getInstance() != null
|
||||
|
||||
return listCellRenderer {
|
||||
toolTipText = null
|
||||
text(value.name)
|
||||
@@ -521,6 +523,9 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
icon(getDisabledIcon(AllIcons.Actions.Restart, null))
|
||||
toolTipText = IdeBundle.message("ide.restart.required.comment")
|
||||
}
|
||||
else if (islandThemes.contains(theme)) {
|
||||
icon(AllIcons.General.Beta)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,14 @@ class UiThemeProviderListManager {
|
||||
.mapNotNull { it.theme.get() }
|
||||
}
|
||||
|
||||
fun getBundledThemeListForTargetUI(targetUI: TargetUIType): List<UIThemeLookAndFeelInfo> {
|
||||
val themes = mutableListOf<UIThemeLookAndFeelInfo>()
|
||||
getThemeListForTargetUI(targetUI).forEach { info ->
|
||||
if (!info.isThemeFromPlugin) themes.add(info)
|
||||
}
|
||||
return themes
|
||||
}
|
||||
|
||||
internal fun themeProviderAdded(provider: UIThemeProvider, pluginDescriptor: PluginDescriptor): LafEntry? {
|
||||
if (findLaFByProviderId(provider) != null) {
|
||||
// provider is already registered
|
||||
|
||||
+2
@@ -105,6 +105,8 @@ open class InternalUICustomization {
|
||||
|
||||
open fun attachIdeFrameBackgroundPainter(frame: IdeFrame, glassPane: IdeGlassPane): Unit = Unit
|
||||
|
||||
open fun updateBackgroundPainter() {}
|
||||
|
||||
open fun attachIdeFallbackBackgroundPainter(glassPane: IdeGlassPane): Unit = Unit
|
||||
|
||||
open fun attachDialogFallbackBackgroundPainter(glassPane: IdeGlassPane): Unit = Unit
|
||||
|
||||
+2
-1
@@ -4,10 +4,11 @@ package com.intellij.openapi.application.impl
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.border.Border
|
||||
|
||||
@ApiStatus.Internal
|
||||
open class ToolWindowUIDecorator() {
|
||||
open fun decorateAndReturnHolder(divider: JComponent, child: JComponent): JComponent? = null
|
||||
open fun decorateAndReturnHolder(divider: JComponent, child: JComponent, originalBorderBuilder: () -> Border): JComponent? = null
|
||||
|
||||
open fun createCustomToolWindowPaneHolder(): JPanel = JPanel()
|
||||
}
|
||||
+2
-2
@@ -18,7 +18,7 @@ import com.intellij.ui.scale.ScaleContext
|
||||
import com.intellij.util.ui.JBUI
|
||||
import java.awt.*
|
||||
|
||||
internal class IslandsGradientPainter(private val frame: IdeFrame, private val mainColor: Color) : AbstractPainter() {
|
||||
internal class IslandsGradientPainter(private val frame: IdeFrame, private val mainColor: Color, private val enabled: () -> Boolean) : AbstractPainter() {
|
||||
private val leftGradientCache: GradientTextureCache = GradientTextureCache()
|
||||
private val rightGradientCache: GradientTextureCache = GradientTextureCache()
|
||||
|
||||
@@ -26,7 +26,7 @@ internal class IslandsGradientPainter(private val frame: IdeFrame, private val m
|
||||
|
||||
private var doPaint = true
|
||||
|
||||
override fun needsRepaint(): Boolean = true
|
||||
override fun needsRepaint(): Boolean = enabled()
|
||||
|
||||
override fun executePaint(component: Component, g: Graphics2D) {
|
||||
if (doPaint) {
|
||||
|
||||
+18
-6
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl.islands
|
||||
|
||||
import com.intellij.openapi.fileEditor.impl.EditorTabPainterAdapter
|
||||
import com.intellij.ui.ColorUtil
|
||||
import com.intellij.ui.JBColor
|
||||
import com.intellij.ui.paint.RectanglePainter2D
|
||||
@@ -16,10 +17,21 @@ import com.intellij.util.ui.JBUI
|
||||
import java.awt.*
|
||||
import java.awt.geom.RoundRectangle2D
|
||||
|
||||
internal class ManyIslandsTabPainterAdapter : TabPainterAdapter {
|
||||
override val tabPainter: JBTabPainter = ManyIslandsTabPainter()
|
||||
internal class IslandsTabPainterAdapter(var isEnabled: Boolean) : TabPainterAdapter {
|
||||
private val editorAdapter = EditorTabPainterAdapter()
|
||||
private val islandsAdapter = IslandsTabPainter()
|
||||
|
||||
override val tabPainter: JBTabPainter
|
||||
get() {
|
||||
return if (isEnabled) islandsAdapter else editorAdapter.tabPainter
|
||||
}
|
||||
|
||||
override fun paintBackground(label: TabLabel, g: Graphics, tabs: JBTabsImpl) {
|
||||
if (!isEnabled) {
|
||||
editorAdapter.paintBackground(label, g, tabs)
|
||||
return
|
||||
}
|
||||
|
||||
val info = label.info
|
||||
val selected = info == tabs.selectedInfo
|
||||
val active = tabs.isActiveTabs(info)
|
||||
@@ -36,7 +48,7 @@ internal class ManyIslandsTabPainterAdapter : TabPainterAdapter {
|
||||
val accentedRect = Rectangle(rect.x, rect.y, rect.width, rect.height)
|
||||
JBInsets.removeFrom(accentedRect, JBInsets(5, 3, 5, 3))
|
||||
|
||||
(tabPainter as ManyIslandsTabPainter).paintTab(g2, accentedRect, info.tabColor, active, hovered, selected)
|
||||
(tabPainter as IslandsTabPainter).paintTab(g2, accentedRect, info.tabColor, active, hovered, selected)
|
||||
}
|
||||
finally {
|
||||
g2.dispose()
|
||||
@@ -44,7 +56,7 @@ internal class ManyIslandsTabPainterAdapter : TabPainterAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private class ManyIslandsTabTheme : TabTheme {
|
||||
private class IslandsTabTheme : TabTheme {
|
||||
override val background: Color
|
||||
get() = JBUI.CurrentTheme.EditorTabs.background()
|
||||
|
||||
@@ -74,8 +86,8 @@ private class ManyIslandsTabTheme : TabTheme {
|
||||
get() = JBColor.namedColor("EditorTabs.underlinedTabInactiveForeground", JBColor(0x000000, 0xFFFFFF))
|
||||
}
|
||||
|
||||
private class ManyIslandsTabPainter : JBTabPainter {
|
||||
private val myTheme = ManyIslandsTabTheme()
|
||||
private class IslandsTabPainter : JBTabPainter {
|
||||
private val myTheme = IslandsTabTheme()
|
||||
|
||||
override fun getTabTheme(): TabTheme = myTheme
|
||||
|
||||
|
||||
+218
-36
@@ -2,6 +2,7 @@
|
||||
package com.intellij.openapi.application.impl.islands
|
||||
|
||||
import com.intellij.ide.ui.LafManagerListener
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.openapi.actionSystem.ex.ActionButtonLook
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.impl.InternalUICustomization
|
||||
@@ -13,16 +14,20 @@ import com.intellij.openapi.ui.Splittable
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.wm.IdeFrame
|
||||
import com.intellij.openapi.wm.IdeGlassPane
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerEx
|
||||
import com.intellij.openapi.wm.impl.IdeBackgroundUtil
|
||||
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl
|
||||
import com.intellij.openapi.wm.impl.SquareStripeButtonLook
|
||||
import com.intellij.openapi.wm.impl.ToolWindowImpl
|
||||
import com.intellij.toolWindow.ToolWindowButtonManager
|
||||
import com.intellij.toolWindow.ToolWindowPaneNewButtonManager
|
||||
import com.intellij.toolWindow.xNext.island.XNextIslandHolder
|
||||
import com.intellij.ui.ClientProperty
|
||||
import com.intellij.ui.ExperimentalUI
|
||||
import com.intellij.ui.JBColor
|
||||
import com.intellij.ui.tabs.impl.TabPainterAdapter
|
||||
import com.intellij.ui.tabs.impl.JBEditorTabs
|
||||
import com.intellij.util.ui.JBSwingUtilities
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
@@ -30,31 +35,60 @@ import java.awt.*
|
||||
import java.awt.event.AWTEventListener
|
||||
import java.awt.event.HierarchyEvent
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.border.Border
|
||||
|
||||
internal class IslandsUICustomization : InternalUICustomization() {
|
||||
private val isIslandsAvailable = !Registry.`is`("llm.riderNext.enabled", false) && ExperimentalUI.isNewUI()
|
||||
|
||||
private var isManyIslandEnabledCache: Boolean? = null
|
||||
|
||||
private val isManyIslandEnabled: Boolean
|
||||
get() {
|
||||
return isIslandsAvailable && JBUI.getInt("Islands", 0) == 1
|
||||
var value = isManyIslandEnabledCache
|
||||
if (value == null) {
|
||||
value = isIslandsAvailable && JBUI.getInt("Islands", 0) == 1
|
||||
isManyIslandEnabledCache = value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private val isIslandsGradientEnabled: Boolean = Registry.`is`("idea.islands.gradient.enabled", true)
|
||||
private var isIslandsGradientEnabledCache: Boolean? = null
|
||||
|
||||
private val isIslandsGradientEnabled: Boolean
|
||||
get() {
|
||||
var value = isIslandsGradientEnabledCache
|
||||
if (value == null) {
|
||||
value = Registry.`is`("idea.islands.gradient.enabled", true) && UISettings.getInstance().differentiateProjects
|
||||
isIslandsGradientEnabledCache = value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
override fun updateBackgroundPainter() {
|
||||
isIslandsGradientEnabledCache = null
|
||||
}
|
||||
|
||||
override val isProjectCustomDecorationGradientPaint: Boolean = !isManyIslandEnabled || !isIslandsGradientEnabled
|
||||
|
||||
override val shouldPaintEditorFadeout: Boolean = !isManyIslandEnabled
|
||||
|
||||
private val toolWindowDecorator = object : ToolWindowUIDecorator() {
|
||||
override fun decorateAndReturnHolder(divider: JComponent, child: JComponent): JComponent {
|
||||
override val toolWindowUIDecorator: ToolWindowUIDecorator = object : ToolWindowUIDecorator() {
|
||||
override fun decorateAndReturnHolder(divider: JComponent, child: JComponent, originalBorderBuilder: () -> Border): JComponent {
|
||||
return XNextIslandHolder().apply {
|
||||
layout = BorderLayout()
|
||||
background = JBUI.CurrentTheme.ToolWindow.background()
|
||||
add(divider, BorderLayout.NORTH)
|
||||
add(child, BorderLayout.CENTER)
|
||||
|
||||
IslandsRoundedBorder.createToolWindowBorder(this)
|
||||
child.putClientProperty(IdeBackgroundUtil.NO_BACKGROUND, true)
|
||||
putClientProperty("originalBorderBuilder", originalBorderBuilder)
|
||||
|
||||
if (isManyIslandEnabled) {
|
||||
background = JBUI.CurrentTheme.ToolWindow.background()
|
||||
IslandsRoundedBorder.createToolWindowBorder(this)
|
||||
child.putClientProperty(IdeBackgroundUtil.NO_BACKGROUND, true)
|
||||
}
|
||||
else {
|
||||
border = originalBorderBuilder()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,27 +111,160 @@ internal class IslandsUICustomization : InternalUICustomization() {
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.HIERARCHY_EVENT_MASK)
|
||||
}
|
||||
|
||||
var oldManyIsland = isManyIslandEnabled
|
||||
|
||||
val connection = ApplicationManager.getApplication().messageBus.connect()
|
||||
connection.subscribe(LafManagerListener.TOPIC, LafManagerListener {
|
||||
val toolkit = Toolkit.getDefaultToolkit()
|
||||
|
||||
toolkit.removeAWTEventListener(awtListener)
|
||||
isManyIslandEnabledCache = null
|
||||
|
||||
if (isManyIslandEnabled && JBColor.isBright()) {
|
||||
val newManyIsland = isManyIslandEnabled
|
||||
|
||||
if (newManyIsland && JBColor.isBright()) {
|
||||
toolkit.addAWTEventListener(awtListener, AWTEvent.HIERARCHY_EVENT_MASK)
|
||||
}
|
||||
|
||||
if (oldManyIsland == newManyIsland) {
|
||||
return@LafManagerListener
|
||||
}
|
||||
if (newManyIsland) {
|
||||
enableManyIslands()
|
||||
}
|
||||
else {
|
||||
disableManyIslands()
|
||||
}
|
||||
|
||||
oldManyIsland = newManyIsland
|
||||
})
|
||||
}
|
||||
|
||||
private val tabPainterAdapter = ManyIslandsTabPainterAdapter()
|
||||
private fun enableManyIslands() {
|
||||
editorTabPainterAdapter.isEnabled = true
|
||||
|
||||
override val toolWindowUIDecorator: ToolWindowUIDecorator
|
||||
get() {
|
||||
if (isManyIslandEnabled) {
|
||||
return toolWindowDecorator
|
||||
// XXX: dialogs
|
||||
|
||||
for (frame in WindowManager.getInstance().allProjectFrames) {
|
||||
val toolwindows = mutableSetOf<String>()
|
||||
|
||||
UIUtil.forEachComponentInHierarchy(frame.component) {
|
||||
when (it) {
|
||||
is XNextIslandHolder -> {
|
||||
setToolWindowManyBorder(it)
|
||||
|
||||
val id = it.getClientProperty("ToolWindow.ID")
|
||||
if (id is String) {
|
||||
toolwindows.add(id)
|
||||
}
|
||||
}
|
||||
is EditorsSplitters -> {
|
||||
IslandsRoundedBorder.createEditorBorder(it, editorTabPainterAdapter)
|
||||
clearParentNoBackground(it)
|
||||
}
|
||||
is JBEditorTabs -> {
|
||||
if (it.parent is EditorsSplitters) {
|
||||
ClientProperty.putRecursive(it, IdeBackgroundUtil.NO_BACKGROUND, true)
|
||||
}
|
||||
}
|
||||
is ManyIslandDivider -> {
|
||||
it.configure(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val project = frame.project
|
||||
if (project != null) {
|
||||
val manager = ToolWindowManager.getInstance(project) as ToolWindowManagerEx
|
||||
for (toolwindow in manager.toolWindows) {
|
||||
if (!toolwindows.contains(toolwindow.id) && toolwindow is ToolWindowImpl) {
|
||||
toolwindow.getNullableDecorator()?.also {
|
||||
UIUtil.findComponentOfType(it, XNextIslandHolder::class.java)?.also { holder ->
|
||||
setToolWindowManyBorder(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.toolWindowUIDecorator
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableManyIslands() {
|
||||
editorTabPainterAdapter.isEnabled = false
|
||||
|
||||
// XXX: dialogs
|
||||
|
||||
for (frame in WindowManager.getInstance().allProjectFrames) {
|
||||
val toolwindows = mutableSetOf<String>()
|
||||
|
||||
UIUtil.forEachComponentInHierarchy(frame.component) {
|
||||
if (it is JComponent) {
|
||||
ClientProperty.removeRecursive(it, IdeBackgroundUtil.NO_BACKGROUND)
|
||||
}
|
||||
|
||||
when (it) {
|
||||
is XNextIslandHolder -> {
|
||||
setOriginalToolWindowBorder(it)
|
||||
|
||||
val id = it.getClientProperty("ToolWindow.ID")
|
||||
if (id is String) {
|
||||
toolwindows.add(id)
|
||||
}
|
||||
}
|
||||
is EditorsSplitters -> {
|
||||
it.border = null
|
||||
}
|
||||
is ManyIslandDivider -> {
|
||||
it.configure(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val project = frame.project
|
||||
if (project != null) {
|
||||
val manager = ToolWindowManager.getInstance(project) as ToolWindowManagerEx
|
||||
for (toolwindow in manager.toolWindows) {
|
||||
if (!toolwindows.contains(toolwindow.id) && toolwindow is ToolWindowImpl) {
|
||||
toolwindow.getNullableDecorator()?.also {
|
||||
UIUtil.findComponentOfType(it, XNextIslandHolder::class.java)?.also { holder ->
|
||||
setOriginalToolWindowBorder(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setOriginalToolWindowBorder(holder: XNextIslandHolder) {
|
||||
val builder = holder.getClientProperty("originalBorderBuilder")
|
||||
if (builder is Function0<*>) {
|
||||
val border = builder()
|
||||
if (border is Border) {
|
||||
holder.setSuperBorder(border)
|
||||
}
|
||||
}
|
||||
holder.background = JBColor.PanelBackground
|
||||
}
|
||||
|
||||
private fun setToolWindowManyBorder(holder: XNextIslandHolder) {
|
||||
holder.background = JBUI.CurrentTheme.ToolWindow.background()
|
||||
IslandsRoundedBorder.createToolWindowBorder(holder)
|
||||
clearParentNoBackground(holder)
|
||||
|
||||
for (child in holder.components) {
|
||||
ClientProperty.putRecursive(child as JComponent, IdeBackgroundUtil.NO_BACKGROUND, true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearParentNoBackground(component: JComponent) {
|
||||
var nextComponent: JComponent? = component
|
||||
|
||||
while (nextComponent != null && ClientProperty.get(nextComponent, IdeBackgroundUtil.NO_BACKGROUND) != null) {
|
||||
ClientProperty.removeRecursive(nextComponent, IdeBackgroundUtil.NO_BACKGROUND)
|
||||
nextComponent = nextComponent.parent as JComponent?
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureToolWindowPane(toolWindowPaneParent: JComponent, buttonManager: ToolWindowButtonManager) {
|
||||
if (isManyIslandEnabled && buttonManager is ToolWindowPaneNewButtonManager) {
|
||||
@@ -129,15 +296,9 @@ internal class IslandsUICustomization : InternalUICustomization() {
|
||||
}
|
||||
|
||||
override fun createCustomDivider(isVertical: Boolean, splitter: Splittable): Divider? {
|
||||
if (isManyIslandEnabled) {
|
||||
return object : OnePixelDivider(isVertical, splitter) {
|
||||
override fun paint(g: Graphics) {
|
||||
}
|
||||
}.also {
|
||||
it.putClientProperty("DividerWidth", 0)
|
||||
}
|
||||
return ManyIslandDivider(isVertical, splitter).also {
|
||||
it.configure(isManyIslandEnabled)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun configureRendererComponent(component: JComponent) {
|
||||
@@ -154,34 +315,34 @@ internal class IslandsUICustomization : InternalUICustomization() {
|
||||
|
||||
override fun configureEditorsSplitters(component: EditorsSplitters) {
|
||||
if (isManyIslandEnabled) {
|
||||
IslandsRoundedBorder.createEditorBorder(component, tabPainterAdapter)
|
||||
IslandsRoundedBorder.createEditorBorder(component, editorTabPainterAdapter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun paintBeforeEditorEmptyText(component: JComponent, graphics: Graphics) {
|
||||
if (isManyIslandEnabled) {
|
||||
IslandsRoundedBorder.paintBeforeEditorEmptyText(component, graphics, tabPainterAdapter)
|
||||
IslandsRoundedBorder.paintBeforeEditorEmptyText(component, graphics, editorTabPainterAdapter)
|
||||
}
|
||||
}
|
||||
|
||||
override val editorTabPainterAdapter: TabPainterAdapter
|
||||
get() {
|
||||
if (isManyIslandEnabled) {
|
||||
return tabPainterAdapter
|
||||
}
|
||||
return super.editorTabPainterAdapter
|
||||
}
|
||||
override val editorTabPainterAdapter: IslandsTabPainterAdapter = IslandsTabPainterAdapter(isManyIslandEnabled)
|
||||
|
||||
private fun getMainBackgroundColor(): Color {
|
||||
return JBColor.namedColor("MainWindow.background", JBColor.PanelBackground)
|
||||
}
|
||||
|
||||
override fun getCustomMainBackgroundColor(): Color? {
|
||||
if (isManyIslandEnabled) {
|
||||
return JBColor.namedColor("MainWindow.background", JBColor.PanelBackground)
|
||||
return getMainBackgroundColor()
|
||||
}
|
||||
return super.getCustomMainBackgroundColor()
|
||||
return null
|
||||
}
|
||||
|
||||
override fun attachIdeFrameBackgroundPainter(frame: IdeFrame, glassPane: IdeGlassPane) {
|
||||
if (isManyIslandEnabled && isIslandsGradientEnabled && glassPane is IdeGlassPaneImpl) {
|
||||
glassPane.addFallbackBackgroundPainter(IslandsGradientPainter(frame, getCustomMainBackgroundColor()!!))
|
||||
if (glassPane is IdeGlassPaneImpl) {
|
||||
glassPane.addFallbackBackgroundPainter(IslandsGradientPainter(frame, getMainBackgroundColor()) {
|
||||
isManyIslandEnabled && isIslandsGradientEnabled
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,4 +370,25 @@ internal class IslandsUICustomization : InternalUICustomization() {
|
||||
}
|
||||
return graphics
|
||||
}
|
||||
}
|
||||
|
||||
private class ManyIslandDivider(isVertical: Boolean, splitter: Splittable) : OnePixelDivider(isVertical, splitter) {
|
||||
private var doPaint = true
|
||||
|
||||
fun configure(manyIsland: Boolean) {
|
||||
doPaint = !manyIsland
|
||||
|
||||
if (manyIsland) {
|
||||
putClientProperty("DividerWidth", 0)
|
||||
}
|
||||
else {
|
||||
putClientProperty("DividerWidth", null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun paint(g: Graphics) {
|
||||
if (doPaint) {
|
||||
super.paint(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -486,6 +486,8 @@ internal class ToolWindowImpl(
|
||||
toolWindowManager.stretchHeight(this, value)
|
||||
}
|
||||
|
||||
internal fun getNullableDecorator() = decorator
|
||||
|
||||
override fun getDecorator(): InternalDecoratorImpl = decorator!!
|
||||
|
||||
override fun setAdditionalGearActions(value: ActionGroup?) {
|
||||
|
||||
@@ -279,8 +279,12 @@ class InternalDecoratorImpl internal constructor(
|
||||
Mode.SINGLE, Mode.CELL -> {
|
||||
layout = BorderLayout()
|
||||
|
||||
InternalUICustomization.getInstance()?.toolWindowUIDecorator?.decorateAndReturnHolder(dividerAndHeader, myDecoratorChild)?.let {
|
||||
val decorator = InternalUICustomization.getInstance()?.toolWindowUIDecorator
|
||||
?.decorateAndReturnHolder(dividerAndHeader, myDecoratorChild) { InnerPanelBorder(toolWindow) }
|
||||
|
||||
decorator?.let {
|
||||
add(it, BorderLayout.CENTER)
|
||||
putClientProperty("ToolWindow.ID", toolWindowId)
|
||||
} ?: run {
|
||||
add(dividerAndHeader, BorderLayout.NORTH)
|
||||
add(myDecoratorChild, BorderLayout.CENTER)
|
||||
|
||||
@@ -617,7 +617,7 @@ class ToolWindowPane private constructor(
|
||||
}
|
||||
|
||||
override fun createDivider(): Divider {
|
||||
return InternalUICustomization.getInstance()?.createCustomDivider(isVisible, this)
|
||||
return InternalUICustomization.getInstance()?.createCustomDivider(isVertical, this)
|
||||
?: super.createDivider().also { it.background = JBUI.CurrentTheme.ToolWindow.mainBorderColor() }
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ class XNextIslandHolder : JPanel() {
|
||||
super.setBorder(border)
|
||||
}
|
||||
|
||||
fun setSuperBorder(border: Border?) {
|
||||
super.setBorder(border)
|
||||
}
|
||||
|
||||
override fun isOpaque(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -690,8 +690,8 @@
|
||||
|
||||
<bundledColorScheme id="Island Dark" path="/themes/islands/IslandSchemeDark.xml"/>
|
||||
|
||||
<themeProvider id="Many Islands Dark" path="/themes/islands/ManyIslandsDark.theme.json" targetUi="islands" restartRequired="true"/>
|
||||
<themeProvider id="Many Islands Light" path="/themes/islands/ManyIslandsLight.theme.json" targetUi="islands" restartRequired="true"/>
|
||||
<themeProvider id="Many Islands Dark" path="/themes/islands/ManyIslandsDark.theme.json" targetUi="islands"/>
|
||||
<themeProvider id="Many Islands Light" path="/themes/islands/ManyIslandsLight.theme.json" targetUi="islands"/>
|
||||
|
||||
<themeMetadataProvider path="/themes/metadata/IntelliJPlatform.themeMetadata.json"/>
|
||||
<themeMetadataProvider path="/themes/metadata/JDK.themeMetadata.json"/>
|
||||
|
||||
@@ -116,6 +116,24 @@ public final class ClientProperty {
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static <T> void removeRecursive(@NotNull JComponent component, @NotNull Key<T> key) {
|
||||
Map<Key<?>, ContainerListener> listeners = get(component, RECURSIVE_LISTENERS);
|
||||
|
||||
if (listeners != null) {
|
||||
ContainerListener existingListener = listeners.remove(key);
|
||||
if (existingListener != null) {
|
||||
component.removeContainerListener(existingListener);
|
||||
|
||||
if (listeners.isEmpty()) {
|
||||
put(component, RECURSIVE_LISTENERS, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
put(component, key, null);
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
private static @Nullable JComponent getPropertiesHolder(@Nullable Component component) {
|
||||
if (component instanceof JComponent) return (JComponent)component;
|
||||
|
||||
Reference in New Issue
Block a user