mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[python] PY-87445 Make pyproject.toml setting visible across Project Structure pages before Apply
GitOrigin-RevId: 8fd3c7a89dc5c3b65759c38e775c95c68900da42
This commit is contained in:
committed by
intellij-monorepo-bot
parent
110fe78aab
commit
52d2828b6d
-131
@@ -1,131 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.pycharm.community.ide.impl.configuration;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.module.PyContentEntriesEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.Parent.Abstract {
|
||||
private final Module myModule;
|
||||
private final JPanel myTopPanel = new JPanel(new BorderLayout());
|
||||
protected ModifiableRootModel myModifiableModel;
|
||||
protected PyContentEntriesEditor myEditor;
|
||||
|
||||
public PyContentEntriesModuleConfigurable(final Module module) {
|
||||
myModule = module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return PyBundle.message("configurable.PyContentEntriesModuleConfigurable.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpTopic() {
|
||||
return "reference.settingsdialog.project.structure";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
createEditor();
|
||||
return myTopPanel;
|
||||
}
|
||||
|
||||
private void createEditor() {
|
||||
if (myModule == null) return;
|
||||
myModifiableModel =
|
||||
ReadAction.compute(() -> ModuleRootManager.getInstance(myModule).getModifiableModel());
|
||||
|
||||
final ModuleConfigurationStateImpl moduleConfigurationState =
|
||||
new ModuleConfigurationStateImpl(myModule.getProject(), new DefaultModulesProvider(myModule.getProject())) {
|
||||
@Override
|
||||
public ModifiableRootModel getModifiableRootModel() {
|
||||
return myModifiableModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleRootModel getCurrentRootModel() {
|
||||
return myModifiableModel;
|
||||
}
|
||||
};
|
||||
myEditor = createEditor(myModule, moduleConfigurationState);
|
||||
|
||||
JComponent component = ReadAction.compute(() -> myEditor.createComponent());
|
||||
myTopPanel.add(component, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
protected PyContentEntriesEditor createEditor(@NotNull Module module, @NotNull ModuleConfigurationStateImpl state) {
|
||||
return new PyContentEntriesEditor(module, state, true, JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myEditor != null && myEditor.isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
if (myEditor == null) return;
|
||||
final boolean editorWasModified = myEditor.isModified();
|
||||
myEditor.apply();
|
||||
if (editorWasModified) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> myModifiableModel.commit());
|
||||
resetEditor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if (myEditor == null) return;
|
||||
if (myModifiableModel != null) {
|
||||
myModifiableModel.dispose();
|
||||
}
|
||||
resetEditor();
|
||||
}
|
||||
|
||||
private void resetEditor() {
|
||||
myEditor.disposeUIResources();
|
||||
myTopPanel.remove(myEditor.getComponent());
|
||||
createEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
if (myEditor != null) {
|
||||
myEditor.disposeUIResources();
|
||||
myTopPanel.remove(myEditor.getComponent());
|
||||
myEditor = null;
|
||||
}
|
||||
if (myModifiableModel != null) {
|
||||
myModifiableModel.dispose();
|
||||
myModifiableModel = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Configurable @NotNull [] buildConfigurables() {
|
||||
return new Configurable[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getId() {
|
||||
return "python.project.structure";
|
||||
}
|
||||
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.pycharm.community.ide.impl.configuration
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.options.SearchableConfigurable
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider
|
||||
import com.intellij.openapi.ui.Splitter
|
||||
import com.intellij.python.pyproject.model.PyProjectModelSettings
|
||||
import com.intellij.ui.AncestorListenerAdapter
|
||||
import com.intellij.ui.roots.IconActionComponent
|
||||
import com.intellij.ui.roots.ToolbarPanel
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.module.PyContentEntriesEditor
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.JPopupMenu
|
||||
import javax.swing.JScrollPane
|
||||
import javax.swing.JTextField
|
||||
import javax.swing.JTree
|
||||
import javax.swing.event.AncestorEvent
|
||||
|
||||
internal class PyContentEntriesModuleConfigurable(private val module: Module) : SearchableConfigurable.Parent.Abstract() {
|
||||
|
||||
private val topPanel = JPanel(BorderLayout())
|
||||
//.apply {
|
||||
// addAncestorListener(object : AncestorListenerAdapter() {
|
||||
// override fun ancestorAdded(event: AncestorEvent) {
|
||||
// updateEnabledState()
|
||||
// }
|
||||
// })
|
||||
//}
|
||||
|
||||
private var modifiableModel: ModifiableRootModel? = null
|
||||
private var editor: PyContentEntriesEditor? = null
|
||||
private val isPyProjectTomlManaged: Boolean
|
||||
get() {
|
||||
val pending = module.project.getUserData(PythonContentEntriesConfigurable.PYPROJECT_TOML_PENDING_KEY)
|
||||
return pending ?: PyProjectModelSettings.getInstance(module.project).usePyprojectToml
|
||||
}
|
||||
|
||||
override fun getDisplayName(): String = PyBundle.message("configurable.PyContentEntriesModuleConfigurable.display.name")
|
||||
|
||||
override fun getHelpTopic(): String = "reference.settingsdialog.project.structure"
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
createEditor()
|
||||
return topPanel
|
||||
}
|
||||
|
||||
private fun createEditor() {
|
||||
val model = ReadAction.computeBlocking<ModifiableRootModel, RuntimeException> {
|
||||
ModuleRootManager.getInstance(module).modifiableModel
|
||||
}
|
||||
modifiableModel = model
|
||||
|
||||
val state = object : ModuleConfigurationStateImpl(module.project, DefaultModulesProvider(module.project)) {
|
||||
override fun getModifiableRootModel(): ModifiableRootModel = model
|
||||
override fun getCurrentRootModel(): ModifiableRootModel = model
|
||||
}
|
||||
val newEditor = createEditor(module, state)
|
||||
editor = newEditor
|
||||
|
||||
val component = ReadAction.computeBlocking<JComponent, RuntimeException> { newEditor.createComponent() }
|
||||
topPanel.add(component, BorderLayout.CENTER)
|
||||
}
|
||||
|
||||
private fun createEditor(module: Module, state: ModuleConfigurationStateImpl): PyContentEntriesEditor =
|
||||
PyContentEntriesEditor(module, state, true, JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE)
|
||||
|
||||
override fun isModified(): Boolean = !isPyProjectTomlManaged && editor?.isModified == true
|
||||
|
||||
override fun apply() {
|
||||
val currentEditor = editor ?: return
|
||||
val editorWasModified = currentEditor.isModified
|
||||
currentEditor.apply()
|
||||
if (editorWasModified) {
|
||||
ApplicationManager.getApplication().runWriteAction { modifiableModel?.commit() }
|
||||
resetEditor()
|
||||
}
|
||||
//updateEnabledState()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
if (isPyProjectTomlManaged) return
|
||||
editor ?: return
|
||||
modifiableModel?.dispose()
|
||||
resetEditor()
|
||||
}
|
||||
|
||||
private fun resetEditor() {
|
||||
val currentEditor = editor ?: return
|
||||
currentEditor.disposeUIResources()
|
||||
topPanel.remove(currentEditor.component)
|
||||
createEditor()
|
||||
}
|
||||
|
||||
private fun updateEnabledState() {
|
||||
val visible = !isPyProjectTomlManaged
|
||||
|
||||
UIUtil.findComponentOfType(topPanel, Splitter::class.java)?.let { splitter ->
|
||||
// Hide the "Mark as" label and action toolbar (siblings of the splitter in contentPanel)
|
||||
splitter.parent?.let { contentPanel ->
|
||||
contentPanel.components.filter { it != splitter }.forEach { it.isVisible = visible }
|
||||
}
|
||||
|
||||
// In the right panel (ToolbarPanel): hide the "Add Content Root" toolbar and remove-root icons
|
||||
val contentRootsPanel = splitter.secondComponent
|
||||
(contentRootsPanel as? ToolbarPanel)?.let {
|
||||
it.getComponent(0).isVisible = visible
|
||||
}
|
||||
UIUtil.findComponentsOfType(contentRootsPanel, IconActionComponent::class.java).forEach {
|
||||
it.isVisible = visible
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress tree context menu without removing PopupHandler listeners
|
||||
UIUtil.findComponentOfType(topPanel, JTree::class.java)?.let { tree ->
|
||||
tree.componentPopupMenu = if (visible) null else EMPTY_POPUP
|
||||
}
|
||||
|
||||
// Hide "Exclude patterns" field, its label, and comment (all are siblings of the tree JScrollPane)
|
||||
UIUtil.findComponentOfType(topPanel, JTextField::class.java)?.let { excludeField ->
|
||||
excludeField.parent?.let { dialogPanel ->
|
||||
dialogPanel.components.filter { it !is JScrollPane }.forEach { it.isVisible = visible }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disposeUIResources() {
|
||||
editor?.let {
|
||||
it.disposeUIResources()
|
||||
topPanel.remove(it.component)
|
||||
}
|
||||
editor = null
|
||||
modifiableModel?.dispose()
|
||||
modifiableModel = null
|
||||
}
|
||||
|
||||
override fun buildConfigurables(): Array<Configurable> = emptyArray()
|
||||
|
||||
override fun getId(): String = "python.project.structure"
|
||||
|
||||
companion object {
|
||||
private val EMPTY_POPUP = object : JPopupMenu() {
|
||||
override fun show(invoker: Component?, x: Int, y: Int) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -82,7 +82,8 @@ public class PyModuleDependenciesConfigurable implements UnnamedConfigurable {
|
||||
}
|
||||
|
||||
private void updateEnabledState() {
|
||||
boolean managed = PyProjectModelSettings.getInstance(myModule.getProject()).getUsePyprojectToml();
|
||||
Boolean pending = myModule.getProject().getUserData(PythonContentEntriesConfigurable.PYPROJECT_TOML_PENDING_KEY);
|
||||
boolean managed = pending != null ? pending : PyProjectModelSettings.getInstance(myModule.getProject()).getUsePyprojectToml();
|
||||
myDependenciesList.setEnabled(!managed);
|
||||
if (managed) {
|
||||
myTitleLabel.setText(PyBundle.message("python.pyproject.toml.dependencies.managed.hint"));
|
||||
|
||||
+17
@@ -7,6 +7,7 @@ import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ui.configuration.PlatformContentEntriesConfigurable
|
||||
import com.intellij.openapi.ui.DialogPanel
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.ui.dsl.builder.Align
|
||||
import com.intellij.ui.dsl.builder.bindSelected
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
@@ -24,6 +25,11 @@ class PythonContentEntriesConfigurable(project: Project) : ModuleAwareProjectCon
|
||||
|
||||
private var pyprojectPanel: DialogPanel? = null
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val PYPROJECT_TOML_PENDING_KEY: Key<Boolean> = Key.create("PythonContentEntriesConfigurable.pendingUsePyprojectToml")
|
||||
}
|
||||
|
||||
override fun createModuleConfigurable(module: Module): Configurable {
|
||||
if (PlatformUtils.isPyCharmCommunity()) {
|
||||
return PlatformContentEntriesConfigurable(module, JavaSourceRootType.SOURCE)
|
||||
@@ -41,6 +47,9 @@ class PythonContentEntriesConfigurable(project: Project) : ModuleAwareProjectCon
|
||||
row {
|
||||
checkBox(PyBundle.message("python.pyproject.toml.based.project.model"))
|
||||
.bindSelected(settings::usePyprojectToml)
|
||||
.applyToComponent {
|
||||
addActionListener { project.putUserData(PYPROJECT_TOML_PENDING_KEY, isSelected) }
|
||||
}
|
||||
.contextHelp(PyBundle.message("python.pyproject.toml.based.project.model.comment"))
|
||||
}
|
||||
super.createComponent()?.let { parentComponent ->
|
||||
@@ -59,11 +68,19 @@ class PythonContentEntriesConfigurable(project: Project) : ModuleAwareProjectCon
|
||||
|
||||
override fun apply() {
|
||||
pyprojectPanel?.apply()
|
||||
project.putUserData(PYPROJECT_TOML_PENDING_KEY, null)
|
||||
super.apply()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
pyprojectPanel?.reset()
|
||||
project.putUserData(PYPROJECT_TOML_PENDING_KEY, null)
|
||||
super.reset()
|
||||
}
|
||||
|
||||
override fun disposeUIResources() {
|
||||
project.putUserData(PYPROJECT_TOML_PENDING_KEY, null)
|
||||
pyprojectPanel = null
|
||||
super.disposeUIResources()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user