mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-58889 New UI for Python Run configurations
Partial implementation of PY-44688 GitOrigin-RevId: 686c48a6f2649dfebcd079f414cce19559374032
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2a110d7272
commit
308f9110d7
@@ -57,6 +57,9 @@
|
||||
<applicationService serviceInterface="com.jetbrains.python.run.PyCommonOptionsFormFactory"
|
||||
serviceImplementation="com.jetbrains.python.PyIdeCommonOptionsFormFactory"/>
|
||||
|
||||
<applicationService serviceInterface="com.jetbrains.python.run.PyCommonFragmentsBuilder"
|
||||
serviceImplementation="com.jetbrains.python.PyIdeCommonFragmentsBuilder"/>
|
||||
|
||||
<!-- Console -->
|
||||
<toolWindow id="Python Console" anchor="bottom" icon="PythonIcons.Python.PythonConsoleToolWindow" canCloseContents="true"
|
||||
factoryClass="com.jetbrains.python.console.PythonConsoleToolWindowFactory" secondary="false"/>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python
|
||||
|
||||
import com.intellij.application.options.ModulesComboBox
|
||||
import com.intellij.execution.ui.CommandLinePanel
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.execution.ui.SettingsEditorFragmentType
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfiguration
|
||||
import com.jetbrains.python.run.PyCommonFragmentsBuilder
|
||||
import com.jetbrains.python.run.configuration.PyPathMappingsEditorFragment
|
||||
import com.jetbrains.python.run.configuration.PySdkComboBox
|
||||
import com.jetbrains.python.sdk.PySdkListCellRenderer
|
||||
import java.awt.event.ItemEvent
|
||||
|
||||
class PyIdeCommonFragmentsBuilder : PyCommonFragmentsBuilder() {
|
||||
|
||||
override fun <T : AbstractPythonRunConfiguration<*>> createEnvironmentFragments(fragments: MutableList<SettingsEditorFragment<T, *>>,
|
||||
config: T) {
|
||||
val modules = ModuleManager.getInstance(config.project).modules
|
||||
var modulesComboBox: ModulesComboBox? = null
|
||||
if (modules.size > 1) {
|
||||
modulesComboBox = ModulesComboBox()
|
||||
val modulesFragment = SettingsEditorFragment(
|
||||
"py.ide.project",
|
||||
PyBundle.message("python.run.configuration.fragments.project"),
|
||||
null,
|
||||
modulesComboBox, SettingsEditorFragmentType.COMMAND_LINE,
|
||||
{ s: T, modulesCombo: ModulesComboBox ->
|
||||
val validModules: List<Module> = config.validModules
|
||||
modulesCombo.setModules(validModules)
|
||||
modulesCombo.selectedModule = config.module
|
||||
},
|
||||
{ s: T, modulesCombo: ModulesComboBox ->
|
||||
modulesCombo.selectedModule?.let { selected ->
|
||||
s.module = selected
|
||||
}
|
||||
},
|
||||
{ true }
|
||||
)
|
||||
modulesFragment.isRemovable = false
|
||||
modulesFragment.setHint(PyBundle.message("python.run.configuration.fragments.project.hint"))
|
||||
fragments.add(modulesFragment)
|
||||
}
|
||||
|
||||
val sdkComboBox = PySdkComboBox(true) { modulesComboBox?.selectedModule }
|
||||
val minimumSize = CommandLinePanel.setMinimumWidth(sdkComboBox, 400)
|
||||
sdkComboBox.preferredSize = minimumSize
|
||||
sdkComboBox.renderer = PySdkListCellRenderer()
|
||||
val interpreterFragment: SettingsEditorFragment<T, PySdkComboBox> = SettingsEditorFragment<T, PySdkComboBox>(
|
||||
"py.ide.interpreter",
|
||||
PyBundle.message("python.run.configuration.fragments.interpreter.field"),
|
||||
null,
|
||||
sdkComboBox, SettingsEditorFragmentType.COMMAND_LINE,
|
||||
{ s: T, c: PySdkComboBox -> c.reset(s) },
|
||||
{ s: T, c: PySdkComboBox -> c.apply(s) },
|
||||
{ true })
|
||||
interpreterFragment.isRemovable = false
|
||||
interpreterFragment.setHint(PyBundle.message("python.run.configuration.fragments.interpreter.field"))
|
||||
fragments.add(interpreterFragment)
|
||||
|
||||
modulesComboBox?.addItemListener { e ->
|
||||
if (e?.stateChange == ItemEvent.SELECTED) {
|
||||
(e.item as? Module)?.let {
|
||||
sdkComboBox.setModule(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragments.add(createWorkingDirectoryFragment(config.project))
|
||||
fragments.add(createEnvParameters())
|
||||
fragments.add(PyPathMappingsEditorFragment(sdkComboBox))
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceInterface="com.jetbrains.python.run.PyCommonOptionsFormFactory"
|
||||
serviceImplementation="com.jetbrains.python.run.PyPluginCommonOptionsFormFactory"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.run.PyCommonFragmentsBuilder"
|
||||
serviceImplementation="com.jetbrains.python.run.PyPluginCommonFragmentsBuilder"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run
|
||||
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.jetbrains.python.run.configuration.PyInterpreterModeNotifier
|
||||
import com.jetbrains.python.run.configuration.PyPathMappingsEditorFragment
|
||||
import javax.swing.JPanel
|
||||
|
||||
class PyPluginCommonFragmentsBuilder: PyCommonFragmentsBuilder() {
|
||||
override fun <T : AbstractPythonRunConfiguration<*>> createEnvironmentFragments(fragments: MutableList<SettingsEditorFragment<T, *>>,
|
||||
config: T) {
|
||||
val sdkFragment: SettingsEditorFragment<T, JPanel> = PyPluginSdkFragment()
|
||||
fragments.add(sdkFragment)
|
||||
|
||||
fragments.add(createWorkingDirectoryFragment(config.project))
|
||||
fragments.add(createEnvParameters())
|
||||
fragments.add(PyPathMappingsEditorFragment(sdkFragment as PyInterpreterModeNotifier))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run
|
||||
|
||||
import com.intellij.application.options.ModulesComboBox
|
||||
import com.intellij.execution.ui.CommandLinePanel
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.execution.ui.SettingsEditorFragmentType
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.run.configuration.PyInterpreterModeNotifier
|
||||
import com.jetbrains.python.run.configuration.PySdkComboBox
|
||||
import com.jetbrains.python.sdk.PythonSdkUtil
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.GridBagLayout
|
||||
import java.awt.event.ItemEvent
|
||||
import java.util.function.Consumer
|
||||
import javax.swing.JComboBox
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
class PyPluginSdkFragment<T : AbstractPythonRunConfiguration<*>> : SettingsEditorFragment<T, JPanel>(
|
||||
"py.plugin.interpreter", null, null, JPanel(GridBagLayout()), SettingsEditorFragmentType.COMMAND_LINE, null, null,
|
||||
{ true }), PyInterpreterModeNotifier {
|
||||
|
||||
private val typeNames = listOf(PyBundle.message("python.run.configuration.fragments.plugin.sdk.of.module"),
|
||||
PyBundle.message("python.run.configuration.fragments.plugin.specified.interpreter"))
|
||||
private val SDK_OF_MODULE = 0
|
||||
private val SDK_FROM_LIST = 1
|
||||
private var currentMode: Int? = null
|
||||
|
||||
private var modulesCombo: ModulesComboBox? = null
|
||||
private var interpreterCombo: PySdkComboBox? = null
|
||||
|
||||
val fields: MutableList<JComponent?> = MutableList(SDK_FROM_LIST + 1) { null }
|
||||
private val hints: MutableMap<JComponent, String> = mutableMapOf()
|
||||
private val sdkChooser: JComboBox<String>
|
||||
private val interpreterModeListeners: MutableList<Consumer<Boolean>> = mutableListOf()
|
||||
|
||||
init {
|
||||
sdkChooser = JComboBox()
|
||||
sdkChooser.addItem(typeNames[SDK_OF_MODULE])
|
||||
sdkChooser.addItem(typeNames[SDK_FROM_LIST])
|
||||
CommandLinePanel.setMinimumWidth(sdkChooser, 200)
|
||||
component().add(sdkChooser, GridBagConstraints())
|
||||
hints[sdkChooser] = PyBundle.message("python.run.configuration.fragments.plugin.sdk.chooser.hint")
|
||||
|
||||
sdkChooser.addItemListener { e ->
|
||||
if (e?.stateChange == ItemEvent.SELECTED) {
|
||||
if ((e.item as? String) == typeNames[SDK_FROM_LIST]) {
|
||||
showField(SDK_FROM_LIST)
|
||||
currentMode = SDK_FROM_LIST
|
||||
}
|
||||
else {
|
||||
showField(SDK_OF_MODULE)
|
||||
currentMode = SDK_OF_MODULE
|
||||
}
|
||||
}
|
||||
}
|
||||
sdkChooser.addActionListener { updateRemoteInterpreterMode() }
|
||||
}
|
||||
|
||||
override fun resetEditorFrom(config: T) {
|
||||
if (currentMode == null) {
|
||||
initComponents(config)
|
||||
}
|
||||
val type = if (config.isUseModuleSdk) SDK_OF_MODULE else SDK_FROM_LIST
|
||||
if (currentMode != type) {
|
||||
sdkChooser.selectedItem = typeNames[type]
|
||||
(fields[SDK_OF_MODULE] as? ComboBox<*>)?.selectedItem = config.module
|
||||
interpreterCombo?.reset(config)
|
||||
showField(type)
|
||||
}
|
||||
updateRemoteInterpreterMode()
|
||||
}
|
||||
|
||||
private fun showField(type: Int) {
|
||||
for (i in 0 until fields.size) {
|
||||
fields[i]?.isVisible = i == type
|
||||
}
|
||||
}
|
||||
|
||||
private fun initComponents(config: T) {
|
||||
val modulesComponent = ModulesComboBox()
|
||||
initComponent(modulesComponent, SDK_OF_MODULE)
|
||||
val validModules: List<Module> = config.commonOptionsFormData.validModules
|
||||
modulesComponent.setModules(validModules)
|
||||
modulesComponent.selectedModule = config.module
|
||||
fields[SDK_OF_MODULE] = modulesComponent
|
||||
modulesCombo = modulesComponent
|
||||
CommandLinePanel.setMinimumWidth(modulesCombo, 400)
|
||||
hints[modulesComponent] = PyBundle.message("python.run.configuration.fragments.plugin.sdk.of.module.hint")
|
||||
modulesCombo?.addActionListener { updateRemoteInterpreterMode() }
|
||||
|
||||
val interpreterComponent = PySdkComboBox(false) { modulesComponent.selectedModule }
|
||||
initComponent(interpreterComponent, SDK_FROM_LIST)
|
||||
interpreterComponent.reset(config)
|
||||
fields[SDK_FROM_LIST] = interpreterComponent
|
||||
interpreterCombo = interpreterComponent
|
||||
CommandLinePanel.setMinimumWidth(interpreterCombo, 400)
|
||||
hints[interpreterComponent] = PyBundle.message("python.run.configuration.fragments.plugin.specified.interpreter.hint")
|
||||
interpreterCombo?.addActionListener { updateRemoteInterpreterMode() }
|
||||
}
|
||||
|
||||
private fun initComponent(field: JComponent, index: Int) {
|
||||
val constraints = GridBagConstraints()
|
||||
constraints.fill = GridBagConstraints.BOTH
|
||||
constraints.weightx = 1.0
|
||||
component().add(field, constraints)
|
||||
fields[index] = field
|
||||
}
|
||||
|
||||
override fun applyEditorTo(s: T) {
|
||||
if (currentMode == SDK_OF_MODULE) {
|
||||
s.isUseModuleSdk = true
|
||||
val module = (modulesCombo?.selectedItem) as? Module
|
||||
s.module = module
|
||||
module?.let {
|
||||
val moduleSdk = ModuleRootManager.getInstance(it).sdk
|
||||
s.setSdk(moduleSdk)
|
||||
}
|
||||
}
|
||||
else if (currentMode == SDK_FROM_LIST) {
|
||||
s.isUseModuleSdk = false
|
||||
interpreterCombo?.apply(s)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isRemovable(): Boolean = false
|
||||
|
||||
override fun getAllComponents(): Array<JComponent> {
|
||||
return fields.filterNotNull().toTypedArray() + sdkChooser
|
||||
}
|
||||
|
||||
override fun getHint(component: JComponent?): String? {
|
||||
return if (component == null) null else hints[component]
|
||||
}
|
||||
|
||||
override fun isRemoteSelected(): Boolean = PythonSdkUtil.isRemote(getSelectedSdk())
|
||||
|
||||
override fun addInterpreterModeListener(listener: Consumer<Boolean>) {
|
||||
interpreterModeListeners.add(listener)
|
||||
}
|
||||
|
||||
private fun updateRemoteInterpreterMode() {
|
||||
val isRemote = isRemoteSelected()
|
||||
for (listener in interpreterModeListeners) {
|
||||
listener.accept(isRemote)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedSdk(): Sdk? {
|
||||
if (currentMode == SDK_OF_MODULE) {
|
||||
((modulesCombo?.selectedItem) as? Module)?.let {
|
||||
return ModuleRootManager.getInstance(it).sdk
|
||||
}
|
||||
}
|
||||
else if (currentMode == SDK_FROM_LIST) {
|
||||
return interpreterCombo?.getSelectedSdk()
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1030,6 +1030,31 @@ form.tox.configuration.environments.to.run=Environments to run:
|
||||
form.tox.configuration.runcfg.tox=tox
|
||||
py.module.dependencies.configurable.list.title=Project depends on these projects:
|
||||
py.sdk.editor.python.interpreter.label.text=Python Interpreter:
|
||||
|
||||
python.run.configuration.fragments.chooser.hint=Run Python script or module
|
||||
python.run.configuration.fragments.script.path.hint=Path to a Python script
|
||||
python.run.configuration.fragments.module.name.hint=Name of a module
|
||||
python.run.configuration.fragments.project=Project
|
||||
python.run.configuration.fragments.project.hint=Select a project
|
||||
python.run.configuration.fragments.interpreter.field=Python interpreter
|
||||
python.run.configuration.fragments.interpreter.options=Interpreter options
|
||||
python.run.configuration.fragments.interpreter.options.hint=Python interpreter options
|
||||
python.run.configuration.fragments.script.parameters=Parameters
|
||||
python.run.configuration.fragments.script.parameters.hint=Script parameters
|
||||
python.run.configuration.fragments.run.with.python.console=Run with Python Console
|
||||
python.run.configuration.fragments.run.with.python.console.hint=Execute run configuration in Python Console
|
||||
python.run.configuration.fragments.emulate.terminal=Emulate terminal in output console
|
||||
python.run.configuration.fragments.emulate.terminal.hint=Emulate terminal in output console
|
||||
python.run.configuration.fragments.content.roots=Add content roots to PYTHONPATH
|
||||
python.run.configuration.fragments.content.roots.hint=Add content roots to PYTHONPATH
|
||||
python.run.configuration.fragments.source.roots=Add source roots to PYTHONPATH
|
||||
python.run.configuration.fragments.source.roots.hint=Add source roots to PYTHONPATH
|
||||
python.run.configuration.fragments.python.group=Python
|
||||
python.run.configuration.fragments.plugin.sdk.chooser.hint=Python interpreter
|
||||
python.run.configuration.fragments.plugin.sdk.of.module=Use SDK of module
|
||||
python.run.configuration.fragments.plugin.sdk.of.module.hint=Select module
|
||||
python.run.configuration.fragments.plugin.specified.interpreter=Use specified interpreter
|
||||
python.run.configuration.fragments.plugin.specified.interpreter.hint=Select Python interpreter
|
||||
# Python reStructuredText forms
|
||||
rest.configuration.editor.open.output.file.in.browser.label.text=Open output file in browser
|
||||
sphinx.ask.for.working.directory.label.text=Sphinx working directory
|
||||
|
||||
@@ -508,6 +508,8 @@
|
||||
<applicationService
|
||||
serviceInterface="com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory$Available"
|
||||
serviceImplementation="com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory$Available$Default"/>
|
||||
|
||||
<registryKey key="python.new.run.config" defaultValue="true" description="Python Run configurations new UI"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PathMappingSettings;
|
||||
@@ -119,6 +120,11 @@ public abstract class AbstractPythonRunConfiguration<T extends AbstractPythonRun
|
||||
@NotNull
|
||||
@Override
|
||||
public final SettingsEditor<T> getConfigurationEditor() {
|
||||
if (Registry.is("ide.new.run.config", false)) {
|
||||
// TODO: actually, we should return result of `PythonExtendedConfigurationEditor.create()` call, but it produces side effects
|
||||
// investigation needed PY-17716
|
||||
return createConfigurationEditor();
|
||||
}
|
||||
final SettingsEditor<T> runConfigurationEditor = PythonExtendedConfigurationEditor.create(createConfigurationEditor());
|
||||
|
||||
final SettingsEditorGroup<T> group = new SettingsEditorGroup<>();
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run
|
||||
|
||||
import com.intellij.execution.ExecutionBundle
|
||||
import com.intellij.execution.configuration.EnvironmentVariablesComponent
|
||||
import com.intellij.execution.ui.CommonParameterFragments
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.LabeledComponent
|
||||
import com.intellij.openapi.ui.TextComponentAccessor
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.openapi.util.Predicates
|
||||
import com.intellij.ui.components.fields.ExtendableTextField
|
||||
import java.awt.BorderLayout
|
||||
import javax.swing.JComponent
|
||||
|
||||
@Service
|
||||
abstract class PyCommonFragmentsBuilder {
|
||||
abstract fun <T : AbstractPythonRunConfiguration<*>> createEnvironmentFragments(fragments: MutableList<SettingsEditorFragment<T, *>>,
|
||||
config: T)
|
||||
|
||||
fun <T : AbstractPythonRunConfiguration<*>> createWorkingDirectoryFragment(project: Project):
|
||||
SettingsEditorFragment<T, LabeledComponent<TextFieldWithBrowseButton>> {
|
||||
val textField = ExtendableTextField(10)
|
||||
val workingDirectoryField = TextFieldWithBrowseButton(textField)
|
||||
workingDirectoryField.addBrowseFolderListener(
|
||||
ExecutionBundle.message("select.working.directory.message"),
|
||||
null,
|
||||
project,
|
||||
FileChooserDescriptorFactory.createSingleFolderDescriptor(),
|
||||
TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT
|
||||
)
|
||||
val field = LabeledComponent.create(
|
||||
workingDirectoryField,
|
||||
ExecutionBundle.message("run.configuration.working.directory.label"),
|
||||
BorderLayout.WEST
|
||||
)
|
||||
val workingDirectorySettings = SettingsEditorFragment(
|
||||
"workingDirectory",
|
||||
ExecutionBundle.message("run.configuration.working.directory.name"), null, field,
|
||||
{ config: T, component: LabeledComponent<TextFieldWithBrowseButton> -> component.component.text = config.workingDirectory },
|
||||
{ config: T, component: LabeledComponent<TextFieldWithBrowseButton> -> config.workingDirectory = component.component.text },
|
||||
Predicates.alwaysTrue()
|
||||
)
|
||||
workingDirectorySettings.isRemovable = false
|
||||
return workingDirectorySettings
|
||||
}
|
||||
|
||||
fun <T : AbstractPythonRunConfiguration<*>> createEnvParameters(): SettingsEditorFragment<T, *> {
|
||||
val env = EnvironmentVariablesComponent()
|
||||
env.labelLocation = BorderLayout.WEST
|
||||
CommonParameterFragments.setMonospaced(env.component.textField)
|
||||
val fragment = SettingsEditorFragment<T, JComponent>(
|
||||
"environmentVariables",
|
||||
ExecutionBundle.message("environment.variables.fragment.name"),
|
||||
ExecutionBundle.message("group.operating.system"), env,
|
||||
{ config: T, c: JComponent? ->
|
||||
env.envs = config.envs
|
||||
env.isPassParentEnvs = config.isPassParentEnvs
|
||||
},
|
||||
{ config: T, _: JComponent? ->
|
||||
if (!env.isVisible) {
|
||||
config.envs = emptyMap()
|
||||
config.isPassParentEnvs = true
|
||||
}
|
||||
else {
|
||||
config.envs = env.envs
|
||||
config.isPassParentEnvs = env.isPassParentEnvs
|
||||
}
|
||||
},
|
||||
{ true })
|
||||
fragment.isCanBeHidden = true
|
||||
fragment.setHint(ExecutionBundle.message("environment.variables.fragment.hint"))
|
||||
fragment.actionHint = ExecutionBundle.message("set.custom.environment.variables.for.the.process")
|
||||
return fragment
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -18,6 +19,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementAdapter;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.run.configuration.PythonConfigurationFragmentedEditor;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -54,6 +56,9 @@ public class PythonRunConfiguration extends AbstractPythonRunConfiguration
|
||||
|
||||
@Override
|
||||
protected SettingsEditor<? extends RunConfiguration> createConfigurationEditor() {
|
||||
if (Registry.is("python.new.run.config", false)) {
|
||||
return new PythonConfigurationFragmentedEditor(this);
|
||||
}
|
||||
return new PythonRunConfigurationEditor(this);
|
||||
}
|
||||
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import com.intellij.diagnostic.logging.LogsGroupFragment
|
||||
import com.intellij.execution.ui.*
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.ui.RawCommandLineEditor
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfiguration
|
||||
import com.jetbrains.python.run.PyCommonFragmentsBuilder
|
||||
import com.jetbrains.python.run.PythonRunConfigurationExtensionsManager
|
||||
|
||||
abstract class AbstractPythonConfigurationFragmentedEditor<T : AbstractPythonRunConfiguration<*>>(val runConfiguration: T) :
|
||||
RunConfigurationFragmentedEditor<T>(runConfiguration, PythonRunConfigurationExtensionsManager.instance) {
|
||||
|
||||
override fun createRunFragments(): MutableList<SettingsEditorFragment<T, *>> {
|
||||
val fragments: MutableList<SettingsEditorFragment<T, *>> = ArrayList()
|
||||
val beforeRunComponent = BeforeRunComponent(this)
|
||||
fragments.add(BeforeRunFragment.createBeforeRun(beforeRunComponent, null))
|
||||
fragments.addAll(BeforeRunFragment.createGroup())
|
||||
fragments.add(CommonParameterFragments.createRunHeader())
|
||||
|
||||
createEnvironmentFragments(fragments, runConfiguration)
|
||||
addInterpreterOptions(fragments)
|
||||
addContentSourceRoots(fragments)
|
||||
|
||||
customizeFragments(fragments)
|
||||
|
||||
fragments.add(LogsGroupFragment())
|
||||
return fragments
|
||||
}
|
||||
|
||||
private fun <T : AbstractPythonRunConfiguration<*>> createEnvironmentFragments(fragments: MutableList<SettingsEditorFragment<T, *>>,
|
||||
runConfiguration: T) {
|
||||
service<PyCommonFragmentsBuilder>().createEnvironmentFragments(fragments, runConfiguration)
|
||||
}
|
||||
|
||||
abstract fun customizeFragments(fragments: MutableList<SettingsEditorFragment<T, *>>)
|
||||
|
||||
private fun <T : AbstractPythonRunConfiguration<*>> addInterpreterOptions(fragments: MutableList<SettingsEditorFragment<T, *>>) {
|
||||
val interpreterOptionsField = RawCommandLineEditor()
|
||||
val interpreterOptionsFragment: SettingsEditorFragment<T, RawCommandLineEditor> = SettingsEditorFragment<T, RawCommandLineEditor>(
|
||||
"py.interpreter.options",
|
||||
PyBundle.message("python.run.configuration.fragments.interpreter.options"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
interpreterOptionsField, SettingsEditorFragmentType.COMMAND_LINE,
|
||||
{ config: T, field: RawCommandLineEditor -> field.text = config.interpreterOptions },
|
||||
{ config: T, field: RawCommandLineEditor -> config.interpreterOptions = field.text.trim() },
|
||||
{ config: T -> !config.interpreterOptions.trim().isEmpty() })
|
||||
interpreterOptionsFragment.setHint(PyBundle.message("python.run.configuration.fragments.interpreter.options.hint"))
|
||||
interpreterOptionsFragment.actionHint = PyBundle.message("python.run.configuration.fragments.interpreter.options.hint")
|
||||
fragments.add(interpreterOptionsFragment)
|
||||
}
|
||||
|
||||
private fun <T : AbstractPythonRunConfiguration<*>> addContentSourceRoots(fragments: MutableList<SettingsEditorFragment<T, *>>) {
|
||||
val addContentRoots = SettingsEditorFragment.createTag<T>(
|
||||
"py.add.content.roots",
|
||||
PyBundle.message("python.run.configuration.fragments.content.roots"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
{ it.shouldAddContentRoots() },
|
||||
{ config, value -> config.setAddContentRoots(value) })
|
||||
|
||||
addContentRoots.actionHint = PyBundle.message("python.run.configuration.fragments.content.roots.hint")
|
||||
fragments.add(addContentRoots)
|
||||
|
||||
val addSourceRoots = SettingsEditorFragment.createTag<T>(
|
||||
"py.add.content.roots",
|
||||
PyBundle.message("python.run.configuration.fragments.source.roots"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
{ it.shouldAddContentRoots() },
|
||||
{ config, value -> config.setAddContentRoots(value) })
|
||||
|
||||
addSourceRoots.actionHint = PyBundle.message("python.run.configuration.fragments.source.roots.hint")
|
||||
fragments.add(addSourceRoots)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import java.util.function.Consumer
|
||||
|
||||
interface PyInterpreterModeNotifier {
|
||||
fun addInterpreterModeListener(listener: Consumer<Boolean>)
|
||||
|
||||
fun isRemoteSelected(): Boolean
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import com.intellij.execution.ui.CommandLinePanel
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.execution.util.PathMappingsComponent
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfiguration
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.GridBagLayout
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
class PyPathMappingsEditorFragment<T : AbstractPythonRunConfiguration<*>>(val notifier: PyInterpreterModeNotifier) :
|
||||
SettingsEditorFragment<T, JPanel>("py.path.mappings", null, null, JPanel(GridBagLayout()), null, null, { true }) {
|
||||
private val pathMappingsComponent = PathMappingsComponent()
|
||||
|
||||
init {
|
||||
pathMappingsComponent.labelLocation = BorderLayout.WEST
|
||||
CommandLinePanel.setMinimumWidth(component(), 500)
|
||||
val constrains = GridBagConstraints()
|
||||
constrains.fill = GridBagConstraints.HORIZONTAL
|
||||
constrains.weightx = 1.0
|
||||
constrains.gridx = 0
|
||||
|
||||
component().add(pathMappingsComponent, constrains)
|
||||
pathMappingsComponent.isVisible = notifier.isRemoteSelected()
|
||||
notifier.addInterpreterModeListener { isRemote ->
|
||||
pathMappingsComponent.isVisible = isRemote
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAllComponents(): Array<JComponent> {
|
||||
return arrayOf(pathMappingsComponent)
|
||||
}
|
||||
|
||||
override fun resetEditorFrom(config: T) {
|
||||
pathMappingsComponent.setMappingSettings(config.mappingSettings)
|
||||
}
|
||||
|
||||
override fun applyEditorTo(s: T) {
|
||||
s.mappingSettings = pathMappingsComponent.mappingSettings
|
||||
}
|
||||
|
||||
override fun isRemovable(): Boolean = false
|
||||
|
||||
override fun isSelected(): Boolean = true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import com.intellij.execution.ui.CommandLinePanel
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.execution.ui.SettingsEditorFragmentType
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.ui.TextBrowseFolderListener
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.psi.PsiFileSystemItem
|
||||
import com.intellij.ui.TextAccessor
|
||||
import com.jetbrains.PySymbolFieldWithBrowseButton
|
||||
import com.jetbrains.extensions.ModuleBasedContextAnchor
|
||||
import com.jetbrains.extensions.ProjectSdkContextAnchor
|
||||
import com.jetbrains.isPythonModule
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.run.PythonRunConfiguration
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.GridBagLayout
|
||||
import java.awt.event.ItemEvent
|
||||
import javax.swing.JComboBox
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
|
||||
class PyScriptOrModuleFragment : SettingsEditorFragment<PythonRunConfiguration, JPanel>(
|
||||
"py.script.field", null, null, JPanel(GridBagLayout()), SettingsEditorFragmentType.COMMAND_LINE, null, null, { true }) {
|
||||
|
||||
private val typeNames = listOf("script", "module")
|
||||
private val SCRIPT_MODE = 0
|
||||
private val MODULE_MODE = 1
|
||||
private var currentMode: Int? = null
|
||||
|
||||
val fields: MutableList<JComponent?> = MutableList(MODULE_MODE + 1) { null }
|
||||
val hints: MutableMap<JComponent, String> = mutableMapOf()
|
||||
|
||||
private val moduleModeChooser: JComboBox<String>
|
||||
|
||||
init {
|
||||
CommandLinePanel.setMinimumWidth(component(), 500)
|
||||
moduleModeChooser = JComboBox()
|
||||
moduleModeChooser.addItem(typeNames[SCRIPT_MODE])
|
||||
moduleModeChooser.addItem(typeNames[MODULE_MODE])
|
||||
component().add(moduleModeChooser, GridBagConstraints())
|
||||
hints[moduleModeChooser] = PyBundle.message("python.run.configuration.fragments.chooser.hint")
|
||||
|
||||
moduleModeChooser.addItemListener { e ->
|
||||
if (e?.stateChange == ItemEvent.SELECTED) {
|
||||
if ((e.item as? String) == typeNames[MODULE_MODE]) {
|
||||
showField(MODULE_MODE)
|
||||
currentMode = MODULE_MODE
|
||||
}
|
||||
else {
|
||||
showField(SCRIPT_MODE)
|
||||
currentMode = SCRIPT_MODE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetEditorFrom(config: PythonRunConfiguration) {
|
||||
if (currentMode == null) {
|
||||
initComponents(config)
|
||||
}
|
||||
val type = if (config.isModuleMode) MODULE_MODE else SCRIPT_MODE
|
||||
if (currentMode != type) {
|
||||
currentMode = type
|
||||
moduleModeChooser.selectedItem = typeNames[type]
|
||||
showField(type)
|
||||
(fields[type] as TextAccessor).text = config.scriptName
|
||||
}
|
||||
}
|
||||
|
||||
private fun showField(type: Int) {
|
||||
for (i in 0 until fields.size) {
|
||||
fields[i]?.isVisible = i == type
|
||||
}
|
||||
}
|
||||
|
||||
private fun initComponents(config: PythonRunConfiguration) {
|
||||
val scriptField = TextFieldWithBrowseButton()
|
||||
scriptField.addBrowseFolderListener(TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFileDescriptor(), config.project))
|
||||
initComponent(scriptField, SCRIPT_MODE)
|
||||
fields[SCRIPT_MODE] = scriptField
|
||||
hints[scriptField] = PyBundle.message("python.run.configuration.fragments.script.path.hint")
|
||||
|
||||
val module = config.module
|
||||
val contentAnchor = if (module == null) ProjectSdkContextAnchor(config.project, config.sdk) else ModuleBasedContextAnchor(module)
|
||||
val workingDirectory = config.workingDirectory
|
||||
val moduleField = PySymbolFieldWithBrowseButton(
|
||||
contentAnchor,
|
||||
{ element -> (element is PsiFileSystemItem && isPythonModule(element)) },
|
||||
if (StringUtil.isEmpty(workingDirectory)) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
{ LocalFileSystem.getInstance().findFileByPath(workingDirectory)!! }
|
||||
})
|
||||
initComponent(moduleField, MODULE_MODE)
|
||||
fields[MODULE_MODE] = moduleField
|
||||
hints[moduleField] = PyBundle.message("python.run.configuration.fragments.module.name.hint")
|
||||
}
|
||||
|
||||
private fun initComponent(field: JComponent, index: Int) {
|
||||
val constraints = GridBagConstraints()
|
||||
constraints.fill = GridBagConstraints.BOTH
|
||||
constraints.weightx = 1.0
|
||||
component().add(field, constraints)
|
||||
fields[index] = field
|
||||
}
|
||||
|
||||
override fun applyEditorTo(s: PythonRunConfiguration) {
|
||||
val mode = currentMode
|
||||
if (mode == null) return
|
||||
s.isModuleMode = mode == MODULE_MODE
|
||||
val text = (fields[mode] as? TextAccessor)?.text?.trim()
|
||||
if (mode == MODULE_MODE) {
|
||||
s.scriptName = text
|
||||
}
|
||||
else {
|
||||
s.scriptName = text?.let { FileUtil.toSystemIndependentName(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun isRemovable(): Boolean = false
|
||||
|
||||
override fun getAllComponents(): Array<JComponent> {
|
||||
return fields.filterNotNull().toTypedArray() + moduleModeChooser
|
||||
}
|
||||
|
||||
override fun getHint(component: JComponent?): String? {
|
||||
return if (component == null) null else hints[component]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfigurationParams
|
||||
import com.jetbrains.python.sdk.PySdkListCellRenderer
|
||||
import com.jetbrains.python.sdk.PythonSdkUtil
|
||||
import java.util.function.Consumer
|
||||
|
||||
class PySdkComboBox(private val addDefault: Boolean,
|
||||
private val moduleProvider: Computable<out Module?>) : ComboBox<Sdk>(), PyInterpreterModeNotifier {
|
||||
private val interpreterModeListeners: MutableList<Consumer<Boolean>> = mutableListOf()
|
||||
|
||||
fun reset(config: AbstractPythonRunConfigurationParams) {
|
||||
initList()
|
||||
selectedItem = config.sdk
|
||||
setUseModuleSdk(config.isUseModuleSdk)
|
||||
setModule(config.module)
|
||||
addActionListener {
|
||||
updateRemoteInterpreterMode()
|
||||
}
|
||||
updateRemoteInterpreterMode()
|
||||
}
|
||||
|
||||
private fun initList() {
|
||||
val pythonSdks: MutableList<Sdk?> = PythonSdkUtil.getAllSdks().toMutableList()
|
||||
if (addDefault) {
|
||||
pythonSdks.add(0, null)
|
||||
}
|
||||
for (item in pythonSdks) {
|
||||
addItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
fun apply(config: AbstractPythonRunConfigurationParams) {
|
||||
config.sdk = selectedItem as? Sdk
|
||||
config.isUseModuleSdk = isUseModuleSdk()
|
||||
}
|
||||
|
||||
fun setModule(module: Module?) {
|
||||
updateDefaultInterpreter(module)
|
||||
updateRemoteInterpreterMode()
|
||||
}
|
||||
|
||||
private fun updateDefaultInterpreter(module: Module?) {
|
||||
val sdk = if (module == null) null else ModuleRootManager.getInstance(module).sdk
|
||||
setRenderer(
|
||||
if (sdk == null) PySdkListCellRenderer()
|
||||
else PySdkListCellRenderer(PyBundle.message("python.sdk.rendering.project.default.0", sdk.name), sdk)
|
||||
)
|
||||
}
|
||||
|
||||
private fun setUseModuleSdk(useModuleSdk: Boolean) {
|
||||
if (selectedItem != null && useModuleSdk) {
|
||||
selectedItem = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUseModuleSdk(): Boolean = addDefault && selectedItem == null
|
||||
|
||||
fun getSelectedSdk(): Sdk? {
|
||||
val selectedSdk = selectedItem as? Sdk
|
||||
if (selectedSdk != null) {
|
||||
return selectedSdk
|
||||
}
|
||||
else {
|
||||
if (isUseModuleSdk()) {
|
||||
moduleProvider.get()?.let {
|
||||
return@getSelectedSdk PythonSdkUtil.findPythonSdk(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun isRemoteSelected(): Boolean = PythonSdkUtil.isRemote(getSelectedSdk())
|
||||
|
||||
private fun updateRemoteInterpreterMode() {
|
||||
val isRemote = isRemoteSelected()
|
||||
for (listener in interpreterModeListeners) {
|
||||
listener.accept(isRemote)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addInterpreterModeListener(listener: Consumer<Boolean>) {
|
||||
interpreterModeListeners.add(listener)
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.run.configuration
|
||||
|
||||
import com.intellij.execution.ExecutionBundle
|
||||
import com.intellij.execution.ui.SettingsEditorFragment
|
||||
import com.intellij.execution.ui.SettingsEditorFragmentType
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.ui.LabeledComponent
|
||||
import com.intellij.openapi.ui.TextBrowseFolderListener
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.ui.RawCommandLineEditor
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.run.PythonRunConfiguration
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
|
||||
class PythonConfigurationFragmentedEditor(runConfiguration: PythonRunConfiguration) :
|
||||
AbstractPythonConfigurationFragmentedEditor<PythonRunConfiguration>(runConfiguration) {
|
||||
|
||||
override fun customizeFragments(fragments: MutableList<SettingsEditorFragment<PythonRunConfiguration, *>>) {
|
||||
fragments.add(PyScriptOrModuleFragment())
|
||||
|
||||
val scriptParametersFragment: SettingsEditorFragment<PythonRunConfiguration, RawCommandLineEditor> = SettingsEditorFragment<PythonRunConfiguration, RawCommandLineEditor>(
|
||||
"py.script.parameters",
|
||||
PyBundle.message("python.run.configuration.fragments.script.parameters"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
RawCommandLineEditor(), SettingsEditorFragmentType.COMMAND_LINE,
|
||||
{ config: PythonRunConfiguration, field: RawCommandLineEditor -> field.text = config.scriptParameters },
|
||||
{ config: PythonRunConfiguration, field: RawCommandLineEditor -> config.scriptParameters = field.text.trim() },
|
||||
{ config: PythonRunConfiguration -> !config.scriptParameters.trim().isEmpty() })
|
||||
scriptParametersFragment.setHint(PyBundle.message("python.run.configuration.fragments.script.parameters.hint"))
|
||||
scriptParametersFragment.actionHint = PyBundle.message("python.run.configuration.fragments.script.parameters.hint")
|
||||
fragments.add(scriptParametersFragment)
|
||||
|
||||
|
||||
val runWithConsole = SettingsEditorFragment.createTag<PythonRunConfiguration>(
|
||||
"py.run.with.python.console",
|
||||
PyBundle.message("python.run.configuration.fragments.run.with.python.console"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
{ it.showCommandLineAfterwards() },
|
||||
{ config, value -> config.setShowCommandLineAfterwards(value) })
|
||||
runWithConsole.actionHint = PyBundle.message("python.run.configuration.fragments.run.with.python.console.hint")
|
||||
fragments.add(runWithConsole)
|
||||
|
||||
val emulateTerminal = SettingsEditorFragment.createTag<PythonRunConfiguration>(
|
||||
"py.emulate.terminal",
|
||||
PyBundle.message("python.run.configuration.fragments.emulate.terminal"),
|
||||
PyBundle.message("python.run.configuration.fragments.python.group"),
|
||||
{ it.emulateTerminal() },
|
||||
{ config, value -> config.setEmulateTerminal(value) })
|
||||
emulateTerminal.actionHint = PyBundle.message("python.run.configuration.fragments.emulate.terminal.hint")
|
||||
fragments.add(emulateTerminal)
|
||||
|
||||
val inputFile = TextFieldWithBrowseButton()
|
||||
inputFile.addBrowseFolderListener(TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFileDescriptor(),
|
||||
runConfiguration.project))
|
||||
val labeledComponent = LabeledComponent.create<TextFieldWithBrowseButton>(inputFile, ExecutionBundle.message("redirect.input.from"))
|
||||
labeledComponent.labelLocation = BorderLayout.WEST
|
||||
val redirectInputFrom: SettingsEditorFragment<PythonRunConfiguration, LabeledComponent<TextFieldWithBrowseButton>> =
|
||||
SettingsEditorFragment<PythonRunConfiguration, LabeledComponent<TextFieldWithBrowseButton>>(
|
||||
"py.redirect.input",
|
||||
ExecutionBundle.message("redirect.input.from.name"),
|
||||
ExecutionBundle.message("group.operating.system"),
|
||||
labeledComponent, SettingsEditorFragmentType.COMMAND_LINE,
|
||||
{ config: PythonRunConfiguration, component: LabeledComponent<TextFieldWithBrowseButton> ->
|
||||
component.component.text = config.inputFile
|
||||
},
|
||||
{ config: PythonRunConfiguration, component: LabeledComponent<TextFieldWithBrowseButton> ->
|
||||
val filePath = component.component.text
|
||||
config.isRedirectInput = component.isVisible && StringUtil.isNotEmpty(filePath)
|
||||
config.inputFile = filePath
|
||||
},
|
||||
{ config: PythonRunConfiguration -> config.isRedirectInput })
|
||||
redirectInputFrom.actionHint = ExecutionBundle.message("read.input.from.the.specified.file")
|
||||
redirectInputFrom.setHint(ExecutionBundle.message("read.input.from.the.specified.file"))
|
||||
fragments.add(redirectInputFrom)
|
||||
|
||||
val editors = mutableListOf<SettingsEditorFragment<PythonRunConfiguration, *>>()
|
||||
editors.add(runWithConsole)
|
||||
editors.add(emulateTerminal)
|
||||
editors.add(redirectInputFrom)
|
||||
addSingleSelectionListeners(editors)
|
||||
}
|
||||
|
||||
private fun addSingleSelectionListeners(editors: MutableList<SettingsEditorFragment<PythonRunConfiguration, *>>) {
|
||||
for ((i, editor) in editors.withIndex()) {
|
||||
editor.component().addComponentListener(object : ComponentAdapter() {
|
||||
override fun componentShown(e: ComponentEvent?) {
|
||||
for ((j, otherEditor) in editors.withIndex()) {
|
||||
if (i != j) {
|
||||
otherEditor.isSelected = false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user