mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
PY-72994 Packages(refactor, feat): Rename Delete package andd Update package
GitOrigin-RevId: 56ddaade343cb5eeb3240fd1090f68b72e42ed86
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c15235e357
commit
134376878d
@@ -742,7 +742,7 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
|
||||
dynamic="true"/>
|
||||
|
||||
<extensionPoint qualifiedName="Pythonid.PythonPackagingToolwindowActionProvider"
|
||||
interface="com.jetbrains.python.packaging.toolwindow.PythonPackagingToolwindowActionProvider"
|
||||
interface="com.jetbrains.python.packaging.toolwindow.actions.PythonPackagingToolwindowActionProvider"
|
||||
dynamic="true"/>
|
||||
|
||||
<extensionPoint qualifiedName="Pythonid.pythonPackageManagerProvider"
|
||||
|
||||
@@ -1356,8 +1356,9 @@ python.toolwindow.packages.custom.repo.invalid={0} (Authorization failed)
|
||||
python.toolwindow.packages.documentation.link=Documentation
|
||||
python.toolwindow.packages.no.interpreter.text=Select an interpreter to see the installed packages
|
||||
python.toolwindow.packages.latest.version.label=latest
|
||||
python.toolwindow.packages.delete.package=Delete Package
|
||||
python.toolwindow.packages.update.package=Update Package
|
||||
python.toolwindow.packages.delete.package=Uninstall
|
||||
python.toolwindow.packages.update.package=Change Version
|
||||
python.toolwindow.packages.update.package.version=Update {0} -> {1}
|
||||
python.toolwindow.packages.install.link=Install
|
||||
python.toolwindow.packages.search.text.placeholder=Search for more packages
|
||||
python.toolwindow.packages.description.panel.placeholder=Select a package to view documentation
|
||||
|
||||
@@ -4,9 +4,9 @@ package com.jetbrains.python.packaging.conda
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.toolwindow.PythonPackagingToolwindowActionProvider
|
||||
import com.jetbrains.python.packaging.toolwindow.PythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.SimplePythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackagingToolwindowActionProvider
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.SimplePythonPackageInstallAction
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
|
||||
@@ -5,9 +5,9 @@ import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.common.PythonSimplePackageDetails
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.toolwindow.PythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.PythonPackagingToolwindowActionProvider
|
||||
import com.jetbrains.python.packaging.toolwindow.SimplePythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackagingToolwindowActionProvider
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.SimplePythonPackageInstallAction
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
|
||||
@@ -6,6 +6,11 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.ui.JBColor
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.repository.PyPackageRepository
|
||||
import com.jetbrains.python.packaging.toolwindow.model.*
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTableModel
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagingTableGroup
|
||||
import java.awt.Rectangle
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
@@ -99,7 +104,7 @@ class PyPackagingTablesView(private val project: Project,
|
||||
foreground = JBColor.RED
|
||||
icon = AllIcons.General.Error
|
||||
}
|
||||
it to headerPanel(label, null)
|
||||
it to PyPackagesUiComponents.headerPanel(label, null)
|
||||
}
|
||||
.forEach {
|
||||
invalidRepositories[it.first] = it.second
|
||||
|
||||
@@ -46,10 +46,19 @@ import com.jetbrains.python.packaging.PyPackageUtil
|
||||
import com.jetbrains.python.packaging.common.PythonLocalPackageSpecification
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.common.PythonVcsPackageSpecification
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackageInstallAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PythonPackagingToolwindowActionProvider
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.PyPackagesViewData
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import java.awt.event.ActionEvent
|
||||
@@ -60,7 +69,7 @@ import javax.swing.event.DocumentEvent
|
||||
import javax.swing.event.ListSelectionListener
|
||||
|
||||
class PyPackagingToolWindowPanel(private val project: Project, toolWindow: ToolWindow) : SimpleToolWindowPanel(false, true), Disposable {
|
||||
internal val packagingScope = CoroutineScope(Dispatchers.IO)
|
||||
internal val packagingScope = PyPackageCoroutine.getIoScope(project)
|
||||
private var selectedPackage: DisplayablePackage? = null
|
||||
private var selectedPackageDetails: PythonPackageDetails? = null
|
||||
|
||||
@@ -172,20 +181,20 @@ class PyPackagingToolWindowPanel(private val project: Project, toolWindow: ToolW
|
||||
tablesView = PyPackagingTablesView(project, packageListPanel, this)
|
||||
|
||||
leftPanel = createLeftPanel(service)
|
||||
rightPanel = borderPanel {
|
||||
add(borderPanel {
|
||||
rightPanel = PyPackagesUiComponents.borderPanel {
|
||||
add(PyPackagesUiComponents.borderPanel {
|
||||
border = SideBorder(JBColor.GRAY, SideBorder.BOTTOM)
|
||||
preferredSize = Dimension(preferredSize.width, 50)
|
||||
minimumSize = Dimension(minimumSize.width, 50)
|
||||
maximumSize = Dimension(maximumSize.width, 50)
|
||||
add(boxPanel {
|
||||
add(PyPackagesUiComponents.boxPanel {
|
||||
add(Box.createHorizontalStrut(10))
|
||||
add(packageNameLabel)
|
||||
add(Box.createHorizontalStrut(10))
|
||||
add(documentationLink)
|
||||
}, BorderLayout.WEST)
|
||||
add(boxPanel {
|
||||
alignmentX = Component.RIGHT_ALIGNMENT
|
||||
add(PyPackagesUiComponents.boxPanel {
|
||||
alignmentX = RIGHT_ALIGNMENT
|
||||
add(progressBar)
|
||||
add(versionSelector)
|
||||
add(versionLabel)
|
||||
@@ -266,8 +275,8 @@ class PyPackagingToolWindowPanel(private val project: Project, toolWindow: ToolW
|
||||
}
|
||||
}
|
||||
|
||||
mainPanel = borderPanel {
|
||||
val topToolbar = boxPanel {
|
||||
mainPanel = PyPackagesUiComponents.borderPanel {
|
||||
val topToolbar = PyPackagesUiComponents.boxPanel {
|
||||
border = SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.BOTTOM)
|
||||
preferredSize = Dimension(preferredSize.width, 30)
|
||||
minimumSize = Dimension(minimumSize.width, 30)
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.management.packagesByRepository
|
||||
import com.jetbrains.python.packaging.repository.*
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.model.*
|
||||
import com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory
|
||||
import com.jetbrains.python.run.applyHelperPackageToPythonPath
|
||||
import com.jetbrains.python.run.buildTargetedCommandLine
|
||||
@@ -197,7 +198,6 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
|
||||
}
|
||||
|
||||
private suspend fun invokeUpdateLatestVersion() {
|
||||
serviceScope.launch(Dispatchers.Default) {
|
||||
val proccessPackages = installedPackages
|
||||
val updatedPackages = proccessPackages.map { (name, pyPackage: InstalledPackage) ->
|
||||
val specification = pyPackage.repository.createPackageSpecification(pyPackage.name)
|
||||
@@ -220,7 +220,6 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
|
||||
}.toMap()
|
||||
handleSearch(currentQuery)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun showPackagingNotification(text: @Nls String) {
|
||||
val notification = NotificationGroupManager.getInstance()
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.common.PythonPackageSpecification
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
interface PythonPackagingToolwindowActionProvider {
|
||||
fun getInstallActions(details: PythonPackageDetails, packageManager: PythonPackageManager): List<PythonPackageInstallAction>?
|
||||
|
||||
companion object {
|
||||
val EP_NAME = ExtensionPointName.create<PythonPackagingToolwindowActionProvider>("Pythonid.PythonPackagingToolwindowActionProvider")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PythonPackageInstallAction(internal val text: @Nls String,
|
||||
internal val project: Project) {
|
||||
|
||||
abstract suspend fun installPackage(specification: PythonPackageSpecification)
|
||||
}
|
||||
|
||||
class SimplePythonPackageInstallAction(text: @Nls String,
|
||||
project: Project) : PythonPackageInstallAction(text, project) {
|
||||
override suspend fun installPackage(specification: PythonPackageSpecification) {
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.ui.awt.RelativePoint
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
internal class ChangeVersionPackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.update.package")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val pkg = table.selectedItem() as? InstalledPackage ?: return
|
||||
|
||||
PyPackageCoroutine.getIoScope(project).launch {
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
val details = service.detailsForPackage(pkg)
|
||||
withContext(Dispatchers.EDT) {
|
||||
PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller).show(
|
||||
RelativePoint(e.inputEvent as MouseEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val pkg = table.selectedItem() as? InstalledPackage
|
||||
e.presentation.isEnabledAndVisible = pkg != null
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
internal class DeletePackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.delete.package")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val pkg = table.selectedItem() as? InstalledPackage ?: return
|
||||
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
|
||||
PyPackageCoroutine.launch(project, Dispatchers.IO) {
|
||||
service.deletePackage(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = table.selectedItem() is InstalledPackage
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.ui.awt.RelativePoint
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
internal class InstallPackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.install.link")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
val pkg = table.selectedItem() as? InstallablePackage ?: return
|
||||
|
||||
PyPackageCoroutine.launch(project, Dispatchers.IO) {
|
||||
val details = service.detailsForPackage(pkg)
|
||||
withContext(Dispatchers.Main) {
|
||||
val popup = PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller)
|
||||
popup.show(RelativePoint(e.inputEvent as MouseEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = table.selectedItem() is InstallablePackage
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.jetbrains.python.packaging.common.PythonPackageSpecification
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
abstract class PythonPackageInstallAction(
|
||||
internal val text: @Nls String,
|
||||
internal val project: Project,
|
||||
) {
|
||||
|
||||
abstract suspend fun installPackage(specification: PythonPackageSpecification)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
|
||||
interface PythonPackagingToolwindowActionProvider {
|
||||
fun getInstallActions(details: PythonPackageDetails, packageManager: PythonPackageManager): List<PythonPackageInstallAction>?
|
||||
|
||||
companion object {
|
||||
val EP_NAME = ExtensionPointName.create<PythonPackagingToolwindowActionProvider>("Pythonid.PythonPackagingToolwindowActionProvider")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.jetbrains.python.packaging.common.PythonPackageSpecification
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
class SimplePythonPackageInstallAction(text: @Nls String,
|
||||
project: Project) : PythonPackageInstallAction(text, project) {
|
||||
override suspend fun installPackage(specification: PythonPackageSpecification) {
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.ui.awt.RelativePoint
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
internal class UpdatePackageToLatestAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.update.package")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val pkg = table.selectedItem()
|
||||
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
if (pkg is InstalledPackage && pkg.canBeUpdated) {
|
||||
PyPackageCoroutine.getIoScope(project).launch {
|
||||
val specification = pkg.repository.createPackageSpecification(pkg.name, pkg.nextVersion!!.presentableText)
|
||||
service.updatePackage(specification)
|
||||
}
|
||||
}
|
||||
else if (pkg is InstallablePackage) {
|
||||
PyPackageCoroutine.getIoScope(project).launch {
|
||||
val details = service.detailsForPackage(pkg)
|
||||
withContext(Dispatchers.EDT) {
|
||||
PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller).show(
|
||||
RelativePoint(e.inputEvent as MouseEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val pkg = table.selectedItem() as? InstalledPackage
|
||||
|
||||
val currentVersion = pkg?.currentVersion?.presentableText
|
||||
val nextVersion = pkg?.nextVersion?.presentableText
|
||||
if (currentVersion != null && nextVersion != null) {
|
||||
e.presentation.isEnabledAndVisible = true
|
||||
e.presentation.text = PyBundle.message("python.toolwindow.packages.update.package.version", currentVersion, nextVersion)
|
||||
}
|
||||
else {
|
||||
e.presentation.isEnabledAndVisible = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python.packaging.toolwindow
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.model
|
||||
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.jetbrains.python.packaging.PyPackageVersion
|
||||
@@ -11,9 +11,11 @@ import com.jetbrains.python.packaging.repository.PyPackageRepository
|
||||
sealed class DisplayablePackage(@NlsSafe val name: String, val repository: PyPackageRepository)
|
||||
|
||||
class InstalledPackage(val instance: PythonPackage, repository: PyPackageRepository, val nextVersion: PyPackageVersion? = null) : DisplayablePackage(instance.name, repository) {
|
||||
val currentVersion = PyPackageVersionNormalizer.normalize(instance.version)
|
||||
|
||||
val canBeUpdated: Boolean
|
||||
get() {
|
||||
val currentVersion = PyPackageVersionNormalizer.normalize(instance.version) ?: return false
|
||||
currentVersion ?: return false
|
||||
return nextVersion != null && PyPackageVersionComparator.compare(nextVersion, currentVersion) > 0
|
||||
}
|
||||
|
||||
@@ -24,6 +26,9 @@ class InstalledPackage(val instance: PythonPackage, repository: PyPackageReposit
|
||||
|
||||
|
||||
class InstallablePackage(name: String, repository: PyPackageRepository) : DisplayablePackage(name, repository)
|
||||
|
||||
class ExpandResultNode(var more: Int, repository: PyPackageRepository) : DisplayablePackage("", repository)
|
||||
|
||||
open class PyPackagesViewData(@NlsSafe val repository: PyPackageRepository, val packages: List<DisplayablePackage>, val exactMatch: Int = -1, val moreItems: Int = 0)
|
||||
|
||||
class PyInvalidRepositoryViewData(repository: PyPackageRepository) : PyPackagesViewData(repository, emptyList())
|
||||
@@ -0,0 +1,218 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.ui
|
||||
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.ui.DoubleClickListener
|
||||
import com.intellij.ui.PopupHandler
|
||||
import com.intellij.ui.SideBorder
|
||||
import com.intellij.ui.awt.RelativePoint
|
||||
import com.intellij.ui.hover.TableHoverListener
|
||||
import com.intellij.ui.table.JBTable
|
||||
import com.intellij.util.ui.ListTableModel
|
||||
import com.intellij.util.ui.NamedColorUtil
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingTablesView
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowPanel
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.ChangeVersionPackageAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.DeletePackageAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.InstallPackageAction
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.UpdatePackageToLatestAction
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.ExpandResultNode
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.Cursor
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.AbstractAction
|
||||
import javax.swing.JTable
|
||||
import javax.swing.KeyStroke
|
||||
import javax.swing.ListSelectionModel
|
||||
import javax.swing.table.TableCellRenderer
|
||||
|
||||
internal class PyPackagesTable<T : DisplayablePackage>(
|
||||
project: Project,
|
||||
model: ListTableModel<T>,
|
||||
tablesView: PyPackagingTablesView,
|
||||
val controller: PyPackagingToolWindowPanel,
|
||||
) : JBTable(model) {
|
||||
private var lastSelectedRow = -1
|
||||
internal var hoveredColumn = -1
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val listModel: ListTableModel<T>
|
||||
get() = model as ListTableModel<T>
|
||||
|
||||
var items: List<T>
|
||||
get() = listModel.items
|
||||
set(value) {
|
||||
listModel.items = value.toMutableList()
|
||||
}
|
||||
|
||||
init {
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
setShowGrid(false)
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
|
||||
val column = columnModel.getColumn(1)
|
||||
column.minWidth = 130
|
||||
column.maxWidth = 130
|
||||
column.resizable = false
|
||||
border = SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.BOTTOM)
|
||||
rowHeight = 20
|
||||
|
||||
initCrossNavigation(service, tablesView)
|
||||
|
||||
val hoverListener = object : TableHoverListener() {
|
||||
override fun onHover(table: JTable, row: Int, column: Int) {
|
||||
hoveredColumn = column
|
||||
if (column == 1) {
|
||||
table.repaint(table.getCellRect(row, column, true))
|
||||
val currentPackage = items[row]
|
||||
if (currentPackage is InstallablePackage
|
||||
|| (currentPackage is InstalledPackage && currentPackage.canBeUpdated)) {
|
||||
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
|
||||
return
|
||||
}
|
||||
}
|
||||
cursor = Cursor.getDefaultCursor()
|
||||
}
|
||||
}
|
||||
hoverListener.addTo(this)
|
||||
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (e.clickCount != 1 || columnAtPoint(e.point) != 1) return // double click or click on package name column, nothing to be done
|
||||
val hoveredRow = TableHoverListener.getHoveredRow(this@PyPackagesTable)
|
||||
val selectedPackage = this@PyPackagesTable.items[hoveredRow]
|
||||
|
||||
if (selectedPackage is InstallablePackage) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val details = service.detailsForPackage(selectedPackage)
|
||||
withContext(Dispatchers.Main) {
|
||||
PyPackagesUiComponents.createAvailableVersionsPopup(selectedPackage, details, project, controller).show(RelativePoint(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selectedPackage is InstalledPackage && selectedPackage.canBeUpdated) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val specification = selectedPackage.repository.createPackageSpecification(selectedPackage.name,
|
||||
selectedPackage.nextVersion!!.presentableText)
|
||||
project.service<PyPackagingToolWindowService>().updatePackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
selectionModel.addListSelectionListener {
|
||||
if (selectedRow != -1 && selectedRow != lastSelectedRow) {
|
||||
lastSelectedRow = selectedRow
|
||||
tablesView.requestSelection(this)
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg !is ExpandResultNode) controller.packageSelected(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
object : DoubleClickListener() {
|
||||
override fun onDoubleClick(event: MouseEvent): Boolean {
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg is ExpandResultNode) loadMoreItems(service, pkg)
|
||||
return true
|
||||
}
|
||||
}.installOn(this)
|
||||
|
||||
val packageActionGroup = DefaultActionGroup(
|
||||
DeletePackageAction(this),
|
||||
InstallPackageAction(this),
|
||||
UpdatePackageToLatestAction(this),
|
||||
ChangeVersionPackageAction(this),
|
||||
)
|
||||
PopupHandler.installPopupMenu(this, packageActionGroup, "PackagePopup")
|
||||
}
|
||||
|
||||
|
||||
fun selectedItem(): T? = items.getOrNull(selectedRow)
|
||||
|
||||
private fun initCrossNavigation(service: PyPackagingToolWindowService, tablesView: PyPackagingTablesView) {
|
||||
getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ENTER_ACTION)
|
||||
actionMap.put(ENTER_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
val index = selectedRow
|
||||
val selectedItem = selectedItem() ?: return
|
||||
|
||||
if (selectedItem is ExpandResultNode) {
|
||||
loadMoreItems(service, selectedItem)
|
||||
}
|
||||
setRowSelectionInterval(index, index)
|
||||
}
|
||||
})
|
||||
|
||||
val nextRowAction = actionMap[NEXT_ROW_ACTION]
|
||||
actionMap.put(NEXT_ROW_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
|
||||
if (selectedRow + 1 == items.size) {
|
||||
tablesView.selectNextFrom(this@PyPackagesTable)
|
||||
}
|
||||
else {
|
||||
nextRowAction.actionPerformed(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val prevRowAction = actionMap[PREVIOUS_ROW_ACTION]
|
||||
actionMap.put(PREVIOUS_ROW_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
|
||||
if (selectedRow == 0) {
|
||||
tablesView.selectPreviousOf(this@PyPackagesTable)
|
||||
}
|
||||
else {
|
||||
prevRowAction.actionPerformed(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun loadMoreItems(service: PyPackagingToolWindowService, node: ExpandResultNode) {
|
||||
val result = service.getMoreResultsForRepo(node.repository, items.size - 1)
|
||||
items = items.dropLast(1) + (result.packages as List<T>)
|
||||
if (result.moreItems > 0) {
|
||||
node.more = result.moreItems
|
||||
items = items + listOf(node) as List<T>
|
||||
}
|
||||
this@PyPackagesTable.revalidate()
|
||||
this@PyPackagesTable.repaint()
|
||||
}
|
||||
|
||||
override fun getCellRenderer(row: Int, column: Int): TableCellRenderer {
|
||||
return PyPaginationAwareRenderer()
|
||||
}
|
||||
|
||||
override fun clearSelection() {
|
||||
lastSelectedRow = -1
|
||||
super.clearSelection()
|
||||
}
|
||||
|
||||
internal fun removeRow(index: Int) = listModel.removeRow(index)
|
||||
internal fun insertRow(index: Int, pkg: T) = listModel.insertRow(index, pkg)
|
||||
|
||||
|
||||
companion object {
|
||||
private const val NEXT_ROW_ACTION = "selectNextRow"
|
||||
private const val PREVIOUS_ROW_ACTION = "selectPreviousRow"
|
||||
private const val ENTER_ACTION = "ENTER"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.ui
|
||||
|
||||
import com.intellij.util.ui.ListTableModel
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
|
||||
internal class PyPackagesTableModel<T : DisplayablePackage> : ListTableModel<T>() {
|
||||
override fun isCellEditable(rowIndex: Int, columnIndex: Int): Boolean = false
|
||||
override fun getColumnCount(): Int = 2
|
||||
override fun getColumnName(column: Int): String = column.toString()
|
||||
override fun getColumnClass(columnIndex: Int): Class<*> = DisplayablePackage::class.java
|
||||
override fun getValueAt(rowIndex: Int, columnIndex: Int): Any? = items[rowIndex]
|
||||
}
|
||||
@@ -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.jetbrains.python.packaging.toolwindow.ui
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.ListPopup
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
import com.intellij.ui.SideBorder
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.NamedColorUtil
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowPanel
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.*
|
||||
|
||||
object PyPackagesUiComponents {
|
||||
fun createAvailableVersionsPopup(selectedPackage: DisplayablePackage, details: PythonPackageDetails, project: Project, controller: PyPackagingToolWindowPanel): ListPopup {
|
||||
return JBPopupFactory.getInstance().createListPopup(object : BaseListPopupStep<String>(null, details.availableVersions) {
|
||||
override fun onChosen(selectedValue: String?, finalChoice: Boolean): PopupStep<*>? {
|
||||
return doFinalStep {
|
||||
val specification = selectedPackage.repository.createPackageSpecification(selectedPackage.name, selectedValue)
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 8)
|
||||
}
|
||||
|
||||
|
||||
fun boxPanel(init: JPanel.() -> Unit) = object : JPanel() {
|
||||
init {
|
||||
layout = BoxLayout(this, BoxLayout.X_AXIS)
|
||||
alignmentX = LEFT_ALIGNMENT
|
||||
init()
|
||||
}
|
||||
}
|
||||
|
||||
fun borderPanel(init: JPanel.() -> Unit) = object : JPanel() {
|
||||
init {
|
||||
layout = BorderLayout(0, 0)
|
||||
init()
|
||||
}
|
||||
}
|
||||
|
||||
fun headerPanel(label: JLabel, component: JComponent?) = object : JPanel() {
|
||||
init {
|
||||
background = UIUtil.getLabelBackground()
|
||||
layout = BorderLayout()
|
||||
border = BorderFactory.createCompoundBorder(SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.BOTTOM), JBUI.Borders.empty(0, 5))
|
||||
preferredSize = Dimension(preferredSize.width, 25)
|
||||
minimumSize = Dimension(minimumSize.width, 25)
|
||||
maximumSize = Dimension(maximumSize.width, 25)
|
||||
|
||||
add(label, BorderLayout.WEST)
|
||||
if (component != null) {
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent?) {
|
||||
component.isVisible = !component.isVisible
|
||||
label.icon = if (component.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.ui
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.repository.PyPackageRepository
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
|
||||
internal class PyPackagingTableGroup<T : DisplayablePackage>(val repository: PyPackageRepository, val table: PyPackagesTable<T>) {
|
||||
@NlsSafe
|
||||
val name: String = repository.name!!
|
||||
|
||||
private var expanded = false
|
||||
private val label = JLabel(name).apply { icon = AllIcons.General.ArrowDown }
|
||||
private val header: JPanel = PyPackagesUiComponents.headerPanel(label, table)
|
||||
private var itemsCount: Int? = null
|
||||
|
||||
|
||||
internal var items: List<T>
|
||||
get() = table.items
|
||||
set(value) {
|
||||
table.items = value
|
||||
}
|
||||
|
||||
fun collapse() {
|
||||
expanded = false
|
||||
table.isVisible = false
|
||||
label.icon = if (table.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
|
||||
fun expand() {
|
||||
expanded = true
|
||||
table.isVisible = true
|
||||
label.icon = if (table.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
|
||||
fun updateHeaderText(newItemCount: Int?) {
|
||||
itemsCount = newItemCount
|
||||
label.text = if (itemsCount == null) name else PyBundle.message("python.toolwindow.packages.custom.repo.searched", name, itemsCount)
|
||||
}
|
||||
|
||||
fun addTo(panel: JPanel) {
|
||||
panel.add(header)
|
||||
panel.add(table)
|
||||
}
|
||||
|
||||
fun replace(row: Int, pkg: T) {
|
||||
table.removeRow(row)
|
||||
table.insertRow(row, pkg)
|
||||
}
|
||||
|
||||
fun removeFrom(panel: JPanel) {
|
||||
panel.remove(header)
|
||||
panel.remove(table)
|
||||
}
|
||||
|
||||
fun repaint() {
|
||||
table.invalidate()
|
||||
table.repaint()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.toolwindow.ui
|
||||
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.ui.hover.TableHoverListener
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.ExpandResultNode
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
import java.awt.Component
|
||||
import java.awt.font.TextAttribute
|
||||
import javax.swing.BoxLayout
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.JTable
|
||||
import javax.swing.table.DefaultTableCellRenderer
|
||||
|
||||
internal class PyPaginationAwareRenderer : DefaultTableCellRenderer() {
|
||||
private val nameLabel = JLabel().apply { border = JBUI.Borders.empty(0, 12) }
|
||||
private val versionLabel = JLabel().apply { border = JBUI.Borders.emptyRight(12) }
|
||||
private val linkLabel = JLabel(PyBundle.message("python.toolwindow.packages.install.link")).apply {
|
||||
border = JBUI.Borders.emptyRight(12)
|
||||
foreground = JBUI.CurrentTheme.Link.Foreground.ENABLED
|
||||
}
|
||||
|
||||
private val namePanel = JPanel().apply {
|
||||
layout = BoxLayout(this, BoxLayout.X_AXIS)
|
||||
border = JBUI.Borders.empty()
|
||||
add(nameLabel)
|
||||
}
|
||||
|
||||
private val versionPanel = PyPackagesUiComponents.boxPanel {
|
||||
border = JBUI.Borders.emptyRight(12)
|
||||
add(versionLabel)
|
||||
}
|
||||
|
||||
override fun getTableCellRendererComponent(
|
||||
table: JTable,
|
||||
value: Any?,
|
||||
isSelected: Boolean,
|
||||
hasFocus: Boolean,
|
||||
row: Int,
|
||||
column: Int,
|
||||
): Component {
|
||||
val rowSelected = table.selectedRow == row
|
||||
val tableFocused = table.hasFocus()
|
||||
|
||||
if (value is ExpandResultNode) {
|
||||
if (column == 1) {
|
||||
versionPanel.removeAll()
|
||||
return versionPanel
|
||||
}
|
||||
else {
|
||||
nameLabel.text = PyBundle.message("python.toolwindow.packages.load.more", value.more)
|
||||
nameLabel.foreground = UIUtil.getContextHelpForeground()
|
||||
return namePanel
|
||||
}
|
||||
}
|
||||
|
||||
// version column
|
||||
if (column == 1) {
|
||||
versionPanel.background = JBUI.CurrentTheme.Table.background(rowSelected, tableFocused)
|
||||
versionPanel.foreground = JBUI.CurrentTheme.Table.foreground(rowSelected, tableFocused)
|
||||
versionPanel.removeAll()
|
||||
|
||||
if (value is InstallablePackage) {
|
||||
linkLabel.text = PyBundle.message("python.toolwindow.packages.install.link")
|
||||
linkLabel.updateUnderline(table, row)
|
||||
if (rowSelected || TableHoverListener.getHoveredRow(table) == row) {
|
||||
versionPanel.add(linkLabel)
|
||||
}
|
||||
}
|
||||
else if (value is InstalledPackage && value.nextVersion != null && value.canBeUpdated) {
|
||||
@NlsSafe val updateLink = value.instance.version + " -> " + value.nextVersion.presentableText
|
||||
linkLabel.text = updateLink
|
||||
linkLabel.updateUnderline(table, row)
|
||||
versionPanel.add(linkLabel)
|
||||
}
|
||||
else {
|
||||
@NlsSafe val version = (value as InstalledPackage).instance.version
|
||||
versionLabel.text = version
|
||||
versionPanel.add(versionLabel)
|
||||
}
|
||||
return versionPanel
|
||||
}
|
||||
|
||||
// package name column
|
||||
val currentPackage = value as DisplayablePackage
|
||||
|
||||
namePanel.background = JBUI.CurrentTheme.Table.background(rowSelected, tableFocused)
|
||||
namePanel.foreground = JBUI.CurrentTheme.Table.foreground(rowSelected, tableFocused)
|
||||
|
||||
nameLabel.text = currentPackage.name
|
||||
nameLabel.foreground = JBUI.CurrentTheme.Label.foreground()
|
||||
return namePanel
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun JLabel.updateUnderline(table: JTable, currentRow: Int) {
|
||||
val hoveredRow = TableHoverListener.getHoveredRow(table)
|
||||
val hoveredColumn = (table as PyPackagesTable<*>).hoveredColumn
|
||||
val underline = if (hoveredRow == currentRow && hoveredColumn == 1) TextAttribute.UNDERLINE_ON else -1
|
||||
|
||||
val attributes = font.attributes as MutableMap<TextAttribute, Any>
|
||||
attributes[TextAttribute.UNDERLINE] = underline
|
||||
attributes[TextAttribute.LIGATURES] = TextAttribute.LIGATURES_ON
|
||||
font = font.deriveFont(attributes)
|
||||
}
|
||||
}
|
||||
@@ -1,462 +0,0 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python.packaging.toolwindow
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.ListPopup
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.ui.DoubleClickListener
|
||||
import com.intellij.ui.PopupHandler
|
||||
import com.intellij.ui.SideBorder
|
||||
import com.intellij.ui.awt.RelativePoint
|
||||
import com.intellij.ui.hover.TableHoverListener
|
||||
import com.intellij.ui.table.JBTable
|
||||
import com.intellij.util.ui.*
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.repository.PyPackageRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.*
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.awt.font.TextAttribute
|
||||
import javax.swing.*
|
||||
import javax.swing.table.DefaultTableCellRenderer
|
||||
import javax.swing.table.TableCellRenderer
|
||||
|
||||
|
||||
internal class PyPackagesTable<T : DisplayablePackage>(project: Project,
|
||||
model: ListTableModel<T>,
|
||||
tablesView: PyPackagingTablesView,
|
||||
controller: PyPackagingToolWindowPanel) : JBTable(model) {
|
||||
private var lastSelectedRow = -1
|
||||
internal var hoveredColumn = -1
|
||||
init {
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
setShowGrid(false)
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
|
||||
val column = columnModel.getColumn(1)
|
||||
column.minWidth = 130
|
||||
column.maxWidth = 130
|
||||
column.resizable = false
|
||||
border = SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.BOTTOM)
|
||||
rowHeight = 20
|
||||
|
||||
initCrossNavigation(service, tablesView)
|
||||
|
||||
val hoverListener = object : TableHoverListener() {
|
||||
override fun onHover(table: JTable, row: Int, column: Int) {
|
||||
hoveredColumn = column
|
||||
if (column == 1) {
|
||||
table.repaint(table.getCellRect(row, column, true))
|
||||
val currentPackage = items[row]
|
||||
if (currentPackage is InstallablePackage
|
||||
|| (currentPackage is InstalledPackage && currentPackage.canBeUpdated)) {
|
||||
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
|
||||
return
|
||||
}
|
||||
}
|
||||
cursor = Cursor.getDefaultCursor()
|
||||
}
|
||||
}
|
||||
hoverListener.addTo(this)
|
||||
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (e.clickCount != 1 || columnAtPoint(e.point) != 1) return // double click or click on package name column, nothing to be done
|
||||
val hoveredRow = TableHoverListener.getHoveredRow(this@PyPackagesTable)
|
||||
val selectedPackage = this@PyPackagesTable.items[hoveredRow]
|
||||
|
||||
if (selectedPackage is InstallablePackage) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val details = service.detailsForPackage(selectedPackage)
|
||||
withContext(Dispatchers.Main) {
|
||||
createAvailableVersionsPopup(selectedPackage, details, project, controller).show(RelativePoint(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selectedPackage is InstalledPackage && selectedPackage.canBeUpdated) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val specification = selectedPackage.repository.createPackageSpecification(selectedPackage.name,
|
||||
selectedPackage.nextVersion!!.presentableText)
|
||||
project.service<PyPackagingToolWindowService>().updatePackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
selectionModel.addListSelectionListener {
|
||||
if (selectedRow != -1 && selectedRow != lastSelectedRow) {
|
||||
lastSelectedRow = selectedRow
|
||||
tablesView.requestSelection(this)
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg !is ExpandResultNode) controller.packageSelected(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
object : DoubleClickListener() {
|
||||
override fun onDoubleClick(event: MouseEvent): Boolean {
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg is ExpandResultNode) loadMoreItems(service, pkg)
|
||||
return true
|
||||
}
|
||||
}.installOn(this)
|
||||
|
||||
PopupHandler.installPopupMenu(this, DefaultActionGroup(object : DumbAwareAction({
|
||||
val pkg = if (selectedRow >= 0) model.items[selectedRow] else null
|
||||
if (pkg is InstalledPackage) {
|
||||
message("python.toolwindow.packages.delete.package")
|
||||
}
|
||||
else {
|
||||
message("python.toolwindow.packages.install.link")
|
||||
}
|
||||
}) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
controller.packagingScope.launch(Dispatchers.Main) {
|
||||
if (selectedRow == -1) return@launch
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg is InstalledPackage) {
|
||||
withContext(Dispatchers.IO) {
|
||||
service.deletePackage(pkg)
|
||||
}
|
||||
}
|
||||
else if (pkg is InstallablePackage) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val details = service.detailsForPackage(pkg)
|
||||
withContext(Dispatchers.Main) {
|
||||
createAvailableVersionsPopup(pkg as InstallablePackage, details, project, controller).show(RelativePoint(e.inputEvent as MouseEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, object : DumbAwareAction({
|
||||
val pkg = if (selectedRow >= 0) model.items[selectedRow] else null
|
||||
if (pkg is InstalledPackage && pkg.canBeUpdated) {
|
||||
message("python.toolwindow.packages.update.package")
|
||||
}
|
||||
else {
|
||||
""
|
||||
}
|
||||
}) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
controller.packagingScope.launch(Dispatchers.Main) {
|
||||
if (selectedRow == -1) return@launch
|
||||
val pkg = model.items[selectedRow]
|
||||
if (pkg is InstalledPackage && pkg.canBeUpdated) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val specification = pkg.repository.createPackageSpecification(pkg.name, pkg.nextVersion!!.presentableText)
|
||||
service.updatePackage(specification)
|
||||
}
|
||||
}
|
||||
else if (pkg is InstallablePackage) {
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
val details = service.detailsForPackage(pkg)
|
||||
withContext(Dispatchers.Main) {
|
||||
createAvailableVersionsPopup(pkg as InstallablePackage, details, project, controller).show(RelativePoint(e.inputEvent as MouseEvent))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}), "PackagePopup")
|
||||
}
|
||||
|
||||
private fun createAvailableVersionsPopup(selectedPackage: InstallablePackage, details: PythonPackageDetails, project: Project, controller: PyPackagingToolWindowPanel): ListPopup {
|
||||
return JBPopupFactory.getInstance().createListPopup(object : BaseListPopupStep<String>(null, details.availableVersions) {
|
||||
override fun onChosen(selectedValue: String?, finalChoice: Boolean): PopupStep<*>? {
|
||||
return doFinalStep {
|
||||
val specification = selectedPackage.repository.createPackageSpecification(selectedPackage.name, selectedValue)
|
||||
controller.packagingScope.launch(Dispatchers.IO) {
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 8)
|
||||
}
|
||||
|
||||
private fun initCrossNavigation(service: PyPackagingToolWindowService, tablesView: PyPackagingTablesView) {
|
||||
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ENTER_ACTION)
|
||||
actionMap.put(ENTER_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
val index = selectedRow
|
||||
val selectedItem = items[selectedRow]
|
||||
|
||||
if (selectedItem is ExpandResultNode) {
|
||||
loadMoreItems(service, selectedItem)
|
||||
}
|
||||
setRowSelectionInterval(index, index)
|
||||
}
|
||||
})
|
||||
|
||||
val nextRowAction = actionMap[NEXT_ROW_ACTION]
|
||||
actionMap.put(NEXT_ROW_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
|
||||
if (selectedRow + 1 == items.size) {
|
||||
tablesView.selectNextFrom(this@PyPackagesTable)
|
||||
}
|
||||
else {
|
||||
nextRowAction.actionPerformed(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val prevRowAction = actionMap[PREVIOUS_ROW_ACTION]
|
||||
actionMap.put(PREVIOUS_ROW_ACTION, object : AbstractAction() {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
if (selectedRow == -1) return
|
||||
|
||||
if (selectedRow == 0) {
|
||||
tablesView.selectPreviousOf(this@PyPackagesTable)
|
||||
}
|
||||
else {
|
||||
prevRowAction.actionPerformed(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun loadMoreItems(service: PyPackagingToolWindowService, node: ExpandResultNode) {
|
||||
val result = service.getMoreResultsForRepo(node.repository, items.size - 1)
|
||||
items = items.dropLast(1) + (result.packages as List<T>)
|
||||
if (result.moreItems > 0) {
|
||||
node.more = result.moreItems
|
||||
items = items + listOf(node) as List<T>
|
||||
}
|
||||
this@PyPackagesTable.revalidate()
|
||||
this@PyPackagesTable.repaint()
|
||||
}
|
||||
|
||||
override fun getCellRenderer(row: Int, column: Int): TableCellRenderer {
|
||||
return PyPaginationAwareRenderer()
|
||||
}
|
||||
|
||||
override fun clearSelection() {
|
||||
lastSelectedRow = -1
|
||||
super.clearSelection()
|
||||
}
|
||||
|
||||
internal fun addRows(rows: List<T>) = listModel.addRows(rows)
|
||||
internal fun removeRow(index: Int) = listModel.removeRow(index)
|
||||
internal fun insertRow(index: Int, pkg: T) = listModel.insertRow(index, pkg)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val listModel: ListTableModel<T>
|
||||
get() = model as ListTableModel<T>
|
||||
|
||||
var items: List<T>
|
||||
get() = listModel.items
|
||||
set(value) { listModel.items = value.toMutableList() }
|
||||
|
||||
companion object {
|
||||
private const val NEXT_ROW_ACTION = "selectNextRow"
|
||||
private const val PREVIOUS_ROW_ACTION = "selectPreviousRow"
|
||||
private const val ENTER_ACTION = "ENTER"
|
||||
}
|
||||
}
|
||||
|
||||
internal class PyPackagesTableModel<T : DisplayablePackage> : ListTableModel<T>() {
|
||||
override fun isCellEditable(rowIndex: Int, columnIndex: Int): Boolean = false
|
||||
override fun getColumnCount(): Int = 2
|
||||
override fun getColumnName(column: Int): String = column.toString()
|
||||
override fun getColumnClass(columnIndex: Int): Class<*> = DisplayablePackage::class.java
|
||||
|
||||
override fun getValueAt(rowIndex: Int, columnIndex: Int): Any? = items[rowIndex]
|
||||
}
|
||||
|
||||
fun boxPanel(init: JPanel.() -> Unit) = object : JPanel() {
|
||||
init {
|
||||
layout = BoxLayout(this, BoxLayout.X_AXIS)
|
||||
alignmentX = LEFT_ALIGNMENT
|
||||
init()
|
||||
}
|
||||
}
|
||||
|
||||
fun borderPanel(init: JPanel.() -> Unit) = object : JPanel() {
|
||||
init {
|
||||
layout = BorderLayout(0, 0)
|
||||
init()
|
||||
}
|
||||
}
|
||||
|
||||
fun headerPanel(label: JLabel, component: JComponent?) = object : JPanel() {
|
||||
init {
|
||||
background = UIUtil.getLabelBackground()
|
||||
layout = BorderLayout()
|
||||
border = BorderFactory.createCompoundBorder(SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.BOTTOM), JBUI.Borders.empty(0, 5))
|
||||
preferredSize = Dimension(preferredSize.width, 25)
|
||||
minimumSize = Dimension(minimumSize.width, 25)
|
||||
maximumSize = Dimension(maximumSize.width, 25)
|
||||
|
||||
add(label, BorderLayout.WEST)
|
||||
if (component != null) {
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent?) {
|
||||
component.isVisible = !component.isVisible
|
||||
label.icon = if (component.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PyPaginationAwareRenderer : DefaultTableCellRenderer() {
|
||||
private val nameLabel = JLabel().apply { border = JBUI.Borders.empty(0, 12) }
|
||||
private val versionLabel = JLabel().apply { border = JBUI.Borders.emptyRight(12) }
|
||||
private val linkLabel = JLabel(message("python.toolwindow.packages.install.link")).apply {
|
||||
border = JBUI.Borders.emptyRight(12)
|
||||
foreground = JBUI.CurrentTheme.Link.Foreground.ENABLED
|
||||
}
|
||||
|
||||
private val namePanel = JPanel().apply {
|
||||
layout = BoxLayout(this, BoxLayout.X_AXIS)
|
||||
border = JBUI.Borders.empty()
|
||||
add(nameLabel)
|
||||
}
|
||||
|
||||
private val versionPanel = boxPanel {
|
||||
border = JBUI.Borders.emptyRight(12)
|
||||
add(versionLabel)
|
||||
}
|
||||
|
||||
override fun getTableCellRendererComponent(table: JTable,
|
||||
value: Any?,
|
||||
isSelected: Boolean,
|
||||
hasFocus: Boolean,
|
||||
row: Int,
|
||||
column: Int): Component {
|
||||
val rowSelected = table.selectedRow == row
|
||||
val tableFocused = table.hasFocus()
|
||||
|
||||
if (value is ExpandResultNode) {
|
||||
if (column == 1) {
|
||||
versionPanel.removeAll()
|
||||
return versionPanel
|
||||
}
|
||||
else {
|
||||
nameLabel.text = message("python.toolwindow.packages.load.more", value.more)
|
||||
nameLabel.foreground = UIUtil.getContextHelpForeground()
|
||||
return namePanel
|
||||
}
|
||||
}
|
||||
|
||||
// version column
|
||||
if (column == 1) {
|
||||
versionPanel.background = JBUI.CurrentTheme.Table.background(rowSelected, tableFocused)
|
||||
versionPanel.foreground = JBUI.CurrentTheme.Table.foreground(rowSelected, tableFocused)
|
||||
versionPanel.removeAll()
|
||||
|
||||
if (value is InstallablePackage) {
|
||||
linkLabel.text = message("python.toolwindow.packages.install.link")
|
||||
linkLabel.updateUnderline(table, row)
|
||||
if (rowSelected || TableHoverListener.getHoveredRow(table) == row) {
|
||||
versionPanel.add(linkLabel)
|
||||
}
|
||||
}
|
||||
else if (value is InstalledPackage && value.nextVersion != null && value.canBeUpdated) {
|
||||
@NlsSafe val updateLink = value.instance.version + " -> " + value.nextVersion.presentableText
|
||||
linkLabel.text = updateLink
|
||||
linkLabel.updateUnderline(table, row)
|
||||
versionPanel.add(linkLabel)
|
||||
}
|
||||
else {
|
||||
@NlsSafe val version = (value as InstalledPackage).instance.version
|
||||
versionLabel.text = version
|
||||
versionPanel.add(versionLabel)
|
||||
}
|
||||
return versionPanel
|
||||
}
|
||||
|
||||
// package name column
|
||||
val currentPackage = value as DisplayablePackage
|
||||
|
||||
namePanel.background = JBUI.CurrentTheme.Table.background(rowSelected, tableFocused)
|
||||
namePanel.foreground = JBUI.CurrentTheme.Table.foreground(rowSelected, tableFocused)
|
||||
|
||||
nameLabel.text = currentPackage.name
|
||||
nameLabel.foreground = JBUI.CurrentTheme.Label.foreground()
|
||||
return namePanel
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun JLabel.updateUnderline(table: JTable, currentRow: Int) {
|
||||
val hoveredRow = TableHoverListener.getHoveredRow(table)
|
||||
val hoveredColumn = (table as PyPackagesTable<*>).hoveredColumn
|
||||
val underline = if (hoveredRow == currentRow && hoveredColumn == 1) TextAttribute.UNDERLINE_ON else -1
|
||||
|
||||
val attributes = font.attributes as MutableMap<TextAttribute, Any>
|
||||
attributes[TextAttribute.UNDERLINE] = underline
|
||||
attributes[TextAttribute.LIGATURES] = TextAttribute.LIGATURES_ON
|
||||
font = font.deriveFont(attributes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class PyPackagingTableGroup<T: DisplayablePackage>(val repository: PyPackageRepository, val table: PyPackagesTable<T>) {
|
||||
@NlsSafe val name: String = repository.name!!
|
||||
|
||||
private var expanded = false
|
||||
private val label = JLabel(name).apply { icon = AllIcons.General.ArrowDown }
|
||||
private val header: JPanel = headerPanel(label, table)
|
||||
private var itemsCount: Int? = null
|
||||
|
||||
|
||||
internal var items: List<T>
|
||||
get() = table.items
|
||||
set(value) {
|
||||
table.items = value
|
||||
}
|
||||
|
||||
fun collapse() {
|
||||
expanded = false
|
||||
table.isVisible = false
|
||||
label.icon = if (table.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
|
||||
fun expand() {
|
||||
expanded = true
|
||||
table.isVisible = true
|
||||
label.icon = if (table.isVisible) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
|
||||
fun updateHeaderText(newItemCount: Int?) {
|
||||
itemsCount = newItemCount
|
||||
label.text = if (itemsCount == null) name else message("python.toolwindow.packages.custom.repo.searched", name, itemsCount)
|
||||
}
|
||||
|
||||
fun addTo(panel: JPanel) {
|
||||
panel.add(header)
|
||||
panel.add(table)
|
||||
}
|
||||
|
||||
fun replace(row: Int, pkg: T) {
|
||||
table.removeRow(row)
|
||||
table.insertRow(row, pkg)
|
||||
}
|
||||
|
||||
fun removeFrom(panel: JPanel) {
|
||||
panel.remove(header)
|
||||
panel.remove(table)
|
||||
}
|
||||
|
||||
fun repaint() {
|
||||
table.invalidate()
|
||||
table.repaint()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.jetbrains.python.packaging.utils
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
class PyPackageCoroutine(val project: Project, val coroutineScope: CoroutineScope) {
|
||||
val ioScope = coroutineScope.childScope("Jupyter IO scope", context = Dispatchers.IO)
|
||||
|
||||
companion object {
|
||||
fun launch(project: Project, context: CoroutineContext = Dispatchers.Main, body: suspend CoroutineScope.() -> Unit) =
|
||||
project.service<PyPackageCoroutine>().coroutineScope.launch(context, block = body)
|
||||
|
||||
fun getIoScope(project: Project): CoroutineScope = project.service<PyPackageCoroutine>().ioScope
|
||||
fun getScope(project: Project): CoroutineScope = project.service<PyPackageCoroutine>().coroutineScope
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user