IJPL-208969 Islands: Fadeout gradient is missing if 'Squeeze tabs' option is on

(cherry picked from commit a000a5a4ae216a56cf0c62f0aa8c56e033776965)

IJ-CR-194805

GitOrigin-RevId: a0c04b12d7e148b35b9538094cb746b0d439aca1
This commit is contained in:
Pavel Porvatov
2026-03-19 12:44:57 +00:00
committed by intellij-monorepo-bot
parent ff629bcd76
commit a175904b9f
6 changed files with 65 additions and 16 deletions
@@ -3,9 +3,12 @@ package com.intellij.ui.tabs.impl
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.serviceOrNull
import com.intellij.ui.tabs.JBTabPainter
import com.intellij.ui.tabs.JBTabsPosition
import org.jetbrains.annotations.ApiStatus
import java.awt.Color
import java.awt.Insets
import javax.swing.JComponent
@ApiStatus.Experimental
@ApiStatus.Internal
@@ -19,9 +22,16 @@ open class IslandsPainterProvider {
open fun useMacScrollBar(): Boolean = false
open fun isTabOccupiesWholeHeight(): Boolean = true
open fun getSingleRowTabInsets(tabsPosition: JBTabsPosition): Insets? = null
open fun isRoundedTabDuringDrag(): Boolean = false
open fun getEditorTabComposedBgColor(
component: JComponent,
tabPainter: JBTabPainter,
tabColor: Color?,
active: Boolean,
hovered: Boolean,
selected: Boolean,
): Color? = null
}
@@ -22,6 +22,7 @@ import com.intellij.ui.ClientProperty
import com.intellij.ui.ColorUtil
import com.intellij.ui.ExperimentalUI.Companion.isNewUI
import com.intellij.ui.InplaceButton
import com.intellij.ui.IslandsState
import com.intellij.ui.LayeredIcon
import com.intellij.ui.RelativeFont
import com.intellij.ui.SimpleColoredComponent
@@ -347,8 +348,8 @@ open class TabLabel @Internal constructor(
protected fun paintFadeout(g: Graphics) {
val g2d = g.create() as Graphics2D
try {
val isTabOccupiesWholeHeight = IslandsPainterProvider.getInstance()?.isTabOccupiesWholeHeight() != false
val tabBg = if (isTabOccupiesWholeHeight) effectiveBackground else tabs.tabPainter.getBackgroundColor()
val isIslands = IslandsState.isEnabled()
val tabBg = if (isIslands) tabs.tabPainter.getBackgroundColor() else effectiveBackground
val transparent = ColorUtil.withAlpha(tabBg, 0.0)
val borderThickness = tabs.borderThickness
val width = JBUI.scale(MathUtil.clamp(Registry.intValue("ide.editor.tabs.fadeout.width", 10), 1, 200))
@@ -364,8 +365,18 @@ open class TabLabel @Internal constructor(
val contentRect = labelPlaceholder.bounds
// Fadeout for right side before pin/close button (needed only in side placements and in squeezing layout)
if (contentRect.width < labelPlaceholder.preferredSize.width + tabs.tabHGap) {
if (isTabOccupiesWholeHeight) { // Can be implemented later for isTabOccupiesWholeHeight
val rightRect = Rectangle(contentRect.x + contentRect.width - width, borderThickness, width, rect.height - 2 * borderThickness)
val rightRect = Rectangle(contentRect.x + contentRect.width - width, borderThickness, width, rect.height - 2 * borderThickness)
if (isIslands) {
val composedBg = IslandsPainterProvider.getInstance()?.getEditorTabComposedBgColor(
tabs, tabs.tabPainter, info.tabColor, tabs.isActiveTabs(info), isHovered, isSelected)
if (composedBg != null) {
val labelCoord = SwingUtilities.convertPoint(label, 0, 0, this)
rightRect.y = labelCoord.y
rightRect.height = label.height
paintGradientRect(g2d, rightRect, ColorUtil.withAlpha(composedBg, 0.0), composedBg)
}
}
else {
paintGradientRect(g2d, rightRect, transparent, tabBg)
}
}
@@ -94,8 +94,6 @@ open class InternalUICustomization {
open val isMainMenuBottomBorder: Boolean = true
open val isTabOccupiesWholeHeight: Boolean = true
open val isRoundedTabDuringDrag: Boolean = false
internal open fun configureToolWindowPane(toolWindowPaneParent: JComponent, buttonManager: ToolWindowButtonManager) {}
@@ -2,10 +2,13 @@
package com.intellij.openapi.application.impl.islands
import com.intellij.openapi.application.impl.InternalUICustomization
import com.intellij.ui.tabs.JBTabPainter
import com.intellij.ui.tabs.JBTabsPosition
import com.intellij.ui.tabs.impl.IslandsPainterProvider
import com.intellij.ui.tabs.impl.TabPainterAdapter
import java.awt.Color
import java.awt.Insets
import javax.swing.JComponent
internal class IslandsInternalPainterProvider : IslandsPainterProvider() {
override fun createCommonTabPainter(): TabPainterAdapter? {
@@ -16,11 +19,6 @@ internal class IslandsInternalPainterProvider : IslandsPainterProvider() {
return InternalUICustomization.getInstance()?.isMacScrollBar == true
}
override fun isTabOccupiesWholeHeight(): Boolean {
val customization = InternalUICustomization.getInstance()
return customization?.isTabOccupiesWholeHeight ?: super.isTabOccupiesWholeHeight()
}
override fun getSingleRowTabInsets(tabsPosition: JBTabsPosition): Insets? {
val customization = InternalUICustomization.getInstance()
return if (customization == null) super.getSingleRowTabInsets(tabsPosition) else customization.getSingleRowTabInsets(tabsPosition)
@@ -29,4 +27,15 @@ internal class IslandsInternalPainterProvider : IslandsPainterProvider() {
override fun isRoundedTabDuringDrag(): Boolean {
return InternalUICustomization.getInstance()?.isRoundedTabDuringDrag == true
}
override fun getEditorTabComposedBgColor(
component: JComponent,
tabPainter: JBTabPainter,
tabColor: Color?,
active: Boolean,
hovered: Boolean,
selected: Boolean,
): Color? {
return (tabPainter as? IslandsTabPainter)?.getEditorTabComposedBgColor(component, tabColor, active, hovered, selected)
}
}
@@ -26,6 +26,7 @@ import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.Point
import java.awt.Rectangle
import javax.swing.JComponent
import kotlin.math.floor
internal class IslandsTabPainterAdapter(isDefault: Boolean, debugger: Boolean, var isEnabled: Boolean) : TabPainterAdapter {
@@ -191,6 +192,29 @@ internal open class IslandsTabPainter(isDefault: Boolean, isToolWindow: Boolean)
RectanglePainter2D.DRAW.paint(g, x, y, width, height, arc)
}
/**
* Calculates the composed background color for editor tabs. The resulting color is not transparent,
* see [paintTab] for details.
*/
fun getEditorTabComposedBgColor(
component: JComponent,
tabColor: Color?,
active: Boolean,
hovered: Boolean,
selected: Boolean,
): Color {
var result = if (myFillBackground) getBackgroundColor() else UIUtil.getBgFillColor(component)
if (tabColor != null) {
result = ColorUtil.alphaBlending(ColorUtil.withAlpha(tabColor, 0.9), result)
}
val (fill, _) = getColors(active, hovered, selected)
result = ColorUtil.alphaBlending(fill, result)
return result
}
private val hoverBackground = JBColor("EditorTabs.hoverBackground", JBColor(Color(0xE5, 0xEE, 0xFF, 0x80), Color(0x34, 0x3E, 0x51, 0x80)))
private val inactiveBorderColor = JBColor("EditorTabs.inactiveUnderlinedTabBorderColor", JBColor(Color(0x7F, 0x99, 0xC3, 0x80), Color(0x7F, 0x99, 0xC3, 0x80)))
@@ -197,9 +197,6 @@ internal class IslandsUICustomization : InternalUICustomization() {
return !isManyIslandEnabled
}
override val isTabOccupiesWholeHeight: Boolean
get() = !isManyIslandEnabled
override val isRoundedTabDuringDrag: Boolean
get() = isManyIslandEnabled && (WindowRoundedCornersManager.isAvailable() || StartupUiUtil.isWaylandToolkit())