diff --git a/platform/platform-impl/src/com/intellij/platform/ide/bootstrap/IdeStartupWizard.kt b/platform/platform-impl/src/com/intellij/platform/ide/bootstrap/IdeStartupWizard.kt index d7ecf8ac9510..78b5c3e1836d 100644 --- a/platform/platform-impl/src/com/intellij/platform/ide/bootstrap/IdeStartupWizard.kt +++ b/platform/platform-impl/src/com/intellij/platform/ide/bootstrap/IdeStartupWizard.kt @@ -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") diff --git a/plugins/ide-startup/importSettings/intellij.ide.startup.importSettings.iml b/plugins/ide-startup/importSettings/intellij.ide.startup.importSettings.iml index 7c669dbfd238..92c0232d9dda 100644 --- a/plugins/ide-startup/importSettings/intellij.ide.startup.importSettings.iml +++ b/plugins/ide-startup/importSettings/intellij.ide.startup.importSettings.iml @@ -50,5 +50,6 @@ + \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/resources/messages/ImportSettingsBundle.properties b/plugins/ide-startup/importSettings/resources/messages/ImportSettingsBundle.properties index 79b2e4250d88..3289d059507a 100644 --- a/plugins/ide-startup/importSettings/resources/messages/ImportSettingsBundle.properties +++ b/plugins/ide-startup/importSettings/resources/messages/ImportSettingsBundle.properties @@ -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 + diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/ij.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij.png new file mode 100644 index 000000000000..f3e5f4b14972 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x.png new file mode 100644 index 000000000000..77fc00280fe3 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x_dark.png new file mode 100644 index 000000000000..c0b922ec985e Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij@2x_dark.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/ij_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij_dark.png new file mode 100644 index 000000000000..fb0d26b4afd7 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/ij_dark.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/rider.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider.png new file mode 100644 index 000000000000..eea666ed5be4 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x.png new file mode 100644 index 000000000000..688374e63783 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x_dark.png new file mode 100644 index 000000000000..2a307354c5ea Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider@2x_dark.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/rider_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider_dark.png new file mode 100644 index 000000000000..c57035a579fe Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/rider_dark.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/vs.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs.png new file mode 100644 index 000000000000..020519c817ef Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x.png new file mode 100644 index 000000000000..6597db6873be Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x_dark.png new file mode 100644 index 000000000000..401f52a0eff3 Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs@2x_dark.png differ diff --git a/plugins/ide-startup/importSettings/resources/wizardPreviews/vs_dark.png b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs_dark.png new file mode 100644 index 000000000000..677aa4df492f Binary files /dev/null and b/plugins/ide-startup/importSettings/resources/wizardPreviews/vs_dark.png differ diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/importProgress/ImportProgressPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/importProgress/ImportProgressPage.kt index 0cadd7192a23..79878c556db8 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/importProgress/ImportProgressPage.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/importProgress/ImportProgressPage.kt @@ -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) "
$it
" else " " } - 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 = "
${value}
" - 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))) - } - } } \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/settingChooser/SettingChooserPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/settingChooser/SettingChooserPage.kt index 02ee5b80b853..fa45358e830e 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/settingChooser/SettingChooserPage.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/settingChooser/SettingChooserPage.kt @@ -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 diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ImportSettingsController.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ImportSettingsController.kt index 90bd41953267..26e390f873e8 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ImportSettingsController.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ImportSettingsController.kt @@ -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() } } \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingController.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingController.kt index aa3423ff7a3e..11a74def9af1 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingController.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingController.kt @@ -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 } } \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingDialog.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingDialog.kt index 39af62e6bc44..41a1fc17e531 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingDialog.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/OnboardingDialog.kt @@ -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) } diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ProgressLabel.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ProgressLabel.kt new file mode 100644 index 000000000000..b9bbac554bf1 --- /dev/null +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/ProgressLabel.kt @@ -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 = "
${value}
" + 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))) + } +} \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardController.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardController.kt index c4b121d19544..70b264baa876 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardController.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardController.kt @@ -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) + 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) { + 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() + } } diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardPagePane.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardPagePane.kt index 460c215af75c..529315c90925 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardPagePane.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/chooser/ui/WizardPagePane.kt @@ -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) : JPanel() { +class WizardPagePane(centralPane: JComponent, buttons: List, leftComponent: JComponent? = null) : JPanel() { init { layout = GridBagLayout() @@ -29,7 +30,7 @@ class WizardPagePane(centralPane: JComponent, buttons: List) : 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) : 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) + } } \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardMockData.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardMockData.kt index 0196c36d3b74..299a69796030 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardMockData.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardMockData.kt @@ -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 = listOf override fun install(ids: List): PluginImportProgress = TestPluginImportProgress(Lifetime.Eternal) + override fun skipPlugins() { + + } } class TestPluginImportProgress(lifetime: Lifetime) : TestImportProgress(lifetime), PluginImportProgress { - override val complete: Signal = 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 = Property(WizardPlugin.State.UNCHECKED)) : WizardPlugin { - + override val id: String = UUID.randomUUID().toString()) : WizardPlugin { } - @Suppress("HardCodedStringLiteral") class TestKeymapService : KeymapService { override val keymaps: List = diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardProvider.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardProvider.kt index 9733cd66c208..79f5099b8af0 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardProvider.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/data/WizardProvider.kt @@ -46,32 +46,18 @@ interface WizardTheme { interface PluginService { val plugins: List fun install(ids: List): PluginImportProgress + fun skipPlugins() } interface PluginImportProgress : ImportProgress { - val complete: Signal -} - -interface PluginInstallationResult { - val icon: Icon - val message: String + val icon: IPropertyView } 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 } interface KeymapService { diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/keymapChooser/KeymapChooserPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/keymapChooser/KeymapChooserPage.kt index afcecbf2ddc8..2f414ae1b2fd 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/keymapChooser/KeymapChooserPage.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/keymapChooser/KeymapChooserPage.kt @@ -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.* diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/PluginChooserPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/PluginChooserPage.kt deleted file mode 100644 index 85a38068a7ba..000000000000 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/PluginChooserPage.kt +++ /dev/null @@ -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() - - 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 = if (SystemInfo.isMac) { - listOf(backAction, continueAction) - } - else listOf(continueAction, backAction) - - - contentPage = WizardPagePane(pane, buttons) - } - - override val content: JComponent = contentPage - -} - - diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginPane.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginPane.kt index 7bd1af9bed80..eb01b5a6e00c 100644 --- a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginPane.kt +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginPane.kt @@ -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, 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(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 - } - } - } - } } \ No newline at end of file diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginsPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginsPage.kt new file mode 100644 index 000000000000..d823367a6508 --- /dev/null +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardPluginsPage.kt @@ -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() + + 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 { + 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 = if (SystemInfo.isMac) { + listOf(backAction, continueAction) + } + else listOf(continueAction, backAction) + + + contentPage = WizardPagePane(pane, buttons, leftLabel) + + changeHandler() + } + + override val content: JComponent = contentPage +} + + + + diff --git a/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardProgressPage.kt b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardProgressPage.kt new file mode 100644 index 000000000000..1c7610429813 --- /dev/null +++ b/plugins/ide-startup/importSettings/src/com/intellij/ide/startup/importSettings/wizard/pluginChooser/WizardProgressPage.kt @@ -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) "
$it
" else " " + } + + 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) + } +} \ No newline at end of file