mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
PY-82344 Implement Welcome to unified PyCharm! promo welcome screen banner, refactoring
(cherry picked from commit b80df8b40facfbf114d0d8965756768cb799f198) IJ-CR-179688 GitOrigin-RevId: 06d66ae94cfc38b07ba27e8ea71e7f52d072e19d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d82a65e259
commit
ee44190f3c
-103
@@ -1,103 +0,0 @@
|
||||
<svg width="360" height="128" viewBox="0 0 360 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M84.4762 70.0674L268.763 -187.318C293.214 -221.468 340.85 -231.027 375.159 -208.669L633.748 -40.1578C668.058 -17.7996 676.049 28.0093 651.598 62.1593L467.311 319.544C442.86 353.694 395.225 363.254 360.915 340.895L102.326 172.384C68.0167 150.026 60.0249 104.217 84.4762 70.0674Z"
|
||||
fill="url(#paint0_linear_232_30135)"/>
|
||||
<path
|
||||
d="M138 128.822L248.148 -99.1917C262.763 -129.445 299.476 -143.451 330.148 -130.477L561.327 -32.6895C592 -19.715 605.018 15.3277 590.403 45.5806L480.255 273.594C465.64 303.847 428.928 317.854 398.255 304.879L167.076 207.092C136.403 194.117 123.386 159.075 138 128.822Z"
|
||||
fill="url(#paint1_linear_232_30135)"/>
|
||||
<path
|
||||
d="M189.304 167.896L244.41 -26.8865C251.721 -52.7302 279.055 -68.7618 305.462 -62.6941L504.49 -16.9618C530.897 -10.8941 546.377 14.9753 539.065 40.819L483.959 235.602C476.648 261.446 449.314 277.477 422.907 271.409L223.879 225.677C197.472 219.609 181.993 193.74 189.304 167.896Z"
|
||||
fill="url(#paint2_linear_232_30135)"/>
|
||||
<path
|
||||
d="M235.986 191.748L251.88 30.648C253.989 9.27306 273.53 -7.08205 295.526 -5.88217L461.31 3.16118C483.307 4.36106 499.429 22.6616 497.32 44.0365L481.427 205.137C479.318 226.512 459.777 242.867 437.78 241.667L271.996 232.624C250 231.424 233.878 213.123 235.986 191.748Z"
|
||||
fill="url(#paint3_linear_232_30135)"/>
|
||||
<path
|
||||
d="M276.768 204.22L266.175 75.0081C264.769 57.8642 278.031 42.3122 295.796 40.2718L429.687 24.8938C447.452 22.8534 462.992 35.0973 464.398 52.2413L474.991 181.453C476.397 198.597 463.135 214.149 445.37 216.189L311.479 231.567C293.715 233.608 278.174 221.364 276.768 204.22Z"
|
||||
fill="url(#paint4_linear_232_30135)"/>
|
||||
<path
|
||||
d="M311.188 208.518L284.025 108.052C280.421 94.7222 288.777 80.656 302.689 76.6347L407.541 46.3269C421.454 42.3056 435.653 49.8519 439.257 63.1821L466.421 163.648C470.025 176.978 461.668 191.044 447.756 195.066L342.904 225.374C328.992 229.395 314.792 221.849 311.188 208.518Z"
|
||||
fill="url(#paint5_linear_232_30135)"/>
|
||||
<path
|
||||
d="M339.336 207.234L303.079 131.687C298.269 121.664 302.917 109.436 313.461 104.376L392.932 66.2357C403.476 61.1754 415.923 65.1987 420.733 75.2221L456.99 150.769C461.801 160.792 457.153 173.02 446.609 178.081L367.138 216.221C356.594 221.281 344.147 217.258 339.336 207.234Z"
|
||||
fill="url(#paint6_linear_232_30135)"/>
|
||||
<path
|
||||
d="M361.661 202.399L321.737 147.741C316.44 140.489 318.388 130.215 326.088 124.792L384.126 83.9218C391.827 78.4991 402.363 79.9821 407.661 87.2341L447.585 141.892C452.882 149.144 450.933 159.419 443.233 164.842L385.195 205.712C377.494 211.134 366.958 209.651 361.661 202.399Z"
|
||||
fill="url(#paint7_linear_232_30135)"/>
|
||||
<path
|
||||
d="M378.816 195.559L338.981 157.874C333.696 152.873 333.768 144.505 339.142 139.183L379.644 99.0696C385.018 93.7472 393.66 93.4861 398.945 98.4865L438.78 136.172C444.066 141.172 443.994 149.541 438.62 154.863L398.117 194.976C392.743 200.298 384.102 200.56 378.816 195.559Z"
|
||||
fill="url(#paint8_linear_232_30135)"/>
|
||||
<path
|
||||
d="M391.546 187.833L354.237 163.52C349.286 160.294 348.133 153.685 351.661 148.758L378.25 111.622C381.778 106.695 388.651 105.316 393.601 108.542L430.91 132.854C435.86 136.08 437.013 142.69 433.486 147.617L406.897 184.752C403.369 189.68 396.496 191.059 391.546 187.833Z"
|
||||
fill="url(#paint9_linear_232_30135)"/>
|
||||
<path
|
||||
d="M400.607 180.009L367.253 165.9C362.828 164.028 360.95 158.972 363.058 154.608L378.95 121.71C381.059 117.345 386.356 115.324 390.781 117.196L424.135 131.305C428.561 133.177 430.439 138.233 428.33 142.598L412.438 175.495C410.33 179.86 405.033 181.881 400.607 180.009Z"
|
||||
fill="url(#paint10_linear_232_30135)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_232_30135" x1="502.466" y1="-121.657" x2="250.469" y2="265.044" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_232_30135" x1="444.547" y1="-79.1399" x2="300.748" y2="260.813" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_232_30135" x1="404.377" y1="-37.7393" x2="338.298" y2="249.837" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_232_30135" x1="378.241" y1="0.368083" x2="365.385" y2="236.054" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_232_30135" x1="362.85" y1="33.9701" x2="384.429" y2="221.849" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_232_30135" x1="355.403" y1="62.5602" x2="397.575" y2="208.458" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_232_30135" x1="353.582" y1="86.118" x2="406.498" y2="196.376" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_232_30135" x1="355.534" y1="104.945" x2="412.402" y2="185.702" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_232_30135" x1="359.819" y1="119.532" x2="416.107" y2="176.367" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_232_30135" x1="365.355" y1="130.452" x2="418.148" y2="168.252" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_232_30135" x1="371.362" y1="138.312" x2="418.895" y2="161.274" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.0 KiB |
+3
@@ -9,6 +9,7 @@ import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization
|
||||
import com.intellij.openapi.updateSettings.impl.*
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.pycharm.community.ide.impl.promo.WelcomeToUnifiedWelcomeScreenBanner
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@@ -48,6 +49,8 @@ internal class PyCommunityToUnifiedPromoService(val serviceScope: CoroutineScope
|
||||
val propertiesComponent = PropertiesComponent.getInstance()
|
||||
propertiesComponent.unsetValue(PROMO_UPDATE_DECLINED)
|
||||
propertiesComponent.unsetValue(PROMO_REMIND_ME_LATER_LAST_TIME_CLICKED)
|
||||
propertiesComponent.unsetValue(WelcomeToUnifiedWelcomeScreenBanner.BANNER_CLOSED_PROPERTY)
|
||||
|
||||
Registry.get(REG_PROMO_INTERVAL_SECONDS).resetToDefault()
|
||||
}
|
||||
|
||||
|
||||
+9
-58
@@ -4,18 +4,16 @@ package com.intellij.pycharm.community.ide.impl.promotion.communityToUnified
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.wm.BannerStartPagePromoter
|
||||
import com.intellij.openapi.wm.StartPagePromoter
|
||||
import com.intellij.pycharm.community.ide.impl.icons.PycharmCommunityIdeImplIcons
|
||||
import com.intellij.pycharm.community.ide.impl.promo.PyCommunityToUnifiedWelcomeScreenBannerBase
|
||||
import com.intellij.pycharm.community.ide.impl.promotion.communityToUnified.statistics.PyCommunityUnifiedPromoFusCollector
|
||||
import com.intellij.pycharm.community.ide.impl.promotion.icons.PycharmCommunityIdeImplPromotionIcons
|
||||
import com.intellij.ui.components.panels.BackgroundRoundedPanel
|
||||
import com.intellij.ui.components.panels.Wrapper
|
||||
import com.intellij.ui.dsl.builder.EmptySpacingConfiguration
|
||||
import com.intellij.ui.dsl.builder.TopGap
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
import com.intellij.ui.dsl.gridLayout.UnscaledGaps
|
||||
import com.intellij.ui.dsl.gridLayout.UnscaledGapsY
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.ui.JBFont
|
||||
import com.intellij.util.ui.JBUI
|
||||
@@ -24,21 +22,16 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.awt.Graphics
|
||||
import java.awt.Graphics2D
|
||||
import java.awt.geom.RoundRectangle2D
|
||||
import javax.swing.BoxLayout
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
import kotlin.math.min
|
||||
|
||||
@ApiStatus.Internal
|
||||
internal class PyCommunityToUnifiedWelcomeScreenBanner : BannerStartPagePromoter() {
|
||||
internal class PyCommunityToUnifiedWelcomeScreenBanner : PyCommunityToUnifiedWelcomeScreenBannerBase() {
|
||||
override val headerLabel: @Nls String = ""
|
||||
override val actionLabel: @Nls String = ""
|
||||
override val description: @Nls String = ""
|
||||
override val promoImage: Icon = PycharmCommunityIdeImplPromotionIcons.Backgrounds.Promotion_bg
|
||||
override val promoImage: Icon = PycharmCommunityIdeImplIcons.Backgrounds.Promotion_bg
|
||||
|
||||
private val mainBannerPanel = createMainPanel()
|
||||
|
||||
@@ -58,19 +51,19 @@ internal class PyCommunityToUnifiedWelcomeScreenBanner : BannerStartPagePromoter
|
||||
}
|
||||
}
|
||||
}
|
||||
return container
|
||||
return wrapIntoSvgBackgroundPanel(container)
|
||||
}
|
||||
|
||||
override fun runAction() {}
|
||||
|
||||
override fun canCreatePromo(isEmptyState: Boolean): Boolean {
|
||||
return PlatformUtils.isPyCharmCommunity()
|
||||
}
|
||||
|
||||
override fun getMainPanel(): JPanel = container
|
||||
|
||||
override fun getPriorityLevel(): Int = StartPagePromoter.PRIORITY_LEVEL_HIGH
|
||||
|
||||
private fun createMainPanel(): JPanel {
|
||||
val panel = panel {
|
||||
private fun createMainPanel(): JPanel =
|
||||
panel {
|
||||
customizeSpacingConfiguration(EmptySpacingConfiguration()) {
|
||||
row {
|
||||
label(PyPromoSharedComponents.headerTitle)
|
||||
@@ -101,46 +94,4 @@ internal class PyCommunityToUnifiedWelcomeScreenBanner : BannerStartPagePromoter
|
||||
isOpaque = false
|
||||
border = JBUI.Borders.empty(0, 12, 16, 0)
|
||||
}
|
||||
return wrapIntoSvgBackgroundPanel(panel, JBUI.scale(16), promoImage)
|
||||
}
|
||||
|
||||
private fun wrapIntoSvgBackgroundPanel(panel: JPanel, arc: Int, bgImage: Icon): JPanel {
|
||||
val svgPanel = SvgBackgroundRightAnchoredPanel(arc, bgImage).apply {
|
||||
layout = BoxLayout(this, BoxLayout.X_AXIS)
|
||||
}
|
||||
svgPanel.add(panel)
|
||||
return svgPanel
|
||||
}
|
||||
|
||||
private class SvgBackgroundRightAnchoredPanel(
|
||||
private val arc: Int,
|
||||
private val bgImage: Icon,
|
||||
) : BackgroundRoundedPanel(arc) {
|
||||
|
||||
override fun paintComponent(g: Graphics) {
|
||||
super.paintComponent(g)
|
||||
if (width <= 0 || height <= 0) return
|
||||
|
||||
val iw = bgImage.iconWidth
|
||||
val ih = bgImage.iconHeight
|
||||
if (iw <= 0 || ih <= 0) return
|
||||
|
||||
val g2 = g.create() as Graphics2D
|
||||
try {
|
||||
g2.clip(RoundRectangle2D.Float(0f, 0f, width.toFloat(), height.toFloat(), arc.toFloat(), arc.toFloat()))
|
||||
val sx = width.toFloat() / iw
|
||||
val sy = height.toFloat() / ih
|
||||
val scale = min(sx, sy)
|
||||
|
||||
val scaled = IconUtil.scale(bgImage, this, scale)
|
||||
// Right-anchored (no padding)
|
||||
val x = width - scaled.iconWidth
|
||||
val y = 0
|
||||
scaled.paintIcon(this, g2, x, y)
|
||||
}
|
||||
finally {
|
||||
g2.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import java.awt.Color
|
||||
|
||||
internal object PyPromoSharedComponents {
|
||||
|
||||
val popUpImg = PycharmCommunityIdeImplPromotionIcons.Images.Popup_img
|
||||
val popUpImg = PycharmCommunityIdeImplPromotionIcons.Popup_img
|
||||
val infoFontColor = JBColor(Color.decode("#6C707E"), Color.decode("#A8ADBD"))
|
||||
|
||||
// URLs used by promo-related messages
|
||||
|
||||
+1
-8
@@ -15,12 +15,5 @@ public final class PycharmCommunityIdeImplPromotionIcons {
|
||||
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, PycharmCommunityIdeImplPromotionIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
|
||||
public static final class Backgrounds {
|
||||
/** 360x128 */ public static final @NotNull Icon Promotion_bg = load("promo/backgrounds/promotion_bg.svg", -882473096, 0);
|
||||
}
|
||||
|
||||
public static final class Images {
|
||||
/** 384x242 */ public static final @NotNull Icon Popup_img = load("promo/images/popup_img.svg", 986597622, 0);
|
||||
}
|
||||
/** 384x242 */ public static final @NotNull Icon Popup_img = load("promo/images/popup_img.svg", 986597622, 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<svg width="770" height="128" viewBox="0 0 770 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_664_32769)">
|
||||
<g clip-path="url(#clip1_664_32769)">
|
||||
<path
|
||||
d="M494.476 70.0674L678.763 -187.318C703.214 -221.468 750.85 -231.027 785.159 -208.669L1043.75 -40.1578C1078.06 -17.7996 1086.05 28.0092 1061.6 62.1592L877.311 319.544C852.86 353.694 805.225 363.253 770.915 340.895L512.326 172.384C478.017 150.026 470.025 104.217 494.476 70.0674Z"
|
||||
fill="url(#paint0_linear_664_32769)"/>
|
||||
<path
|
||||
d="M548 128.822L658.148 -99.1917C672.763 -129.445 709.476 -143.452 740.148 -130.477L971.327 -32.6895C1002 -19.715 1015.02 15.3277 1000.4 45.5806L890.255 273.594C875.64 303.847 838.928 317.854 808.255 304.879L577.076 207.092C546.403 194.117 533.386 159.075 548 128.822Z"
|
||||
fill="url(#paint1_linear_664_32769)"/>
|
||||
<path
|
||||
d="M599.304 167.896L654.41 -26.8865C661.721 -52.7302 689.055 -68.7618 715.462 -62.6941L914.49 -16.9618C940.897 -10.8941 956.377 14.9753 949.065 40.819L893.959 235.602C886.648 261.446 859.314 277.477 832.907 271.409L633.879 225.677C607.472 219.609 591.993 193.74 599.304 167.896Z"
|
||||
fill="url(#paint2_linear_664_32769)"/>
|
||||
<path
|
||||
d="M645.986 191.748L661.88 30.648C663.989 9.27305 683.53 -7.08207 705.526 -5.88219L871.31 3.16116C893.307 4.36104 909.429 22.6615 907.32 44.0365L891.427 205.137C889.318 226.512 869.777 242.867 847.78 241.667L681.996 232.624C660 231.424 643.878 213.123 645.986 191.748Z"
|
||||
fill="url(#paint3_linear_664_32769)"/>
|
||||
<path
|
||||
d="M686.768 204.22L676.175 75.0081C674.769 57.8642 688.031 42.3122 705.796 40.2718L839.687 24.8938C857.452 22.8534 872.992 35.0973 874.398 52.2412L884.991 181.453C886.397 198.597 873.135 214.149 855.37 216.189L721.479 231.567C703.715 233.608 688.174 221.364 686.768 204.22Z"
|
||||
fill="url(#paint4_linear_664_32769)"/>
|
||||
<path
|
||||
d="M721.188 208.518L694.025 108.052C690.421 94.7222 698.777 80.656 712.689 76.6347L817.541 46.3269C831.454 42.3056 845.653 49.8519 849.257 63.1821L876.421 163.648C880.025 176.978 871.668 191.044 857.756 195.066L752.904 225.374C738.992 229.395 724.792 221.849 721.188 208.518Z"
|
||||
fill="url(#paint5_linear_664_32769)"/>
|
||||
<path
|
||||
d="M749.336 207.234L713.079 131.687C708.269 121.664 712.917 109.436 723.461 104.376L802.932 66.2357C813.476 61.1753 825.923 65.1987 830.733 75.2221L866.99 150.769C871.801 160.792 867.153 173.02 856.609 178.081L777.138 216.221C766.594 221.281 754.147 217.258 749.336 207.234Z"
|
||||
fill="url(#paint6_linear_664_32769)"/>
|
||||
<path
|
||||
d="M771.661 202.399L731.737 147.741C726.44 140.489 728.388 130.215 736.088 124.792L794.126 83.9217C801.827 78.4991 812.363 79.9821 817.661 87.2341L857.585 141.892C862.882 149.144 860.933 159.419 853.233 164.841L795.195 205.712C787.494 211.134 776.958 209.651 771.661 202.399Z"
|
||||
fill="url(#paint7_linear_664_32769)"/>
|
||||
<path
|
||||
d="M788.816 195.559L748.981 157.874C743.696 152.873 743.768 144.505 749.142 139.183L789.644 99.0696C795.018 93.7472 803.66 93.4861 808.945 98.4865L848.78 136.172C854.066 141.172 853.994 149.541 848.62 154.863L808.117 194.976C802.743 200.298 794.102 200.56 788.816 195.559Z"
|
||||
fill="url(#paint8_linear_664_32769)"/>
|
||||
<path
|
||||
d="M801.546 187.833L764.237 163.52C759.286 160.294 758.133 153.685 761.661 148.758L788.25 111.622C791.778 106.695 798.651 105.316 803.601 108.542L840.91 132.854C845.86 136.08 847.013 142.69 843.486 147.617L816.897 184.752C813.369 189.68 806.496 191.059 801.546 187.833Z"
|
||||
fill="url(#paint9_linear_664_32769)"/>
|
||||
<path
|
||||
d="M810.607 180.009L777.253 165.9C772.828 164.028 770.95 158.972 773.058 154.608L788.95 121.71C791.059 117.345 796.356 115.324 800.781 117.196L834.135 131.305C838.561 133.177 840.439 138.233 838.33 142.598L822.438 175.495C820.33 179.86 815.033 181.881 810.607 180.009Z"
|
||||
fill="url(#paint10_linear_664_32769)"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_664_32769" x1="912.466" y1="-121.657" x2="660.469" y2="265.044" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_664_32769" x1="854.547" y1="-79.1399" x2="710.748" y2="260.813" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_664_32769" x1="814.377" y1="-37.7393" x2="748.298" y2="249.837" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_664_32769" x1="788.241" y1="0.368068" x2="775.385" y2="236.054" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_664_32769" x1="772.85" y1="33.9701" x2="794.429" y2="221.849" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_664_32769" x1="765.403" y1="62.5602" x2="807.575" y2="208.458" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_664_32769" x1="763.582" y1="86.118" x2="816.498" y2="196.376" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_664_32769" x1="765.534" y1="104.945" x2="822.402" y2="185.702" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_664_32769" x1="769.819" y1="119.532" x2="826.107" y2="176.367" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_664_32769" x1="775.355" y1="130.452" x2="828.148" y2="168.252" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_664_32769" x1="781.362" y1="138.312" x2="828.895" y2="161.274" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F0EB18" stop-opacity="0.9"/>
|
||||
<stop offset="0.3" stop-color="#00D886" stop-opacity="0.5"/>
|
||||
<stop offset="0.59" stop-color="#00C4F4" stop-opacity="0.3"/>
|
||||
<stop offset="1" stop-color="#00C4F4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_664_32769">
|
||||
<rect width="770" height="128" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_664_32769">
|
||||
<rect width="360" height="217" fill="white" transform="matrix(1 -8.74228e-08 -8.74228e-08 -1 410 196)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.5 12.5L12.5 3.5M12.5 12.5L3.5 3.5" stroke="#6C707E" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 321 B |
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.5 12.5L12.5 3.5M12.5 12.5L3.5 3.5" stroke="#FFFFFF" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 321 B |
@@ -139,6 +139,8 @@
|
||||
|
||||
<codeInsight.codeVision.settings.defaults implementation="com.intellij.pycharm.community.ide.impl.PyCharmCodeVisionSettingsDefaults"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.pycharm.community.ide.impl.configuration.ui.PyAddNewEnvCollector"/>
|
||||
<startPagePromoter
|
||||
implementation="com.intellij.pycharm.community.ide.impl.promo.WelcomeToUnifiedWelcomeScreenBanner"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="Pythonid">
|
||||
@@ -163,6 +165,8 @@
|
||||
<applicationListeners>
|
||||
<listener class="com.intellij.pycharm.community.ide.impl.welcomeScreen.PyWelcomeScreenNewUsersTracker"
|
||||
topic="com.intellij.ide.AppLifecycleListener"/>
|
||||
<listener class="com.intellij.pycharm.community.ide.impl.promo.CommunityToUnifiedListener"
|
||||
topic="com.intellij.ide.AppLifecycleListener"/>
|
||||
</applicationListeners>
|
||||
|
||||
<actions resource-bundle="messages.ActionsBundle">
|
||||
|
||||
@@ -77,11 +77,14 @@ promotion.update.to.unified.banner.header.title=Update to the unified PyCharm
|
||||
promotion.update.to.unified.info.text=Starting with version 2025.3, all updates will be released exclusively for the unified PyCharm.<br>Update the IDE to keep receiving new features \u2013 all core functionalities will remain free.
|
||||
promotion.update.to.unified.update.now.button.label=Update Now
|
||||
promotion.update.to.unified.learn.more.hyper.link=Learn More
|
||||
promotion.update.to.unified.closed.banner.go.to.settings.info=You can find and install the new update in the Settings section
|
||||
promotion.update.to.unified.skip.button.label=Skip
|
||||
action.ShowPyCommunityToUnifiedTooltipAction.text=Community To Unified Tooltip
|
||||
action.ShowPyCommunityToUnifiedTooltipAction.description=For testing purposes
|
||||
action.ShowPyCommunityToUnifiedPromoDialogAction.text=Community To Unified Modal Promo
|
||||
action.ShowPyCommunityToUnifiedPromoDialogAction.description=For testing purposes
|
||||
action.ResetCommunityToUnifiedPromoStateAction.text=Reset Community To Unified Promo State
|
||||
action.ResetCommunityToUnifiedPromoStateAction.description=For testing purposes
|
||||
action.ResetCommunityToUnifiedPromoStateAction.description=For testing purposes
|
||||
promotion.welcome.to.unified.main.text=Everything is in one place! Switch between core and advanced<br>features within the same installation.
|
||||
promotion.welcome.to.unified.title=Welcome to unified PyCharm!
|
||||
promotion.welcome.to.unified.close=Close
|
||||
promotion.welcome.to.unified.close.banner=Close banner
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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.pycharm.community.ide.impl.icons;
|
||||
|
||||
import com.intellij.ui.IconManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* NOTE THIS FILE IS AUTO-GENERATED
|
||||
* DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
|
||||
*/
|
||||
@org.jetbrains.annotations.ApiStatus.Internal
|
||||
public final class PycharmCommunityIdeImplIcons {
|
||||
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, PycharmCommunityIdeImplIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
|
||||
public static final class Backgrounds {
|
||||
/** 770x128 */ public static final @NotNull Icon Promotion_bg = load("backgrounds/promotion_bg.svg", -1173415960, 0);
|
||||
}
|
||||
|
||||
public static final class Icons {
|
||||
/** 16x16 */ public static final @NotNull Icon Close = load("icons/close.svg", -540869824, 2);
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
// 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.pycharm.community.ide.impl.promo
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.observable.util.whenDisposed
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.BannerStartPagePromoter
|
||||
import com.intellij.openapi.wm.impl.IdeBackgroundUtil
|
||||
import com.intellij.util.SVGLoader
|
||||
import com.intellij.util.ui.GraphicsUtil
|
||||
import com.intellij.util.ui.JBInsets
|
||||
import com.intellij.util.ui.JBSwingUtilities
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.awt.*
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class PyCommunityToUnifiedWelcomeScreenBannerBase : BannerStartPagePromoter() {
|
||||
override val headerLabel: @Nls String = ""
|
||||
override val actionLabel: @Nls String = ""
|
||||
override val description: @Nls String = ""
|
||||
|
||||
abstract fun getMainPanel(): JPanel
|
||||
|
||||
override fun getPromotion(isEmptyState: Boolean): JComponent {
|
||||
val mainPanel = getMainPanel()
|
||||
return wrapIntoSvgBackgroundPanel(mainPanel)
|
||||
}
|
||||
|
||||
override fun runAction() {}
|
||||
|
||||
fun wrapIntoSvgBackgroundPanel(panel: JPanel): JPanel {
|
||||
val disposable = Disposer.newDisposable("BackgroundPanel")
|
||||
val url = WelcomeToUnifiedWelcomeScreenBanner::class.java.getResource("/backgrounds/promotion_bg.svg") ?: return panel
|
||||
val backgroundImage = SVGLoader.load(url, 1f)
|
||||
val backgroundPanel = BackgroundPanel(BorderLayout(), backgroundImage, disposable)
|
||||
backgroundPanel.add(panel, BorderLayout.CENTER)
|
||||
backgroundPanel.isOpaque = false
|
||||
return backgroundPanel
|
||||
}
|
||||
|
||||
private class BackgroundPanel(layout: LayoutManager, private val image: Image, parentDisposable: Disposable) : JPanel(layout) {
|
||||
|
||||
private var disposable: Disposable? = null
|
||||
|
||||
init {
|
||||
parentDisposable.whenDisposed { clearResources() }
|
||||
installBackground()
|
||||
}
|
||||
|
||||
override fun paintComponent(g: Graphics) {
|
||||
super.paintComponent(g)
|
||||
val g2 = g.create() as Graphics2D
|
||||
try {
|
||||
GraphicsUtil.setupAAPainting(g2)
|
||||
g2.color = background
|
||||
g2.fillRoundRect(0, 0, width, height, 16, 16)
|
||||
}
|
||||
finally {
|
||||
g2.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getComponentGraphics(g: Graphics?): Graphics? {
|
||||
return JBSwingUtilities.runGlobalCGTransform(this, super.getComponentGraphics(g))
|
||||
}
|
||||
|
||||
override fun updateUI() {
|
||||
super.updateUI()
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
if (image != null) {
|
||||
installBackground()
|
||||
}
|
||||
}
|
||||
|
||||
private fun installBackground() {
|
||||
clearResources()
|
||||
disposable = Disposer.newDisposable("BackgroundPanel")
|
||||
IdeBackgroundUtil.createTemporaryBackgroundTransform(this, image,
|
||||
IdeBackgroundUtil.Fill.SCALE,
|
||||
IdeBackgroundUtil.Anchor.MIDDLE_RIGHT,
|
||||
1f, JBInsets.emptyInsets(),
|
||||
disposable)
|
||||
}
|
||||
|
||||
private fun clearResources() {
|
||||
disposable?.let { Disposer.dispose(it) }
|
||||
disposable = null
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
// 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.pycharm.community.ide.impl.promo
|
||||
|
||||
|
||||
import com.intellij.ide.AppLifecycleListener
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBundle
|
||||
import com.intellij.pycharm.community.ide.impl.icons.PycharmCommunityIdeImplIcons
|
||||
import com.intellij.ui.JBColor
|
||||
import com.intellij.ui.components.panels.Wrapper
|
||||
import com.intellij.ui.dsl.builder.*
|
||||
import com.intellij.ui.dsl.gridLayout.UnscaledGaps
|
||||
import com.intellij.ui.dsl.gridLayout.UnscaledGapsY
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.ui.JBFont
|
||||
import com.intellij.util.ui.JBUI
|
||||
import java.awt.Color
|
||||
import java.awt.Dimension
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JPanel
|
||||
|
||||
private const val PREV_BUILD_WAS_PC_PROP = "pycharm.previous.version.was.community"
|
||||
|
||||
class WelcomeToUnifiedWelcomeScreenBanner : PyCommunityToUnifiedWelcomeScreenBannerBase() {
|
||||
|
||||
companion object {
|
||||
const val BANNER_CLOSED_PROPERTY: String = "WELCOME_TO_UNIFIED_BANNER_CLOSED"
|
||||
}
|
||||
|
||||
private fun isBannerClosed(): Boolean = PropertiesComponent.getInstance().getBoolean(BANNER_CLOSED_PROPERTY)
|
||||
private fun onBannerClosed() = PropertiesComponent.getInstance().setValue(BANNER_CLOSED_PROPERTY, true)
|
||||
|
||||
override val promoImage: Icon = PycharmCommunityIdeImplIcons.Backgrounds.Promotion_bg
|
||||
|
||||
private val infoFontColor = JBColor(Color.decode("#6C707E"), Color.decode("#A8ADBD"))
|
||||
private val closeIcon = IconUtil.scale(PycharmCommunityIdeImplIcons.Icons.Close, null, 1.1f)
|
||||
|
||||
private val myCloseAction =
|
||||
object : DumbAwareAction(PyCharmCommunityCustomizationBundle.message("promotion.welcome.to.unified.close"),
|
||||
PyCharmCommunityCustomizationBundle.message("promotion.welcome.to.unified.close.banner"),
|
||||
closeIcon) {
|
||||
override fun getActionUpdateThread() = ActionUpdateThread.EDT
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
onBannerClosed()
|
||||
container.isVisible = false
|
||||
container.repaint()
|
||||
}
|
||||
}
|
||||
|
||||
val container: Wrapper = Wrapper(createMainPanel())
|
||||
|
||||
override fun canCreatePromo(isEmptyState: Boolean): Boolean {
|
||||
val isUnified = ApplicationInfo.getInstance().build.productCode.equals("PY", ignoreCase = true)
|
||||
return isUnified && !isBannerClosed() && isUpgradeFromCommunityToUnified()
|
||||
}
|
||||
|
||||
private fun createMainPanel(): JPanel {
|
||||
val panel = panel {
|
||||
customizeSpacingConfiguration(EmptySpacingConfiguration()) {
|
||||
row {
|
||||
label(PyCharmCommunityCustomizationBundle.message("promotion.welcome.to.unified.title"))
|
||||
.applyToComponent {
|
||||
font = JBFont.h3().asBold()
|
||||
}
|
||||
actionButton(myCloseAction)
|
||||
.applyToComponent {
|
||||
setMinimumButtonSize { Dimension(closeIcon.iconWidth, closeIcon.iconHeight) }
|
||||
}
|
||||
.align(AlignX.RIGHT)
|
||||
.align(AlignY.TOP)
|
||||
.customize(UnscaledGaps(right = 8))
|
||||
}.customize(customRowGaps = UnscaledGapsY(top = 12))
|
||||
row {
|
||||
text(PyCharmCommunityCustomizationBundle.message("promotion.welcome.to.unified.main.text"))
|
||||
.applyToComponent {
|
||||
foreground = infoFontColor
|
||||
}
|
||||
}.customize(customRowGaps = UnscaledGapsY(top = 4, bottom = 8))
|
||||
}
|
||||
row {
|
||||
browserLink(PyCharmCommunityCustomizationBundle.message("promotion.update.to.unified.learn.more.hyper.link"),
|
||||
"https://blog.jetbrains.com/pycharm/2025/04/unified-pycharm/")
|
||||
}.topGap(TopGap.NONE)
|
||||
}.apply {
|
||||
isOpaque = false
|
||||
border = JBUI.Borders.empty(0, 12, 16, 0)
|
||||
}
|
||||
return panel
|
||||
}
|
||||
|
||||
override fun getMainPanel(): JPanel = container
|
||||
|
||||
private fun isUpgradeFromCommunityToUnified(): Boolean {
|
||||
val currentCode = ApplicationInfo.getInstance().build.productCode
|
||||
|
||||
val prevWasCommunity = PropertiesComponent.getInstance().getBoolean(PREV_BUILD_WAS_PC_PROP, false)
|
||||
return prevWasCommunity && currentCode.equals("PY", ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
class CommunityToUnifiedListener : AppLifecycleListener {
|
||||
override fun appStarted() {
|
||||
if (PlatformUtils.isPyCharmCommunity()) {
|
||||
PropertiesComponent.getInstance().setValue(PREV_BUILD_WAS_PC_PROP, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user