RIDER-102481 install plugins page

GitOrigin-RevId: 3252a49109ae0203b6224629da77fcbdf535bf45
This commit is contained in:
anna.gromova
2024-01-18 13:53:31 +00:00
committed by intellij-monorepo-bot
parent 8c61cc136d
commit 1c03fffa1e
30 changed files with 366 additions and 256 deletions
@@ -109,12 +109,13 @@ enum class StartupWizardStage {
ImportProgressPage,
WizardThemePage,
WizardKeymapPage,
WizardPluginPage
WizardPluginPage,
WizardProgressPage
}
object IdeStartupWizardCollector : CounterUsagesCollector() {
val GROUP = EventLogGroup("wizard.startup", 5)
val GROUP = EventLogGroup("wizard.startup", 6)
override fun getGroup() = GROUP
private val initialStartSucceeded = GROUP.registerEvent("initial_start_succeeded")
@@ -50,5 +50,6 @@
<orderEntry type="library" name="jna" level="project" />
<orderEntry type="library" name="sqlite" level="project" />
<orderEntry type="library" name="classgraph" level="project" />
<orderEntry type="module" module-name="intellij.platform.util.ui" />
</component>
</module>
@@ -81,9 +81,12 @@ wizard.button.continue = Continue
plugins.page.title = Featured Plugins
plugins.page.ok.button.continue.without = Continue without Plugins
plugins.page.ok.button.continue.installation = Continue installation
plugins.page.ok.button.install = Install Plugins
plugins.page.ok.button.finish = Finish
plugins.page.ok.button.install = Install Selected
plugins.page.choose.counter.no = No plugins selected for installation
plugins.page.choose.counter.one = 1 plugin selected for installation
plugins.page.choose.counter.multiple = {0} plugins selected for installation
install.plugins.page.title = Installing Plugins\u2026
Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

@@ -6,18 +6,16 @@ import com.intellij.icons.AllIcons
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
import com.intellij.ide.startup.importSettings.chooser.ui.ImportSettingsController
import com.intellij.ide.startup.importSettings.chooser.ui.OnboardingPage
import com.intellij.ide.startup.importSettings.chooser.ui.ProgressCommentLabel
import com.intellij.ide.startup.importSettings.chooser.ui.ProgressLabel
import com.intellij.ide.startup.importSettings.data.DialogImportData
import com.intellij.ide.startup.importSettings.data.ImportFromProduct
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.ui.MessageDialogBuilder
import com.intellij.openapi.util.NlsContexts
import com.intellij.platform.ide.bootstrap.StartupWizardStage
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.ui.scale.JBUIScale
import com.intellij.ui.util.minimumWidth
import com.intellij.ui.util.preferredWidth
import com.intellij.util.ui.JBDimension
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import com.jetbrains.rd.util.lifetime.intersect
import java.awt.*
@@ -82,11 +80,11 @@ class ImportProgressPage(importFromProduct: DialogImportData, controller: Import
cn.gridx = 0
cn.gridy = 1
add(HLabel(from.item.name).label, cn)
add(ProgressLabel(from.item.name).label, cn)
cn.gridx = 2
cn.gridy = 1
add(HLabel(to.item.name).label, cn)
add(ProgressLabel(to.item.name).label, cn)
border = JBUI.Borders.emptyBottom(18)
@@ -94,7 +92,7 @@ class ImportProgressPage(importFromProduct: DialogImportData, controller: Import
}
add(JPanel(VerticalLayout(JBUI.scale(8)).apply {
val hLabel = CommentLabel("")
val hLabel = ProgressCommentLabel("")
add(JProgressBar(0, 99).apply {
importFromProduct.progress.progress.advise(lifetime) {
@@ -104,12 +102,11 @@ class ImportProgressPage(importFromProduct: DialogImportData, controller: Import
hLabel.text = if (it != null) "<center>$it</center>" else "&nbsp"
}
preferredWidth = JBUI.scale(280)
preferredSize = Dimension(JBUI.scale (280), preferredSize.height)
})
add(hLabel.label.apply {
font = JBFont.medium()
foreground = JBUI.CurrentTheme.ContextHelp.FOREGROUND
})
}).apply {
@@ -132,44 +129,4 @@ class ImportProgressPage(importFromProduct: DialogImportData, controller: Import
}
override val content: JComponent = contentPage
private open class HLabel(txt: String) {
var text: @NlsContexts.Label String = ""
set(value) {
@Suppress("HardCodedStringLiteral") // IDEA-338243
if (field == value) return
lbl.text = "<html><center>${value}</center></html>"
field = value
}
private val lbl = object : JLabel() {
override fun getPreferredSize(): Dimension {
val preferredSize = super.getPreferredSize()
return getPref(preferredSize.height)
}
}
open fun getPref(prefH: Int): Dimension {
return Dimension(0, prefH)
}
val label: JComponent
get() {
return lbl
}
init {
lbl.isOpaque = false
lbl.minimumWidth = 10
lbl.horizontalAlignment = SwingConstants.CENTER
lbl.verticalAlignment = SwingConstants.TOP
text = txt
}
}
private class CommentLabel(txt: String) : HLabel(txt) {
override fun getPref(prefH: Int): Dimension {
return Dimension(0, Math.max(prefH, JBUI.scale(45)))
}
}
}
@@ -19,7 +19,6 @@ import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.ui.dsl.builder.AlignY
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.dsl.gridLayout.UnscaledGaps
import com.intellij.ui.util.preferredWidth
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import java.awt.*
@@ -90,7 +89,8 @@ abstract class SettingChooserPage(private val provider: ActionsDataProvider<*>,
}
}.align(AlignY.TOP)
}.apply {
preferredWidth = JBUI.scale(200)
preferredSize = Dimension(JBUI.scale(200), preferredSize.height)
border = JBUI.Borders.empty(20, 20, 0, 0)
}, BorderLayout.WEST)
@@ -103,7 +103,6 @@ abstract class SettingChooserPage(private val provider: ActionsDataProvider<*>,
add(st.component())
}
}
add(
JBScrollPane(listPane).apply {
viewport.isOpaque = false
@@ -8,7 +8,6 @@ import com.intellij.ide.startup.importSettings.data.ActionsDataProvider
import com.intellij.ide.startup.importSettings.data.DialogImportData
import com.intellij.ide.startup.importSettings.data.SettingsContributor
import com.intellij.ide.startup.importSettings.data.SettingsService
import com.intellij.openapi.ui.DialogWrapper
interface ImportSettingsController : BaseController {
companion object {
@@ -35,7 +34,7 @@ private class ImportSettingsControllerImpl(dialog: OnboardingDialog, override va
* what should we do here?
*/
/*skipImportAction.invoke()*/
dialog.doClose(DialogWrapper.CANCEL_EXIT_CODE)
dialog.dialogClose()
}
settService.error.advise(lifetime) {
@@ -61,6 +60,6 @@ private class ImportSettingsControllerImpl(dialog: OnboardingDialog, override va
override fun skipImport() {
dialog.doClose(DialogWrapper.CANCEL_EXIT_CODE)
dialog.dialogClose()
}
}
@@ -2,7 +2,6 @@
package com.intellij.ide.startup.importSettings.chooser.ui
import com.intellij.ide.startup.importSettings.data.WizardProvider
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.util.NlsContexts
class OnboardingController private constructor(){
@@ -66,9 +65,7 @@ class OnboardingController private constructor(){
}
fun dialogClose() {
if(dialog.isShowing && dialog.isVisible) {
dialog.doClose(DialogWrapper.CANCEL_EXIT_CODE)
}
dialog.dialogClose()
}
@@ -94,7 +91,7 @@ class OnboardingController private constructor(){
}
dialog.title = title
state = State.IMPORT
state = State.WIZARD
}
}
@@ -43,7 +43,13 @@ class OnboardingDialog(val cancelCallback: () -> Unit) : DialogWrapper(null, nul
}
}
fun doClose(code: Int) {
fun dialogClose() {
if(isShowing && isVisible) {
doClose(CANCEL_EXIT_CODE)
}
}
private fun doClose(code: Int) {
tracker.onLeave()
close(code)
}
@@ -0,0 +1,53 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.startup.importSettings.chooser.ui
import com.intellij.openapi.util.NlsContexts
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import java.awt.Dimension
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.SwingConstants
open class ProgressLabel(txt: String) {
var text: @NlsContexts.Label String = ""
set(value) {
@Suppress("HardCodedStringLiteral") // IDEA-338243
if (field == value) return
lbl.text = "<html><center>${value}</center></html>"
field = value
}
protected val lbl = object : JLabel() {
override fun getPreferredSize(): Dimension {
val preferredSize = super.getPreferredSize()
return getPref(preferredSize.height)
}
}
open fun getPref(prefH: Int): Dimension {
return Dimension(0, prefH)
}
val label: JComponent
get() {
return lbl
}
init {
lbl.isOpaque = false
lbl.minimumSize = Dimension(10, lbl.minimumSize.height)
lbl.horizontalAlignment = SwingConstants.CENTER
lbl.verticalAlignment = SwingConstants.TOP
text = txt
}
}
class ProgressCommentLabel(txt: String) : ProgressLabel(txt) {
init {
lbl.font = JBFont.medium()
}
override fun getPref(prefH: Int): Dimension {
return Dimension(0, Math.max(prefH, JBUI.scale(45)))
}
}
@@ -3,7 +3,8 @@ package com.intellij.ide.startup.importSettings.chooser.ui
import com.intellij.ide.startup.importSettings.data.WizardService
import com.intellij.ide.startup.importSettings.wizard.keymapChooser.KeymapChooserPage
import com.intellij.ide.startup.importSettings.wizard.pluginChooser.PluginChooserPage
import com.intellij.ide.startup.importSettings.wizard.pluginChooser.WizardPluginsPage
import com.intellij.ide.startup.importSettings.wizard.pluginChooser.WizardProgressPage
interface WizardController : BaseController {
companion object {
@@ -19,7 +20,8 @@ interface WizardController : BaseController {
fun goToThemePage()
fun goToKeymapPage()
fun goToPluginPage()
fun goToInstallPluginPage(ids: List<String>)
fun skipPlugins()
}
class WizardControllerImpl(dialog: OnboardingDialog,
@@ -35,8 +37,22 @@ class WizardControllerImpl(dialog: OnboardingDialog,
}
override fun goToPluginPage() {
val page = PluginChooserPage(this)
val page = WizardPluginsPage(this)
dialog.changePage(page)
}
override fun goToInstallPluginPage(ids: List<String>) {
if(ids.isNotEmpty()) {
val importProgress = service.getPluginService().install(ids)
val page = WizardProgressPage(importProgress, this)
dialog.changePage(page)
} else {
skipPlugins()
}
}
override fun skipPlugins() {
service.getPluginService().skipPlugins()
dialog.dialogClose()
}
}
@@ -6,14 +6,15 @@ import com.intellij.ui.JBColor
import com.intellij.ui.SeparatorComponent
import com.intellij.ui.SeparatorOrientation
import com.intellij.util.ui.JBUI
import java.awt.FlowLayout
import java.awt.BorderLayout
import java.awt.Dimension
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import javax.swing.JButton
import javax.swing.JComponent
import javax.swing.JPanel
class WizardPagePane(centralPane: JComponent, buttons: List<JButton>) : JPanel() {
class WizardPagePane(centralPane: JComponent, buttons: List<JButton>, leftComponent: JComponent? = null) : JPanel() {
init {
layout = GridBagLayout()
@@ -29,7 +30,7 @@ class WizardPagePane(centralPane: JComponent, buttons: List<JButton>) : JPanel()
gbc.fill = GridBagConstraints.BOTH
gbc.gridy = 1
gbc.weighty = 2.0
gbc.weighty = 1.0
add(centralPane, gbc)
gbc.fill = GridBagConstraints.HORIZONTAL
@@ -37,15 +38,25 @@ class WizardPagePane(centralPane: JComponent, buttons: List<JButton>) : JPanel()
gbc.weighty = 0.0
add(SeparatorComponent(JBColor.namedColor("Borders.color", JBColor.BLACK), SeparatorOrientation.HORIZONTAL), gbc)
val buttonPane = JPanel(FlowLayout(FlowLayout.RIGHT)).apply {
add(DialogWrapper.layoutButtonsPanel(buttons))
border = JBUI.Borders.empty(3, 0, 3, 15)
val buttonPane = object : JPanel(BorderLayout()) {
override fun getPreferredSize(): Dimension {
val preferredSize = super.getPreferredSize()
return Dimension(preferredSize.width, JBUI.scale(57))
}
}.apply {
leftComponent?.let {
add(leftComponent, BorderLayout.CENTER)
}
add(DialogWrapper.layoutButtonsPanel(buttons), BorderLayout.EAST)
border = JBUI.Borders.empty(3, 0, 3, 20)
preferredSize = Dimension(preferredSize.width, JBUI.scale(57))
}
gbc.fill = GridBagConstraints.HORIZONTAL
gbc.gridy = 3
gbc.weighty = 0.0
gbc.anchor = GridBagConstraints.SOUTH
gbc.fill = GridBagConstraints.HORIZONTAL
add(buttonPane, gbc)
}
}
@@ -4,6 +4,10 @@ package com.intellij.ide.startup.importSettings.data
import com.intellij.icons.AllIcons
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rd.util.reactive.*
import com.jetbrains.rd.util.threading.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.jetbrains.annotations.Nls
import java.util.*
import javax.swing.Icon
@@ -79,21 +83,43 @@ class PluginServiceImpl : PluginService {
override val plugins: List<WizardPlugin> = listOf
override fun install(ids: List<String>): PluginImportProgress = TestPluginImportProgress(Lifetime.Eternal)
override fun skipPlugins() {
}
}
class TestPluginImportProgress(lifetime: Lifetime) : TestImportProgress(lifetime), PluginImportProgress {
override val complete: Signal<PluginInstallationResult> = Signal()
private val iconList = listOf(AllIcons.Plugins.PluginLogo,
AllIcons.Plugins.PluginLogoDisabled,
AllIcons.TransferSettings.RecentProjects,
AllIcons.TransferSettings.Vscode,
AllIcons.TransferSettings.Settings,
AllIcons.TransferSettings.PluginsAndFeatures)
override val icon = Property(AllIcons.Plugins.PluginLogo)
private var index = 0
init {
lifetime.launch {
launch(Dispatchers.Default) {
while (true) {
index = if (index < iconList.size - 1) index + 1 else 0
icon.set(
iconList[index]
)
delay(300L)
}
}
}
}
}
class WizardPluginImpl(override val icon: Icon,
override val name: String,
override val description: String? = null,
override val id: String = UUID.randomUUID().toString(),
override val state: IProperty<WizardPlugin.State> = Property(WizardPlugin.State.UNCHECKED)) : WizardPlugin {
override val id: String = UUID.randomUUID().toString()) : WizardPlugin {
}
@Suppress("HardCodedStringLiteral")
class TestKeymapService : KeymapService {
override val keymaps: List<WizardKeymap> =
@@ -46,32 +46,18 @@ interface WizardTheme {
interface PluginService {
val plugins: List<WizardPlugin>
fun install(ids: List<String>): PluginImportProgress
fun skipPlugins()
}
interface PluginImportProgress : ImportProgress {
val complete: Signal<PluginInstallationResult>
}
interface PluginInstallationResult {
val icon: Icon
val message: String
val icon: IPropertyView<Icon>
}
interface WizardPlugin {
enum class State {
IN_PROGRESS,
INSTALLED,
CHECKED,
UNCHECKED,
ERROR
}
val id: String
val icon: Icon
val name: String
val description: String?
val state: IProperty<State>
}
interface KeymapService {
@@ -5,12 +5,8 @@ import com.intellij.ide.startup.importSettings.ImportSettingsBundle
import com.intellij.ide.startup.importSettings.chooser.ui.OnboardingPage
import com.intellij.ide.startup.importSettings.chooser.ui.WizardController
import com.intellij.ide.startup.importSettings.chooser.ui.WizardPagePane
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.ide.bootstrap.StartupWizardStage
import com.intellij.ui.JBColor
import com.intellij.ui.SeparatorComponent
import com.intellij.ui.SeparatorOrientation
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import java.awt.*
@@ -1,84 +0,0 @@
// 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.startup.importSettings.wizard.pluginChooser
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
import com.intellij.ide.startup.importSettings.chooser.ui.OnboardingPage
import com.intellij.ide.startup.importSettings.chooser.ui.WizardController
import com.intellij.ide.startup.importSettings.chooser.ui.WizardPagePane
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.ide.bootstrap.StartupWizardStage
import com.intellij.ui.JBColor
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import com.jetbrains.rd.util.lifetime.intersect
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import javax.swing.*
class PluginChooserPage(val controller: WizardController) : OnboardingPage {
override val stage: StartupWizardStage = StartupWizardStage.WizardPluginPage
private val lifetime = controller.lifetime.createNested().intersect(this.createLifetime())
private val pluginPanes = mutableListOf<WizardPluginPane>()
private val contentPage: JComponent
override fun confirmExit(parentComponent: Component?): Boolean = true
private val pane = JPanel(BorderLayout(0, 0)).apply {
add(JLabel(ImportSettingsBundle.message("choose.keymap.title")).apply {
font = JBFont.h1()
border = JBUI.Borders.empty(18, 20)
}, BorderLayout.NORTH)
val plugins = controller.service.getPluginService().plugins
val listPane = JPanel(VerticalLayout(JBUI.scale(4))).apply {
isOpaque = false
plugins.forEach {
val pl = WizardPluginPane(it, lifetime)
pluginPanes.add(pl)
add(pl.pane)
}
border = JBUI.Borders.empty(10, 0)
}
add(
JBScrollPane(listPane).apply {
viewport.isOpaque = false
isOpaque = true
background = JBColor.namedColor("WelcomeScreen.Details.background", JBColor(Color.white, Color(0x313335)))
horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
border = JBUI.Borders.empty()
}, BorderLayout.CENTER
)
}
init {
val backAction = controller.createButton(ImportSettingsBundle.message("import.settings.back")) {
controller.goToKeymapPage()
}
val continueAction = controller.createDefaultButton(ImportSettingsBundle.message("wizard.button.continue")) {
//controller.goToPluginPage()
}
val buttons: List<JButton> = if (SystemInfo.isMac) {
listOf(backAction, continueAction)
}
else listOf(continueAction, backAction)
contentPage = WizardPagePane(pane, buttons)
}
override val content: JComponent = contentPage
}
@@ -2,26 +2,29 @@
package com.intellij.ide.startup.importSettings.wizard.pluginChooser
import com.intellij.ide.startup.importSettings.data.WizardPlugin
import com.intellij.ui.AnimatedIcon
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.ui.dsl.builder.HyperlinkEventAction
import com.intellij.ui.dsl.builder.MAX_LINE_LENGTH_WORD_WRAP
import com.intellij.ui.dsl.builder.components.DslLabel
import com.intellij.ui.dsl.builder.components.DslLabelType
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rd.util.reactive.IProperty
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import javax.swing.JComponent
import javax.swing.JEditorPane
import javax.swing.JLabel
import javax.swing.JPanel
class WizardPluginPane(plugin: WizardPlugin, lifetime: Lifetime) {
private var checkBox = CheckBoxComponent(plugin.state, lifetime)
class WizardPluginPane(val plugin: WizardPlugin, changeHandler: () -> Unit) {
private var checkBox = JBCheckBox().apply {
addItemListener { e ->
changeHandler()
}
isOpaque = false
}
val selected: Boolean
get() = checkBox.isSelected
val pane = JPanel(GridBagLayout()).apply {
val c = GridBagConstraints()
@@ -93,66 +96,4 @@ class WizardPluginPane(plugin: WizardPlugin, lifetime: Lifetime) {
return dslLabel
}
internal class CheckBoxComponent(state: IProperty<WizardPlugin.State>, lifetime: Lifetime) : JPanel() {
private val checkBox: JBCheckBox = JBCheckBox()
private val progress: JLabel = JLabel(AnimatedIcon.Default.INSTANCE)
private val error: JLabel = JLabel(com.intellij.icons.AllIcons.Ide.FatalError)
private val controls = listOf<JComponent>(checkBox, progress, error)
init {
layout = VerticalLayout(0, 0)
border = JBUI.Borders.empty()
isOpaque = false
checkBox.isOpaque = false
checkBox.isSelected = state.value == WizardPlugin.State.CHECKED
checkBox.addItemListener { e ->
state.set(if (checkBox.isSelected) WizardPlugin.State.CHECKED else WizardPlugin.State.UNCHECKED)
}
add(checkBox)
add(progress)
add(error)
state.advise(lifetime) {
when (it) {
WizardPlugin.State.UNCHECKED -> {
setVisibleControl(checkBox)
checkBox.isSelected = false
checkBox.isEnabled = true
}
WizardPlugin.State.CHECKED -> {
setVisibleControl(checkBox)
checkBox.isSelected = true
checkBox.isEnabled = true
}
WizardPlugin.State.INSTALLED -> {
setVisibleControl(checkBox)
checkBox.isSelected = true
checkBox.isEnabled = false
}
WizardPlugin.State.ERROR -> {
setVisibleControl(error)
}
WizardPlugin.State.IN_PROGRESS -> {
setVisibleControl(progress)
}
}
}
}
private fun setVisibleControl(component: JComponent) {
component.isVisible = true
controls.forEach {
if (it != component) {
it.isVisible = false
}
}
}
}
}
@@ -0,0 +1,125 @@
// 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.startup.importSettings.wizard.pluginChooser
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
import com.intellij.ide.startup.importSettings.chooser.ui.OnboardingPage
import com.intellij.ide.startup.importSettings.chooser.ui.WizardController
import com.intellij.ide.startup.importSettings.chooser.ui.WizardPagePane
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.ide.bootstrap.StartupWizardStage
import com.intellij.ui.JBColor
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.components.BorderLayoutPanel
import java.awt.Color
import java.awt.Component
import java.awt.Dimension
import javax.swing.*
class WizardPluginsPage(val controller: WizardController) : OnboardingPage {
private val pluginService = controller.service.getPluginService()
override val stage: StartupWizardStage = StartupWizardStage.WizardPluginPage
private val pluginPanes = mutableListOf<WizardPluginPane>()
private val contentPage: JComponent
private val leftLabel = JLabel().apply {
border = JBUI.Borders.emptyLeft(26)
foreground = UIUtil.getContextHelpForeground()
}
override fun confirmExit(parentComponent: Component?): Boolean = true
private fun getSelected(): List<WizardPluginPane> {
return pluginPanes.filter { it.selected }.toList()
}
private fun changeHandler() {
val selected = getSelected()
when(selected.size) {
0 -> {
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.no")
continueAction.text = ImportSettingsBundle.message("plugins.page.ok.button.continue.without")
}
1 -> {
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.one")
continueAction.text = ImportSettingsBundle.message("plugins.page.ok.button.install")
}
else -> {
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.multiple", selected.size)
continueAction.text = ImportSettingsBundle.message("plugins.page.ok.button.install")
}
}
}
private val pane = BorderLayoutPanel().apply {
isOpaque = false
addToTop(JLabel(ImportSettingsBundle.message("plugins.page.title")).apply {
font = JBFont.h1()
border = JBUI.Borders.empty(18, 20)
})
val plugins = pluginService.plugins
val listPane = JPanel(VerticalLayout(JBUI.scale(4))).apply {
isOpaque = false
plugins.forEach {
val pl = WizardPluginPane(it) { changeHandler() }
pluginPanes.add(pl)
add(pl.pane)
}
border = JBUI.Borders.empty(10, 0)
}
addToCenter(
object : JPanel(){
override fun getPreferredSize(): Dimension {
val preferredSize = super.getPreferredSize()
return Dimension(preferredSize.width, 0)
}
}.apply {
layout = BoxLayout(this, BoxLayout.Y_AXIS)
preferredSize = Dimension(preferredSize.width, 0)
add(JBScrollPane(listPane).apply {
viewport.isOpaque = false
isOpaque = true
background = JBColor.namedColor("WelcomeScreen.Details.background", JBColor(Color.white, Color(0x313335)))
horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
border = JBUI.Borders.empty()
minimumSize = Dimension(0, 0)
})
})
}
private val backAction = controller.createButton(ImportSettingsBundle.message("import.settings.back")) {
controller.goToKeymapPage()
}
private val continueAction = controller.createDefaultButton(ImportSettingsBundle.message("plugins.page.ok.button.continue.without")) {
val ids = getSelected().map { it.plugin.id }.toList()
controller.goToInstallPluginPage(ids)
}
init {
val buttons: List<JButton> = if (SystemInfo.isMac) {
listOf(backAction, continueAction)
}
else listOf(continueAction, backAction)
contentPage = WizardPagePane(pane, buttons, leftLabel)
changeHandler()
}
override val content: JComponent = contentPage
}
@@ -0,0 +1,77 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.startup.importSettings.wizard.pluginChooser
import com.intellij.CommonBundle
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
import com.intellij.ide.startup.importSettings.chooser.ui.OnboardingPage
import com.intellij.ide.startup.importSettings.chooser.ui.ProgressCommentLabel
import com.intellij.ide.startup.importSettings.chooser.ui.WizardController
import com.intellij.ide.startup.importSettings.data.PluginImportProgress
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.ui.MessageDialogBuilder
import com.intellij.platform.ide.bootstrap.StartupWizardStage
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.ui.scale.JBUIScale
import com.intellij.util.ui.JBDimension
import com.intellij.util.ui.JBUI
import com.jetbrains.rd.util.lifetime.intersect
import java.awt.*
import javax.swing.*
class WizardProgressPage(val progress: PluginImportProgress, val controller: WizardController) : OnboardingPage {
override val stage: StartupWizardStage = StartupWizardStage.WizardProgressPage
private val lifetime = controller.lifetime.createNested().intersect(this.createLifetime())
private val icon = JLabel()
private val msgLabel = ProgressCommentLabel("")
private val jProgressBar = JProgressBar(0, 99).apply {
preferredSize = Dimension(JBUI.scale (200), preferredSize.height)
}
private val pane = JPanel(VerticalLayout(JBUI.scale(28))).apply {
add(JLabel(ImportSettingsBundle.message("install.plugins.page.title")).apply {
font = Font(font.fontName, Font.PLAIN, JBUIScale.scaleFontSize(24f))
horizontalAlignment = SwingConstants.CENTER
})
add(icon.apply {
horizontalAlignment = SwingConstants.CENTER
})
add(JPanel(VerticalLayout(JBUIScale.scale(8))).apply {
add(jProgressBar)
add(msgLabel.label)
})
}
override val content: JComponent = JPanel(GridBagLayout()).apply {
preferredSize = JBDimension(640, 457)
val gbc = GridBagConstraints()
gbc.gridx = 0
gbc.gridy = 0
gbc.weightx = 1.0
gbc.weighty = 1.0
add(pane, gbc)
border = JBUI.Borders.empty()
}
init {
progress.progress.advise(lifetime) {
jProgressBar.value = it
}
progress.progressMessage.advise(lifetime) {
msgLabel.text = if (it != null) "<center>$it</center>" else "&nbsp"
}
progress.icon.advise(lifetime) {
icon.icon = it
}
}
override fun confirmExit(parentComponent: Component?): Boolean {
return MessageDialogBuilder.yesNo(ImportSettingsBundle.message("exit.confirm.title"),
ImportSettingsBundle.message("exit.confirm.prompt"))
.yesText(ImportSettingsBundle.message("stop.import"))
.noText(CommonBundle.getCancelButtonText())
.ask(parentComponent)
}
}