From 60583a1e489a984070272fed391c042877a416d3 Mon Sep 17 00:00:00 2001 From: Sebastiano Poggi Date: Fri, 10 May 2024 15:48:20 +0200 Subject: [PATCH] Fix scaling in the IDE once again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out the previous change was wrong — the issue was mostly due to us taking some JBDimensions and not un-scaling them before using their values. To better match the line width in Swing, I also tweaked the border modifier logic to not round up line widths, as that was causing lines to be drawn thicker than they should. This is not a full fix, since Swing does some tweaks in DarculaNewUIUtils#paintRectangle, and it probably just draws things slightly differently. However, this does considerably improve things at most IDE zoom levels, at the cost of some minor fuzziness at 110% zoom. --- .../jewel/foundation/modifier/Border.kt | 2 +- .../bridge/BridgePainterHintsProvider.kt | 1 - .../org/jetbrains/jewel/bridge/BridgeUtils.kt | 24 ++++++++-- .../jewel/bridge/ToolWindowExtensions.kt | 3 +- .../jewel/bridge/theme/IntUiBridge.kt | 44 +++++++------------ .../jewel/bridge/theme/SwingBridgeTheme.kt | 4 +- 6 files changed, 41 insertions(+), 37 deletions(-) diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt index af287dd598..492fd3dbc0 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt @@ -98,7 +98,7 @@ private fun Modifier.drawBorderWithAlignment( drawContent() val strokeWidthPx = - min(if (width == Dp.Hairline) 1f else ceil(width.toPx()), ceil(size.minDimension / 2)) + min(if (width == Dp.Hairline) 1f else width.toPx(), size.minDimension / 2) .coerceAtLeast(1f) val expandWidthPx = expand.takeOrElse { 0.dp }.toPx() diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt index 47782dd827..f950a362b5 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt @@ -5,7 +5,6 @@ import androidx.compose.ui.graphics.Color import com.intellij.ide.ui.UITheme import com.intellij.openapi.diagnostic.thisLogger import com.intellij.ui.NewUI -import org.jetbrains.jewel.bridge.theme.isNewUiTheme import org.jetbrains.jewel.foundation.InternalJewelApi import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.foundation.util.inDebugMode diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt index 4e085ca669..1139db1a1f 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt @@ -19,10 +19,12 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.isUnspecified import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.takeOrElse +import com.intellij.ide.ui.LafManager import com.intellij.ide.ui.UISettingsUtils import com.intellij.openapi.diagnostic.Logger import com.intellij.ui.JBColor import com.intellij.ui.JBColor.marker +import com.intellij.ui.NewUI import com.intellij.ui.scale.JBUIScale.scale import com.intellij.util.ui.JBDimension import com.intellij.util.ui.JBFont @@ -118,7 +120,8 @@ public fun JBInsets.toPaddingValues(): PaddingValues = * instance, this function delegates to the specific [toDpSize] for it, * which is scaling-aware. */ -public fun Dimension.toDpSize(): DpSize = DpSize(width.dp, height.dp) +public fun Dimension.toDpSize(): DpSize = + if (this is JBDimension) toDpSize() else DpSize(width.dp, height.dp) /** * Converts a [JBDimension] to [DpSize], in a scaling-aware way. This means @@ -195,9 +198,22 @@ internal operator fun TextUnit.plus(delta: Float): TextUnit = else -> this } -internal fun retrieveIdeaDensity(sourceDensity: Density): Density { +internal fun scaleDensityWithIdeScale(sourceDensity: Density): Density { val ideaScale = UISettingsUtils.getInstance().currentIdeScale - val fontScale = sourceDensity.fontScale * ideaScale + val density = sourceDensity.density * ideaScale - return Density(sourceDensity.density, fontScale) + return Density(density, sourceDensity.fontScale) +} + +internal fun isNewUiTheme(): Boolean { + if (!NewUI.isEnabled()) return false + + val lafName = lafName() + return lafName == "Light" || lafName == "Dark" || lafName == "Light with Light Header" +} + +@Suppress("UnstableApiUsage") +internal fun lafName(): String { + val lafInfo = LafManager.getInstance().currentUIThemeLookAndFeel + return lafInfo.name } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt index 1292895c0c..65666ba82b 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt @@ -1,11 +1,12 @@ package org.jetbrains.jewel.bridge import androidx.compose.runtime.Composable +import com.intellij.openapi.util.NlsContexts.TabTitle import com.intellij.openapi.wm.ToolWindow import org.jetbrains.jewel.foundation.enableNewSwingCompositing public fun ToolWindow.addComposeTab( - tabDisplayName: String, + @TabTitle tabDisplayName: String, isLockable: Boolean = true, isCloseable: Boolean = false, content: @Composable ToolWindowScope.() -> Unit, diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt index e24936a83f..33d7d29124 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt @@ -13,19 +13,19 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.isSpecified import androidx.compose.ui.unit.takeOrElse -import com.intellij.ide.ui.LafManager import com.intellij.ide.ui.laf.darcula.DarculaUIUtil import com.intellij.ide.ui.laf.intellij.IdeaPopupMenuUI import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.registry.Registry import com.intellij.ui.JBColor -import com.intellij.ui.NewUI import com.intellij.util.ui.DirProvider import com.intellij.util.ui.JBUI import com.intellij.util.ui.NamedColorUtil import org.jetbrains.jewel.bridge.bridgePainterProvider import org.jetbrains.jewel.bridge.createVerticalBrush import org.jetbrains.jewel.bridge.dp +import org.jetbrains.jewel.bridge.isNewUiTheme +import org.jetbrains.jewel.bridge.lafName import org.jetbrains.jewel.bridge.readFromLaF import org.jetbrains.jewel.bridge.retrieveArcAsCornerSizeOrDefault import org.jetbrains.jewel.bridge.retrieveArcAsCornerSizeWithFallbacks @@ -36,6 +36,7 @@ import org.jetbrains.jewel.bridge.retrieveIntAsDpOrUnspecified import org.jetbrains.jewel.bridge.retrieveTextStyle import org.jetbrains.jewel.bridge.toComposeColor import org.jetbrains.jewel.bridge.toComposeColorOrUnspecified +import org.jetbrains.jewel.bridge.toDpSize import org.jetbrains.jewel.bridge.toPaddingValues import org.jetbrains.jewel.foundation.GlobalColors import org.jetbrains.jewel.foundation.GlobalMetrics @@ -227,13 +228,13 @@ private fun readDefaultButtonStyle(): ButtonStyle { borderHovered = normalBorder, ) - val minimumSize = JBUI.CurrentTheme.Button.minimumSize() + val minimumSize = JBUI.CurrentTheme.Button.minimumSize().toDpSize() return ButtonStyle( colors = colors, metrics = ButtonMetrics( cornerSize = retrieveArcAsCornerSizeWithFallbacks("Button.default.arc", "Button.arc"), padding = PaddingValues(horizontal = 14.dp), // see DarculaButtonUI.HORIZONTAL_PADDING - minSize = DpSize(minimumSize.width.dp, minimumSize.height.dp), + minSize = DpSize(minimumSize.width, minimumSize.height), borderWidth = DarculaUIUtil.LW.dp, ), ) @@ -270,14 +271,14 @@ private fun readOutlinedButtonStyle(): ButtonStyle { borderHovered = normalBorder, ) - val minimumSize = JBUI.CurrentTheme.Button.minimumSize() + val minimumSize = JBUI.CurrentTheme.Button.minimumSize().toDpSize() return ButtonStyle( colors = colors, metrics = ButtonMetrics( cornerSize = CornerSize(DarculaUIUtil.BUTTON_ARC.dp / 2), padding = PaddingValues(horizontal = 14.dp), // see DarculaButtonUI.HORIZONTAL_PADDING - minSize = DpSize(minimumSize.width.dp, minimumSize.height.dp), + minSize = DpSize(minimumSize.width, minimumSize.height), borderWidth = DarculaUIUtil.LW.dp, ), ) @@ -468,13 +469,13 @@ private fun readDefaultDropdownStyle( iconTintHovered = Color.Unspecified, ) - val minimumSize = JBUI.CurrentTheme.ComboBox.minimumSize() + val minimumSize = JBUI.CurrentTheme.ComboBox.minimumSize().toDpSize() val arrowWidth = JBUI.CurrentTheme.Component.ARROW_AREA_WIDTH.dp return DropdownStyle( colors = colors, metrics = DropdownMetrics( - arrowMinSize = DpSize(arrowWidth, minimumSize.height.dp), - minSize = DpSize(minimumSize.width.dp + arrowWidth, minimumSize.height.dp), + arrowMinSize = DpSize(arrowWidth, minimumSize.height), + minSize = DpSize(minimumSize.width + arrowWidth, minimumSize.height), cornerSize = CornerSize(DarculaUIUtil.COMPONENT_ARC.dp / 2), contentPadding = retrieveInsetsAsPaddingValues("ComboBox.padding"), borderWidth = DarculaUIUtil.LW.dp, @@ -517,15 +518,15 @@ private fun readUndecoratedDropdownStyle( ) val arrowWidth = JBUI.CurrentTheme.Component.ARROW_AREA_WIDTH.dp - val minimumSize = JBUI.CurrentTheme.Button.minimumSize() + val minimumSize = JBUI.CurrentTheme.Button.minimumSize().toDpSize() return DropdownStyle( colors = colors, metrics = DropdownMetrics( - arrowMinSize = DpSize(arrowWidth, minimumSize.height.dp), - minSize = DpSize(minimumSize.width.dp + arrowWidth, minimumSize.height.dp), + arrowMinSize = DpSize(arrowWidth, minimumSize.height), + minSize = DpSize(minimumSize.width + arrowWidth, minimumSize.height), cornerSize = CornerSize(JBUI.CurrentTheme.MainToolbar.Dropdown.hoverArc().dp), - contentPadding = JBUI.CurrentTheme.MainToolbar.Dropdown.borderInsets().toPaddingValues(), + contentPadding = PaddingValues(3.dp), // from com.intellij.ide.ui.laf.darcula.ui.DarculaComboBoxUI.getDefaultComboBoxInsets borderWidth = 0.dp, ), icons = DropdownIcons(chevronDown = bridgePainterProvider("general/chevron-down.svg")), @@ -852,13 +853,13 @@ private fun readTextFieldStyle(textFieldStyle: TextStyle): TextFieldStyle { placeholder = NamedColorUtil.getInactiveTextColor().toComposeColor(), ) - val minimumSize = JBUI.CurrentTheme.TextField.minimumSize() + val minimumSize = JBUI.CurrentTheme.TextField.minimumSize().toDpSize() return TextFieldStyle( colors = colors, metrics = TextFieldMetrics( cornerSize = CornerSize(DarculaUIUtil.COMPONENT_ARC.dp / 2), contentPadding = PaddingValues(horizontal = 9.dp, vertical = 2.dp), - minSize = DpSize(minimumSize.width.dp, minimumSize.height.dp), + minSize = DpSize(minimumSize.width, minimumSize.height), borderWidth = DarculaUIUtil.LW.dp, ), textStyle = textFieldStyle, @@ -1056,16 +1057,3 @@ private fun readIconButtonStyle(): IconButtonStyle = borderHovered = retrieveColorOrUnspecified("ActionButton.hoverBorderColor"), ), ) - -internal fun isNewUiTheme(): Boolean { - if (!NewUI.isEnabled()) return false - - val lafName = lafName() - return lafName == "Light" || lafName == "Dark" || lafName == "Light with Light Header" -} - -@Suppress("UnstableApiUsage") -private fun lafName(): String { - val lafInfo = LafManager.getInstance().currentUIThemeLookAndFeel - return lafInfo.name -} diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/SwingBridgeTheme.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/SwingBridgeTheme.kt index 2a17ca4071..ca8a7012a3 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/SwingBridgeTheme.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/SwingBridgeTheme.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalDensity import com.intellij.openapi.components.service import org.jetbrains.jewel.bridge.BridgePainterHintsProvider import org.jetbrains.jewel.bridge.SwingBridgeService -import org.jetbrains.jewel.bridge.retrieveIdeaDensity +import org.jetbrains.jewel.bridge.scaleDensityWithIdeScale import org.jetbrains.jewel.foundation.ExperimentalJewelApi import org.jetbrains.jewel.ui.ComponentStyling import org.jetbrains.jewel.ui.painter.LocalPainterHintsProvider @@ -29,7 +29,7 @@ public fun SwingBridgeTheme(content: @Composable () -> Unit) { ) { CompositionLocalProvider( LocalPainterHintsProvider provides BridgePainterHintsProvider(themeData.themeDefinition.isDark), - LocalDensity provides retrieveIdeaDensity(LocalDensity.current), + LocalDensity provides scaleDensityWithIdeScale(LocalDensity.current), ) { content() }