From 212187cc811adabe89e5a3d48a12b23a3fd7e09e Mon Sep 17 00:00:00 2001 From: Sasha Blashenkov Date: Sun, 21 May 2023 23:47:01 +0200 Subject: [PATCH] Fix RIDER-93638 Solution icons are cropped in Presentation mode, fix RIDER-93623 Solutions icons are different in project dropdown, fix RIDER-93676 Got it popup is not displayed GitOrigin-RevId: e9a61b80493965b758c38545034cbc09d4973d92 --- .../ide/ProjectWindowCustomizerService.kt | 65 +++++++++++++------ .../ProjectToolbarWidgetAction.kt | 4 +- .../src/com/intellij/util/ui/AvatarUtils.kt | 16 ++++- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt b/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt index 949c1193d531..76b08b5373e3 100644 --- a/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt +++ b/platform/platform-impl/src/com/intellij/ide/ProjectWindowCustomizerService.kt @@ -1,6 +1,7 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide +import com.intellij.ide.ui.LafManagerListener import com.intellij.ide.ui.UISettings import com.intellij.ide.ui.UISettingsListener import com.intellij.ide.util.PropertiesComponent @@ -23,6 +24,44 @@ import java.awt.* import javax.swing.Icon import javax.swing.JComponent +private fun getProjectPath(project: Project): String { + val recentProjectManager = RecentProjectsManagerBase.getInstanceEx() + return recentProjectManager.getProjectPath(project) ?: project.basePath ?: run { + //thisLogger().warn("Impossible: no path for project $project") + "" + } +} + +private fun getProjectNameForIcon(project: Project): String { + val path = getProjectPath(project) + return RecentProjectIconHelper.getProjectName(path) +} + +@Service(Service.Level.PROJECT) +private class ProjectWindowCustomizerIconCache(private val project: Project) { + var cachedIcon = getIconRaw() + private set + + init { + project.messageBus.connect().subscribe(UISettingsListener.TOPIC, UISettingsListener { + revalidate() + }) + + project.messageBus.connect().subscribe(LafManagerListener.TOPIC, LafManagerListener { + revalidate() + }) + } + + private fun revalidate() { + cachedIcon = getIconRaw() + } + + private fun getIconRaw(): Icon { + val path = getProjectPath(project) + return RecentProjectsManagerBase.getInstanceEx().getProjectIcon(path, true) + } +} + @Service class ProjectWindowCustomizerService : Disposable { companion object { @@ -33,7 +72,6 @@ class ProjectWindowCustomizerService : Disposable { private var wasGradientPainted = false private var ourSettingsValue = UISettings.getInstance().differentiateProjects private val colorCache = mutableMapOf() - private val iconCache = mutableMapOf() private val listeners = mutableListOf<(Boolean) -> Unit>() private val colors: Array @@ -50,26 +88,7 @@ class ProjectWindowCustomizerService : Disposable { ) fun getProjectIcon(project: Project): Icon { - val path = getProjectPath(project) - return iconCache.getOrPut(path) { - Disposer.register(project) { - iconCache.remove(path) - } - RecentProjectsManagerBase.getInstanceEx().getProjectIcon(path, true) - } - } - - private fun getProjectPath(project: Project): String { - val recentProjectManager = RecentProjectsManagerBase.getInstanceEx() - return recentProjectManager.getProjectPath(project) ?: project.basePath ?: run { - thisLogger().warn("Impossible: no path for project $project") - "" - } - } - - private fun getProjectNameForIcon(project: Project): String { - val path = getProjectPath(project) - return RecentProjectIconHelper.getProjectName(path) + return project.service().cachedIcon } internal fun update(newValue: Boolean) { @@ -125,11 +144,15 @@ class ProjectWindowCustomizerService : Disposable { } fun showGotIt(project: Project, component: JComponent) { + if (!shouldShowGotIt() || !isActive()) return + val gotIt = GotItTooltip("colorful.instances", IdeBundle.message("colorfulInstances.gotIt.text"), this).apply { withHeader(IdeBundle.message("colorfulInstances.gotIt.title")) // withTimeout(5000) TODO: to discuss with designers: do we want autohide or do we want a button? } + gotIt.showCondition = { true } + if (WindowManagerEx.getInstanceEx().getFrameHelper(project)?.frame?.isFocused == true) { gotIt.show(component, GotItTooltip.BOTTOM_MIDDLE) recordGotItShown() diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/ProjectToolbarWidgetAction.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/ProjectToolbarWidgetAction.kt index da1f1a708855..2b45c4fd1416 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/ProjectToolbarWidgetAction.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/headertoolbar/ProjectToolbarWidgetAction.kt @@ -70,9 +70,7 @@ class ProjectToolbarWidgetAction : ExpandableComboAction() { val project = presentation.getClientProperty(projectKey) if (project != null) { widget.leftIcons = listOf(customizer.getProjectIcon(project)) - if (customizer.shouldShowGotIt()) { - customizer.showGotIt(project, widget) - } + customizer.showGotIt(project, widget) } } else { diff --git a/platform/util/ui/src/com/intellij/util/ui/AvatarUtils.kt b/platform/util/ui/src/com/intellij/util/ui/AvatarUtils.kt index bc7ca2121712..e4a68c9b9383 100644 --- a/platform/util/ui/src/com/intellij/util/ui/AvatarUtils.kt +++ b/platform/util/ui/src/com/intellij/util/ui/AvatarUtils.kt @@ -2,16 +2,17 @@ package com.intellij.util.ui import com.intellij.openapi.util.registry.Registry -import com.intellij.ui.JBColor import com.intellij.ui.paint.withTxAndClipAligned import com.intellij.util.ui.AvatarUtils.generateColoredAvatar import com.intellij.util.ui.ImageUtil.applyQualityRenderingHints import java.awt.* +import java.awt.font.TextAttribute import java.awt.geom.Area import java.awt.geom.RoundRectangle2D import java.awt.image.BufferedImage import kotlin.math.abs + class AvatarIcon(private val targetSize: Int, private val arcRatio: Double, private val gradientSeed: String, @@ -98,13 +99,22 @@ object AvatarUtils { private fun getFont(size: Int): Font { return if (Registry.`is`("ide.experimental.ui")) { - val fontSize = 13 * size / 20 // Desired font is 13 with default icon size 20 - JBFont.create(Font("JetBrains Mono", Font.BOLD, fontSize)) + val fontSize = 13 * size / 20 + getNewUiFont(fontSize) } else { JBFont.create(Font("Segoe UI", Font.PLAIN, (size / 2.2).toInt())) } } + + private fun getNewUiFont(size: Int): Font { + val attributes = mutableMapOf() + + attributes[TextAttribute.FAMILY] = "JetBrains Mono" + attributes[TextAttribute.WEIGHT] = TextAttribute.WEIGHT_DEMIBOLD + + return JBFont.create(Font.getFont(attributes)).deriveFont(size.toFloat()) + } } internal object Avatars {