mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
PY-75464 PyPackages(refactor): Extract PyPackagesModuleController abd PyPackageCustomInstallComponents
GitOrigin-RevId: 86da1574f329c34604d484bd0663a39b9a59a111
This commit is contained in:
committed by
intellij-monorepo-bot
parent
04a69878f7
commit
016978c8a8
@@ -12,4 +12,6 @@ class PyPackagesToolWindowModuleAttachListener : ModuleAttachListener {
|
||||
module.project.service<PyPackagingToolWindowService>().moduleAttached()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -9,52 +9,42 @@ import com.intellij.openapi.actionSystem.DataSink
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.modules
|
||||
import com.intellij.openapi.ui.SimpleToolWindowPanel
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
|
||||
import com.intellij.ui.OnePixelSplitter
|
||||
import com.intellij.ui.ScrollPaneFactory
|
||||
import com.intellij.ui.SearchTextField
|
||||
import com.intellij.ui.SideBorder
|
||||
import com.intellij.ui.components.*
|
||||
import com.intellij.ui.dsl.builder.*
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.ui.components.JBPanelWithEmptyText
|
||||
import com.intellij.util.ui.NamedColorUtil
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.icons.PythonIcons
|
||||
import com.jetbrains.python.packaging.common.PythonLocalPackageSpecification
|
||||
import com.jetbrains.python.packaging.common.PythonVcsPackageSpecification
|
||||
import com.jetbrains.python.packaging.toolwindow.details.PyPackageDescriptionController
|
||||
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.modules.PyPackagesModuleController
|
||||
import com.jetbrains.python.packaging.toolwindow.packages.PyPackageSearchTextField
|
||||
import com.jetbrains.python.packaging.toolwindow.packages.PyPackagesListController
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackageCustomInstallComponents
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import javax.swing.*
|
||||
import javax.swing.event.ListSelectionListener
|
||||
import javax.swing.BorderFactory
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindowPanel(false, true), Disposable {
|
||||
private val moduleController = PyPackagesModuleController(project)
|
||||
|
||||
private val descriptionController = PyPackageDescriptionController(project).also {
|
||||
Disposer.register(this, it)
|
||||
}
|
||||
@@ -64,7 +54,7 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
}
|
||||
|
||||
|
||||
internal val packagingScope = PyPackageCoroutine.getIoScope(project)
|
||||
private val packagingScope = PyPackageCoroutine.getIoScope(project)
|
||||
|
||||
private val searchTextField: SearchTextField = PyPackageSearchTextField(project)
|
||||
|
||||
@@ -83,12 +73,6 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
}
|
||||
|
||||
|
||||
private val fromVcsText: String
|
||||
get() = message("python.toolwindow.packages.add.package.from.vcs")
|
||||
private val fromDiscText: String
|
||||
get() = message("python.toolwindow.packages.add.package.from.disc")
|
||||
|
||||
|
||||
init {
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
Disposer.register(service, this)
|
||||
@@ -130,19 +114,6 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
actionToolbar.targetComponent = this
|
||||
|
||||
|
||||
val installFromLocationLink = DropDownLink(message("python.toolwindow.packages.add.package.action"),
|
||||
listOf(fromVcsText, fromDiscText)) {
|
||||
val specification = when (it) {
|
||||
fromDiscText -> showInstallFromDiscDialog(service)
|
||||
fromVcsText -> showInstallFromVcsDialog(service)
|
||||
else -> throw IllegalStateException("Unknown operation")
|
||||
}
|
||||
if (specification != null) {
|
||||
packagingScope.launch {
|
||||
service.installPackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainPanel = PyPackagesUiComponents.borderPanel {
|
||||
val topToolbar = PyPackagesUiComponents.boxPanel {
|
||||
@@ -153,7 +124,7 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
add(searchTextField)
|
||||
actionToolbar.component.maximumSize = Dimension(70, actionToolbar.component.maximumSize.height)
|
||||
add(actionToolbar.component)
|
||||
add(installFromLocationLink)
|
||||
add(PyPackageCustomInstallComponents.createInstallFromLocationLink(project))
|
||||
}
|
||||
add(topToolbar, BorderLayout.NORTH)
|
||||
add(splitter!!, BorderLayout.CENTER)
|
||||
@@ -162,121 +133,20 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
}
|
||||
|
||||
private fun createLeftPanel(service: PyPackagingToolWindowService): JComponent {
|
||||
if (project.modules.size == 1) return packageListController.component
|
||||
if (project.modules.size == 1)
|
||||
return packageListController.component
|
||||
|
||||
val left = JPanel(BorderLayout()).apply {
|
||||
border = BorderFactory.createEmptyBorder()
|
||||
}
|
||||
|
||||
val modulePanel = JPanel(FlowLayout(FlowLayout.LEFT, 0, 0)).apply {
|
||||
border = SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.RIGHT)
|
||||
maximumSize = Dimension(80, maximumSize.height)
|
||||
minimumSize = Dimension(50, minimumSize.height)
|
||||
}
|
||||
|
||||
val moduleList = JBList(ModuleManager.getInstance(project).modules.toList().sortedBy { it.name }).apply {
|
||||
selectionMode = ListSelectionModel.SINGLE_SELECTION
|
||||
border = JBUI.Borders.empty()
|
||||
|
||||
val itemRenderer = JBLabel("", PythonIcons.Python.PythonClosed, JLabel.LEFT).apply {
|
||||
border = JBUI.Borders.empty(0, 10)
|
||||
}
|
||||
cellRenderer = ListCellRenderer { _, value, _, _, _ -> itemRenderer.text = value.name; itemRenderer }
|
||||
|
||||
addListSelectionListener(ListSelectionListener { e ->
|
||||
if (e.valueIsAdjusting) return@ListSelectionListener
|
||||
val selectedModule = this@apply.selectedValue
|
||||
val sdk = selectedModule.pythonSdk ?: return@ListSelectionListener
|
||||
packagingScope.launch {
|
||||
service.initForSdk(sdk)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val fileListener = object : FileEditorManagerListener {
|
||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||
if (project.modules.size > 1) {
|
||||
val newFile = event.newFile ?: return
|
||||
val module = ModuleUtilCore.findModuleForFile(newFile, project)
|
||||
packagingScope.launch {
|
||||
val index = (moduleList.model as DefaultListModel<Module>).indexOf(module)
|
||||
moduleList.selectionModel.setSelectionInterval(index, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
service.project.messageBus
|
||||
.connect(service)
|
||||
.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, fileListener)
|
||||
|
||||
modulePanel.add(moduleList)
|
||||
left.add(ScrollPaneFactory.createScrollPane(modulePanel, true), BorderLayout.WEST)
|
||||
left.add(moduleController.component, BorderLayout.WEST)
|
||||
left.add(packageListController.component, BorderLayout.CENTER)
|
||||
|
||||
return left
|
||||
}
|
||||
|
||||
private fun showInstallFromVcsDialog(service: PyPackagingToolWindowService): PythonVcsPackageSpecification? {
|
||||
var editable = false
|
||||
var link = ""
|
||||
val systems = listOf(message("python.toolwindow.packages.add.package.vcs.git"),
|
||||
message("python.toolwindow.packages.add.package.vcs.svn"),
|
||||
message("python.toolwindow.packages.add.package.vcs.hg"),
|
||||
message("python.toolwindow.packages.add.package.vcs.bzr"))
|
||||
var vcs = systems.first()
|
||||
|
||||
val panel = panel {
|
||||
row {
|
||||
comboBox(systems)
|
||||
.bindItem({ vcs }, { vcs = it!! })
|
||||
textField()
|
||||
.columns(COLUMNS_MEDIUM)
|
||||
.bindText({ link }, { link = it })
|
||||
.align(AlignX.FILL)
|
||||
}
|
||||
row {
|
||||
checkBox(message("python.toolwindow.packages.add.package.as.editable"))
|
||||
.bindSelected({ editable }, { editable = it })
|
||||
}
|
||||
}
|
||||
|
||||
val shouldInstall = dialog(message("python.toolwindow.packages.add.package.dialog.title"), panel, project = service.project, resizable = true).showAndGet()
|
||||
if (shouldInstall) {
|
||||
val prefix = when (vcs) {
|
||||
message("python.toolwindow.packages.add.package.vcs.git") -> "git+"
|
||||
message("python.toolwindow.packages.add.package.vcs.svn") -> "svn+"
|
||||
message("python.toolwindow.packages.add.package.vcs.hg") -> "hg+"
|
||||
message("python.toolwindow.packages.add.package.vcs.bzr") -> "bzr+"
|
||||
else -> throw IllegalStateException("Unknown VCS")
|
||||
}
|
||||
|
||||
return PythonVcsPackageSpecification(link, link, prefix, editable)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun showInstallFromDiscDialog(service: PyPackagingToolWindowService): PythonLocalPackageSpecification? {
|
||||
var editable = false
|
||||
|
||||
val textField = TextFieldWithBrowseButton().apply {
|
||||
addBrowseFolderListener(message("python.toolwindow.packages.add.package.path.selector"), "", service.project,
|
||||
FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor())
|
||||
}
|
||||
val panel = panel {
|
||||
row(message("python.toolwindow.packages.add.package.path")) {
|
||||
cell(textField)
|
||||
.columns(COLUMNS_MEDIUM)
|
||||
.align(AlignX.FILL)
|
||||
}
|
||||
row {
|
||||
checkBox(message("python.toolwindow.packages.add.package.as.editable"))
|
||||
.bindSelected({ editable }, { editable = it })
|
||||
}
|
||||
}
|
||||
|
||||
val shouldInstall = dialog(message("python.toolwindow.packages.add.package.dialog.title"), panel, project = service.project, resizable = true).showAndGet()
|
||||
return if (shouldInstall) PythonLocalPackageSpecification(textField.text, textField.text, editable) else null
|
||||
}
|
||||
|
||||
private fun trackOrientation(service: PyPackagingToolWindowService) {
|
||||
service.project.messageBus.connect(service).subscribe(ToolWindowManagerListener.TOPIC, object : ToolWindowManagerListener {
|
||||
@@ -347,9 +217,6 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
companion object {
|
||||
private const val HORIZONTAL_SPLITTER_KEY = "Python.PackagingToolWindow.Horizontal"
|
||||
private const val VERTICAL_SPLITTER_KEY = "Python.PackagingToolWindow.Vertical"
|
||||
|
||||
val NO_DESCRIPTION: String
|
||||
get() = message("python.toolwindow.packages.no.description.placeholder")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.jetbrains.python.PythonHelper
|
||||
import com.jetbrains.python.PythonHelpersLocator
|
||||
import com.jetbrains.python.packaging.PyPIPackageRanking
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowPanel.Companion.NO_DESCRIPTION
|
||||
import com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory
|
||||
import com.jetbrains.python.run.applyHelperPackageToPythonPath
|
||||
import com.jetbrains.python.run.buildTargetedCommandLine
|
||||
@@ -108,4 +107,8 @@ class PyPackageDetailsHtmlRender(val project: Project, val currentSdk: Sdk?) {
|
||||
}
|
||||
|
||||
private fun wrapHtml(html: String): String = "<html><head></head><body><p>$html</p></body></html>"
|
||||
|
||||
private val NO_DESCRIPTION: String
|
||||
get() = message("python.toolwindow.packages.no.description.placeholder")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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.modules
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.modules
|
||||
import com.intellij.ui.ScrollPaneFactory
|
||||
import com.intellij.ui.SideBorder
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.JBList
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.NamedColorUtil
|
||||
import com.jetbrains.python.icons.PythonIcons
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import kotlinx.coroutines.launch
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import javax.swing.*
|
||||
import javax.swing.event.ListSelectionListener
|
||||
|
||||
class PyPackagesModuleController(val project: Project) {
|
||||
val packagingScope = PyPackageCoroutine.getIoScope(project)
|
||||
val service
|
||||
get() = project.service<PyPackagingToolWindowService>()
|
||||
|
||||
val moduleList = JBList(ModuleManager.getInstance(project).modules.toList().sortedBy { it.name }).apply {
|
||||
selectionMode = ListSelectionModel.SINGLE_SELECTION
|
||||
border = JBUI.Borders.empty()
|
||||
|
||||
val itemRenderer = JBLabel("", PythonIcons.Python.PythonClosed, JLabel.LEFT).apply {
|
||||
border = JBUI.Borders.empty(0, 10)
|
||||
}
|
||||
cellRenderer = ListCellRenderer { _, value, _, _, _ -> itemRenderer.text = value.name; itemRenderer }
|
||||
|
||||
addListSelectionListener(ListSelectionListener { e ->
|
||||
if (e.valueIsAdjusting) return@ListSelectionListener
|
||||
val selectedModule = this@apply.selectedValue
|
||||
val sdk = selectedModule.pythonSdk ?: return@ListSelectionListener
|
||||
packagingScope.launch {
|
||||
service.initForSdk(sdk)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private val modulePanel = JPanel(FlowLayout(FlowLayout.LEFT, 0, 0)).apply {
|
||||
border = SideBorder(NamedColorUtil.getBoundsColor(), SideBorder.RIGHT)
|
||||
maximumSize = Dimension(80, maximumSize.height)
|
||||
minimumSize = Dimension(50, minimumSize.height)
|
||||
}.also {
|
||||
it.add(moduleList)
|
||||
}
|
||||
|
||||
val component = ScrollPaneFactory.createScrollPane(modulePanel, true)
|
||||
|
||||
val fileListener = object : FileEditorManagerListener {
|
||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||
if (project.modules.size > 1) {
|
||||
val newFile = event.newFile ?: return
|
||||
val module = ModuleUtilCore.findModuleForFile(newFile, project)
|
||||
packagingScope.launch {
|
||||
val index = (moduleList.model as DefaultListModel<Module>).indexOf(module)
|
||||
moduleList.selectionModel.setSelectionInterval(index, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
project.messageBus
|
||||
.connect(service)
|
||||
.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, fileListener)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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.components.service
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.ui.components.DropDownLink
|
||||
import com.intellij.ui.components.dialog
|
||||
import com.intellij.ui.dsl.builder.*
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.common.PythonLocalPackageSpecification
|
||||
import com.jetbrains.python.packaging.common.PythonVcsPackageSpecification
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
object PyPackageCustomInstallComponents {
|
||||
private val fromVcsText: String
|
||||
get() = message("python.toolwindow.packages.add.package.from.vcs")
|
||||
private val fromDiscText: String
|
||||
get() = message("python.toolwindow.packages.add.package.from.disc")
|
||||
|
||||
fun createInstallFromLocationLink(project: Project): DropDownLink<@Nls String> {
|
||||
return DropDownLink(message("python.toolwindow.packages.add.package.action"),
|
||||
listOf(fromVcsText, fromDiscText)) {
|
||||
val service = project.service<PyPackagingToolWindowService>()
|
||||
|
||||
val specification = when (it) {
|
||||
fromDiscText -> showInstallFromDiscDialog(service)
|
||||
fromVcsText -> showInstallFromVcsDialog(service)
|
||||
else -> throw IllegalStateException("Unknown operation")
|
||||
}
|
||||
if (specification != null) {
|
||||
PyPackageCoroutine.launch(project) {
|
||||
service.installPackage(specification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun showInstallFromVcsDialog(service: PyPackagingToolWindowService): PythonVcsPackageSpecification? {
|
||||
var editable = false
|
||||
var link = ""
|
||||
val systems = listOf(message("python.toolwindow.packages.add.package.vcs.git"),
|
||||
message("python.toolwindow.packages.add.package.vcs.svn"),
|
||||
message("python.toolwindow.packages.add.package.vcs.hg"),
|
||||
message("python.toolwindow.packages.add.package.vcs.bzr"))
|
||||
var vcs = systems.first()
|
||||
|
||||
val panel = panel {
|
||||
row {
|
||||
comboBox(systems)
|
||||
.bindItem({ vcs }, { vcs = it!! })
|
||||
textField()
|
||||
.columns(COLUMNS_MEDIUM)
|
||||
.bindText({ link }, { link = it })
|
||||
.align(AlignX.FILL)
|
||||
}
|
||||
row {
|
||||
checkBox(message("python.toolwindow.packages.add.package.as.editable"))
|
||||
.bindSelected({ editable }, { editable = it })
|
||||
}
|
||||
}
|
||||
|
||||
val shouldInstall = dialog(message("python.toolwindow.packages.add.package.dialog.title"), panel, project = service.project, resizable = true).showAndGet()
|
||||
if (shouldInstall) {
|
||||
val prefix = when (vcs) {
|
||||
message("python.toolwindow.packages.add.package.vcs.git") -> "git+"
|
||||
message("python.toolwindow.packages.add.package.vcs.svn") -> "svn+"
|
||||
message("python.toolwindow.packages.add.package.vcs.hg") -> "hg+"
|
||||
message("python.toolwindow.packages.add.package.vcs.bzr") -> "bzr+"
|
||||
else -> throw IllegalStateException("Unknown VCS")
|
||||
}
|
||||
|
||||
return PythonVcsPackageSpecification(link, link, prefix, editable)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun showInstallFromDiscDialog(service: PyPackagingToolWindowService): PythonLocalPackageSpecification? {
|
||||
var editable = false
|
||||
|
||||
val textField = TextFieldWithBrowseButton().apply {
|
||||
addBrowseFolderListener(message("python.toolwindow.packages.add.package.path.selector"), "", service.project,
|
||||
FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor())
|
||||
}
|
||||
val panel = panel {
|
||||
row(message("python.toolwindow.packages.add.package.path")) {
|
||||
cell(textField)
|
||||
.columns(COLUMNS_MEDIUM)
|
||||
.align(AlignX.FILL)
|
||||
}
|
||||
row {
|
||||
checkBox(message("python.toolwindow.packages.add.package.as.editable"))
|
||||
.bindSelected({ editable }, { editable = it })
|
||||
}
|
||||
}
|
||||
|
||||
val shouldInstall = dialog(message("python.toolwindow.packages.add.package.dialog.title"), panel, project = service.project, resizable = true).showAndGet()
|
||||
return if (shouldInstall) PythonLocalPackageSpecification(textField.text, textField.text, editable) else null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user