From 64d4a1379ce2f297497e4b9037b07eb217f9cced Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Fri, 12 Sep 2025 20:56:31 +0200 Subject: [PATCH] IJPL-207306 Fix UI in Subversion settings - General GitOrigin-RevId: 277750d2413bef47f5b46892b5afe5317e52bc57 --- .../svn4idea/resources/META-INF/plugin.xml | 2 +- .../resources/messages/SvnBundle.properties | 4 +- .../idea/svn/GeneralSettingsPanel.form | 128 ---------------- .../idea/svn/GeneralSettingsPanel.java | 123 --------------- .../idea/svn/GeneralSvnConfigurable.kt | 141 ++++++++++++++++++ .../jetbrains/idea/svn/SvnConfigurable.java | 6 - 6 files changed, 144 insertions(+), 260 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.form delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSvnConfigurable.kt diff --git a/plugins/svn4idea/resources/META-INF/plugin.xml b/plugins/svn4idea/resources/META-INF/plugin.xml index 6f81edf8f561..9e0c2bc6707d 100644 --- a/plugins/svn4idea/resources/META-INF/plugin.xml +++ b/plugins/svn4idea/resources/META-INF/plugin.xml @@ -140,7 +140,7 @@ - diff --git a/plugins/svn4idea/resources/messages/SvnBundle.properties b/plugins/svn4idea/resources/messages/SvnBundle.properties index 74cb6bd7c244..97e07e1c3104 100644 --- a/plugins/svn4idea/resources/messages/SvnBundle.properties +++ b/plugins/svn4idea/resources/messages/SvnBundle.properties @@ -279,8 +279,8 @@ dialog.title.select.path.to.subversion.executable=Subversion label.select.path.to.subversion.executable=Select path to Subversion executable (1.7+) label.path.to.svn.executable=Path to Subversion executable: command.line.interactive.mode.title=Enable interactive mode -command.line.interactive.mode.description=Emulates the behavior when Subversion commands are executed directly from the terminal (in the interactive mode).
\ - This is required to handle password/passphrase prompts for svn+ssh repositories, and trust invalid server certificates for https repositories. +command.line.interactive.mode.description=Emulates the behavior when Subversion commands are executed directly from the terminal (in the interactive mode).
\ + This is required to handle password/passphrase prompts for svn+ssh repositories, and trust invalid server certificates for https repositories. non.english.locale.detected.warning=A non-English locale is used. ssh.settings.executable.label=SSH executable\: diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.form deleted file mode 100644 index 6ddaf9550eaf..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.form +++ /dev/null @@ -1,128 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.java deleted file mode 100644 index 337e9248ab28..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSettingsPanel.java +++ /dev/null @@ -1,123 +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 org.jetbrains.idea.svn; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; -import com.intellij.openapi.options.ConfigurableUi; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.ui.components.JBCheckBox; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; - -import javax.swing.*; -import java.util.Objects; - -import static org.jetbrains.idea.svn.SvnBundle.message; -import static org.jetbrains.idea.svn.SvnUtil.USER_CONFIGURATION_PATH; - -public class GeneralSettingsPanel implements ConfigurableUi, Disposable { - - private final @NotNull Project myProject; - - private JPanel myMainPanel; - - private JCheckBox myUseCustomConfigurationDirectory; - private TextFieldWithBrowseButton myConfigurationDirectoryText; - private JButton myClearAuthButton; - private JBCheckBox myRunUnderTerminal; - private TextFieldWithBrowseButton myCommandLineClient; - - public GeneralSettingsPanel(@NotNull Project project) { - myProject = project; - - myUseCustomConfigurationDirectory.addActionListener(e -> { - boolean enabled = myUseCustomConfigurationDirectory.isSelected(); - myConfigurationDirectoryText.setEnabled(enabled); - myConfigurationDirectoryText.setEditable(enabled); - SvnConfiguration configuration = SvnConfiguration.getInstance(myProject); - String path = configuration.getConfigurationDirectory(); - if (!enabled || path == null) { - myConfigurationDirectoryText.setText(USER_CONFIGURATION_PATH.getValue().toString()); - } - else { - myConfigurationDirectoryText.setText(path); - } - }); - myCommandLineClient.addBrowseFolderListener(project, FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor() - .withTitle(message("dialog.title.select.path.to.subversion.executable")) - .withDescription(message("label.select.path.to.subversion.executable"))); - myClearAuthButton.addActionListener( - e -> SvnAuthenticationNotifier.clearAuthenticationCache(myProject, myMainPanel, myConfigurationDirectoryText.getText())); - myConfigurationDirectoryText.addActionListener(e -> { - @NonNls String path = myConfigurationDirectoryText.getText().trim(); - SvnConfigurable.selectConfigurationDirectory(path, s -> myConfigurationDirectoryText.setText(s), myProject, myMainPanel); - }); - } - - @Override - public @NotNull JComponent getComponent() { - return myMainPanel; - } - - @Override - public void reset(@NotNull SvnConfiguration configuration) { - String path = configuration.getConfigurationDirectory(); - if (configuration.isUseDefaultConfiguration() || path == null) { - path = USER_CONFIGURATION_PATH.getValue().toString(); - } - myConfigurationDirectoryText.setText(path); - myUseCustomConfigurationDirectory.setSelected(!configuration.isUseDefaultConfiguration()); - - boolean enabled = myUseCustomConfigurationDirectory.isSelected(); - myConfigurationDirectoryText.setEnabled(enabled); - myConfigurationDirectoryText.setEditable(enabled); - - myRunUnderTerminal.setSelected(configuration.isRunUnderTerminal()); - final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance(); - myCommandLineClient.setText(applicationSettings17.getCommandLinePath()); - } - - @Override - public boolean isModified(@NotNull SvnConfiguration configuration) { - if (configuration.isUseDefaultConfiguration() == myUseCustomConfigurationDirectory.isSelected()) { - return true; - } - if (configuration.isRunUnderTerminal() != myRunUnderTerminal.isSelected()) return true; - final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance(); - if (!Objects.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim())) return true; - if (!configuration.getConfigurationDirectory().equals(myConfigurationDirectoryText.getText().trim())) return true; - - return false; - } - - @Override - public void apply(@NotNull SvnConfiguration configuration) { - configuration.setConfigurationDirParameters(!myUseCustomConfigurationDirectory.isSelected(), myConfigurationDirectoryText.getText()); - - final SvnVcs vcs17 = SvnVcs.getInstance(myProject); - - final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance(); - boolean reloadWorkingCopies = !StringUtil.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim()); - configuration.setRunUnderTerminal(myRunUnderTerminal.isSelected()); - - applicationSettings17.setCommandLinePath(myCommandLineClient.getText().trim()); - boolean isClientValid = vcs17.checkCommandLineVersion(); - if (!myProject.isDefault() && isClientValid && reloadWorkingCopies) { - vcs17.invokeRefreshSvnRoots(); - VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty(); - } - } - - @Override - public void dispose() { - } - - private void createUIComponents() { - myCommandLineClient = new TextFieldWithBrowseButton(null, this); - myConfigurationDirectoryText = new TextFieldWithBrowseButton(null, this); - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSvnConfigurable.kt b/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSvnConfigurable.kt new file mode 100644 index 000000000000..e805fcec1706 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/GeneralSvnConfigurable.kt @@ -0,0 +1,141 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.svn + +import com.intellij.openapi.Disposable +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory +import com.intellij.openapi.options.BoundSearchableConfigurable +import com.intellij.openapi.options.Configurable.NoScroll +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.DialogPanel +import com.intellij.openapi.ui.TextFieldWithBrowseButton +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager +import com.intellij.ui.components.JBCheckBox +import com.intellij.ui.dsl.builder.AlignX +import com.intellij.ui.dsl.builder.RightGap +import com.intellij.ui.dsl.builder.bindSelected +import com.intellij.ui.dsl.builder.panel +import com.intellij.ui.layout.selected +import com.intellij.util.Consumer +import org.jetbrains.annotations.NonNls +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier + +internal class GeneralSvnConfigurable(private val project: Project) : BoundSearchableConfigurable( + SvnConfigurable.getGroupDisplayName(), + SvnConfigurable.HELP_ID, + SvnConfigurable.ID +), NoScroll, Disposable { + + private val commandLineClient = TextFieldWithBrowseButton(null, this) + private val configurationDirectoryText = TextFieldWithBrowseButton(null, this) + private lateinit var useCustomConfigurationDirectory: JBCheckBox + + init { + commandLineClient.addBrowseFolderListener(project, FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor() + .withTitle(SvnBundle.message("dialog.title.select.path.to.subversion.executable")) + .withDescription(SvnBundle.message("label.select.path.to.subversion.executable"))) + } + + override fun createPanel(): DialogPanel { + val settings = SvnConfiguration.getInstance(project) + lateinit var result: DialogPanel + + result = panel { + row(SvnBundle.message("label.path.to.svn.executable")) { + val applicationSettings17 = SvnApplicationSettings.getInstance() + cell(commandLineClient) + .align(AlignX.FILL) + .onReset { + commandLineClient.setText(applicationSettings17.commandLinePath) + }.onApply { + applicationSettings17.commandLinePath = commandLineClient.getText().trim() + }.onIsModified { + applicationSettings17.commandLinePath != commandLineClient.getText().trim() + } + } + + row { + checkBox(SvnBundle.message("command.line.interactive.mode.title")) + .comment(SvnBundle.message("command.line.interactive.mode.description")) + .bindSelected(settings::isRunUnderTerminal, settings::setRunUnderTerminal) + } + + row { + useCustomConfigurationDirectory = checkBox(SvnBundle.message("settings.use.custom.directory")) + .onChanged { + val configuration = SvnConfiguration.getInstance(project) + val path = configuration.getConfigurationDirectory() + if (!useCustomConfigurationDirectory.isSelected || path == null) { + configurationDirectoryText.setText(SvnUtil.USER_CONFIGURATION_PATH.getValue().toString()) + } + else { + configurationDirectoryText.setText(path) + } + }.gap(RightGap.SMALL) + .component + + cell(configurationDirectoryText) + .align(AlignX.FILL) + .enabledIf(useCustomConfigurationDirectory.selected) + } + + row { + label("") + }.resizableRow() + + row { + button(SvnBundle.message("button.text.clear.authentication.cache")) { + SvnAuthenticationNotifier.clearAuthenticationCache(project, result, configurationDirectoryText.getText()) + }.commentRight(SvnBundle.message("label.text.delete.stored.credentials")) + } + } + + configurationDirectoryText.addActionListener { _ -> + @NonNls val path = configurationDirectoryText.getText().trim() + SvnConfigurable.selectConfigurationDirectory(path, Consumer { s: String? -> configurationDirectoryText.setText(s) }, project, result) + } + + return result + } + + override fun apply() { + val settings = SvnConfiguration.getInstance(project) + val applicationSettings17 = SvnApplicationSettings.getInstance() + val oldCommandLinePath = applicationSettings17.commandLinePath + + super.apply() + + settings.setConfigurationDirParameters(!useCustomConfigurationDirectory.isSelected, configurationDirectoryText.getText()) + + val vcs17 = SvnVcs.getInstance(project) + val isClientValid = vcs17.checkCommandLineVersion() + if (!project.isDefault && isClientValid && oldCommandLinePath != applicationSettings17.commandLinePath) { + vcs17.invokeRefreshSvnRoots() + VcsDirtyScopeManager.getInstance(project).markEverythingDirty() + } + } + + override fun isModified(): Boolean { + val settings = SvnConfiguration.getInstance(project) + if (settings.isUseDefaultConfiguration == useCustomConfigurationDirectory.isSelected + || settings.getConfigurationDirectory() != configurationDirectoryText.getText().trim()) { + return true + } + + return super.isModified() + } + + override fun reset() { + super.reset() + + val settings = SvnConfiguration.getInstance(project) + var path = settings.getConfigurationDirectory() + if (settings.isUseDefaultConfiguration || path == null) { + path = SvnUtil.USER_CONFIGURATION_PATH.getValue().toString() + } + configurationDirectoryText.setText(path) + useCustomConfigurationDirectory.setSelected(!settings.isUseDefaultConfiguration) + } + + override fun dispose() { + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java index df2605f67f0d..19cad7ae02ab 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java @@ -62,12 +62,6 @@ public abstract class SvnConfigurable extends ConfigurableBase new GeneralSettingsPanel(project), HELP_ID); - } - } - public static class Ssh extends SvnConfigurable { public Ssh(@NotNull Project project) { super(project, "SSH", message("configurable.name.svn.ssh"), () -> new SshSettingsPanel(project));