From be8a0fdcdc16bc3ea6913da0cf89f967482f13ff Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Mon, 15 Apr 2024 21:13:53 +0300 Subject: [PATCH 01/13] Try to add validation to the widgets --- .../launching/ui/NewLanguageServerDialog.java | 6 +-- .../lsp4ij/settings/LanguageServerView.java | 7 +++ .../lsp4ij/settings/ui/CommandLineWidget.java | 46 +++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index a853e1823..e6696182f 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -189,11 +189,7 @@ private ValidationInfo validateServerName() { private ValidationInfo validateCommand() { var commandLine = this.languageServerPanel.getCommandLine(); - if (commandLine.getText().isBlank()) { - String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.commandLine.must.be.set"); - return new ValidationInfo(errorMessage, commandLine); - } - return null; + return commandLine.getValidationInfo(); } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index 6ab45a938..fbf49de17 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -19,13 +19,17 @@ import com.intellij.openapi.fileTypes.FileNameMatcher; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.ui.DocumentAdapter; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UI; +import com.redhat.devtools.lsp4ij.LanguageServerBundle; import com.redhat.devtools.lsp4ij.LanguageServersRegistry; import com.redhat.devtools.lsp4ij.internal.StringUtils; import com.redhat.devtools.lsp4ij.launching.ServerMappingSettings; +import com.redhat.devtools.lsp4ij.launching.ui.NewLanguageServerDialog; import com.redhat.devtools.lsp4ij.server.definition.LanguageServerDefinition; import com.redhat.devtools.lsp4ij.server.definition.LanguageServerFileAssociation; import com.redhat.devtools.lsp4ij.server.definition.launching.UserDefinedLanguageServerDefinition; @@ -36,6 +40,9 @@ import javax.swing.*; import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.text.JTextComponent; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index 57c3dd281..793c9c1b0 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -13,14 +13,26 @@ *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; +import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.JBColor; import com.intellij.ui.components.JBTextArea; import com.intellij.util.ui.JBFont; import com.redhat.devtools.lsp4ij.LanguageServerBundle; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; +import java.awt.*; /** * Command line widget used to fill the command to start a language server. */ public class CommandLineWidget extends JBTextArea { + private boolean isValid = true; + private String errorMessage = "Not Valid!"; + private Border normalBorder; public CommandLineWidget() { super(5, 0); @@ -28,5 +40,39 @@ public CommandLineWidget() { super.setWrapStyleWord(true); super.setFont(JBFont.regular()); super.getEmptyText().setText(LanguageServerBundle.message("language.server.command.emptyText")); + this.normalBorder = this.getBorder(); + this.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(@NotNull final DocumentEvent e){ + validateInput(); + } + }); + } + + private void validateInput() { + if (getText().isBlank()) { + isValid = false; + setErrorBorder(); + } else { + isValid = true; + setNormalBorder(); + } + } + + private void setNormalBorder() { + this.setBorder(normalBorder); + this.setToolTipText(null); + } + + private void setErrorBorder() { + this.setBorder(BorderFactory.createLineBorder(JBColor.RED)); + this.setToolTipText(errorMessage); + } + + public ValidationInfo getValidationInfo() { + if (!isValid) { + return new ValidationInfo(errorMessage, this); + } + return null; } } From 1527f023b34661939843b1ec1bef3d3ff580ce4a Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 17 Apr 2024 06:30:47 +0300 Subject: [PATCH 02/13] Initial setup with a shared error border setter --- .../launching/ui/NewLanguageServerDialog.java | 7 +-- .../lsp4ij/settings/LanguageServerView.java | 34 ++++++++++---- .../lsp4ij/settings/ui/CommandLineWidget.java | 16 ++----- .../settings/ui/LanguageServerPanel.java | 11 ++--- .../lsp4ij/settings/ui/ServerNameWidget.java | 44 +++++++++++++++++++ .../settings/ui/ValidatableConsoleWidget.java | 19 ++++++++ 6 files changed, 97 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index e6696182f..3778b98ab 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -180,11 +180,7 @@ private void addValidationInfo(ValidationInfo validationInfo, ListSuspend and wait for a debugger? * */ -public class LanguageServerView implements Disposable { +public class LanguageServerView extends DialogWrapper implements Disposable { private final LanguageServerNameProvider languageServerNameProvider; @@ -77,6 +71,8 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini @Nullable LanguageServerNameProvider languageServerNameProvider, @NotNull Project project ) { + super(true); + super.setTitle("Doesn't show anywhere"); this.languageServerDefinition = languageServerDefinition; this.languageServerNameProvider = languageServerNameProvider; this.project = project; @@ -90,6 +86,16 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini JPanel wrapper = JBUI.Panels.simplePanel(settingsPanel); wrapper.setBorder(JBUI.Borders.emptyLeft(10)); this.myMainPanel = wrapper; + init(); + initValidation(); + } + + /** + * + * @return + */ + public boolean isValid() { + return this.languageServerPanel.getCommandLine().getValidationInfo() == null; } /** @@ -417,6 +423,16 @@ public void setInitializationOptionsContent(String initializationOptionsContent) initializationOptions.setCaretPosition(0); } + @Override + protected @Nullable JComponent createCenterPanel() { + return myMainPanel; + } + + @Override + protected @Nullable ValidationInfo doValidate() { + return this.languageServerPanel.getCommandLine().getValidationInfo(); + } + @Override public void dispose() { } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index 793c9c1b0..c75a095ed 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -15,24 +15,21 @@ import com.intellij.openapi.ui.ValidationInfo; import com.intellij.ui.DocumentAdapter; -import com.intellij.ui.JBColor; import com.intellij.ui.components.JBTextArea; import com.intellij.util.ui.JBFont; import com.redhat.devtools.lsp4ij.LanguageServerBundle; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import javax.swing.border.Border; import javax.swing.event.DocumentEvent; -import java.awt.*; /** * Command line widget used to fill the command to start a language server. */ public class CommandLineWidget extends JBTextArea { private boolean isValid = true; - private String errorMessage = "Not Valid!"; - private Border normalBorder; + private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.commandLine.must.be.set"); + private final Border normalBorder; public CommandLineWidget() { super(5, 0); @@ -47,12 +44,13 @@ protected void textChanged(@NotNull final DocumentEvent e){ validateInput(); } }); + validateInput(); } private void validateInput() { if (getText().isBlank()) { isValid = false; - setErrorBorder(); + ValidatableConsoleWidget.setErrorBorder(this); } else { isValid = true; setNormalBorder(); @@ -61,12 +59,6 @@ private void validateInput() { private void setNormalBorder() { this.setBorder(normalBorder); - this.setToolTipText(null); - } - - private void setErrorBorder() { - this.setBorder(BorderFactory.createLineBorder(JBColor.RED)); - this.setToolTipText(errorMessage); } public ValidationInfo getValidationInfo() { diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java index a7660f94e..ace1bc153 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java @@ -13,13 +13,10 @@ import com.intellij.execution.configuration.EnvironmentVariablesComponent; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.ui.ComboBox; -import com.intellij.ui.ContextHelpLabel; -import com.intellij.ui.PortField; -import com.intellij.ui.SimpleListCellRenderer; +import com.intellij.ui.*; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBTabbedPane; -import com.intellij.ui.components.JBTextField; import com.intellij.ui.scale.JBUIScale; import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.components.BorderLayoutPanel; @@ -49,7 +46,7 @@ public enum EditionMode { EDIT_EXTENSION; } - private JBTextField serverName; + private ServerNameWidget serverName; private EnvironmentVariablesComponent environmentVariables; private CommandLineWidget commandLine; private ServerMappingsPanel mappingsPanel; @@ -176,7 +173,7 @@ private static FormBuilder addTab(JBTabbedPane tabbedPane, String tabTitle, bool } private void createServerNameField(FormBuilder builder) { - serverName = new JBTextField(); + serverName = new ServerNameWidget(); builder.addLabeledComponent(LanguageServerBundle.message("language.server.serverName"), serverName); } @@ -201,7 +198,7 @@ private void createInitializationOptionsTabField(FormBuilder builder) { builder.addLabeledComponent(LanguageServerBundle.message("language.server.initializationOptions"), scrollPane, true); } - public JBTextField getServerName() { + public ServerNameWidget getServerName() { return serverName; } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java new file mode 100644 index 000000000..4ba757932 --- /dev/null +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -0,0 +1,44 @@ +package com.redhat.devtools.lsp4ij.settings.ui; + +import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.components.JBTextField; +import com.redhat.devtools.lsp4ij.LanguageServerBundle; +import org.jetbrains.annotations.NotNull; + +import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; + +public class ServerNameWidget extends JBTextField { + private boolean isValid = true; + private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.serverName.must.be.set"); + private final transient Border normalBorder; + + public ServerNameWidget() { + this.normalBorder = this.getBorder(); + this.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(@NotNull final DocumentEvent e){ + validateInput(); + } + }); + validateInput(); + } + + public void validateInput() { + if (getText().isBlank()) { + isValid = false; + ValidatableConsoleWidget.setErrorBorder(this); + } else { + isValid = true; + this.setBorder(normalBorder); + } + } + + public ValidationInfo getValidationInfo() { + if (!isValid) { + return new ValidationInfo(errorMessage, this); + } + return null; + } +} diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java new file mode 100644 index 000000000..d633cf37c --- /dev/null +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -0,0 +1,19 @@ +package com.redhat.devtools.lsp4ij.settings.ui; + +import com.intellij.ui.JBColor; +import com.intellij.util.ui.JBUI; + +import javax.swing.*; +import java.awt.*; + +public class ValidatableConsoleWidget { + private ValidatableConsoleWidget() { + // Prevent init + } + + public static void setErrorBorder(JComponent jComponent) { + Color color = JBColor.red; + color = color.darker(); + jComponent.setBorder(JBUI.Borders.customLine(color, 1)); + } +} \ No newline at end of file From a43d3ab578d610f674dca67c47bb42fb6e6024fa Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 17 Apr 2024 07:13:14 +0300 Subject: [PATCH 03/13] Create a shared interface to simplify --- .../lsp4ij/settings/ui/CommandLineWidget.java | 24 +++------ .../lsp4ij/settings/ui/ServerNameWidget.java | 22 +++----- .../settings/ui/ValidatableConsoleWidget.java | 50 ++++++++++++++++--- 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index c75a095ed..ff29e28b9 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -14,19 +14,16 @@ package com.redhat.devtools.lsp4ij.settings.ui; import com.intellij.openapi.ui.ValidationInfo; -import com.intellij.ui.DocumentAdapter; import com.intellij.ui.components.JBTextArea; import com.intellij.util.ui.JBFont; import com.redhat.devtools.lsp4ij.LanguageServerBundle; -import org.jetbrains.annotations.NotNull; import javax.swing.border.Border; -import javax.swing.event.DocumentEvent; /** * Command line widget used to fill the command to start a language server. */ -public class CommandLineWidget extends JBTextArea { +public class CommandLineWidget extends JBTextArea implements ValidatableConsoleWidget { private boolean isValid = true; private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.commandLine.must.be.set"); private final Border normalBorder; @@ -38,29 +35,20 @@ public CommandLineWidget() { super.setFont(JBFont.regular()); super.getEmptyText().setText(LanguageServerBundle.message("language.server.command.emptyText")); this.normalBorder = this.getBorder(); - this.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(@NotNull final DocumentEvent e){ - validateInput(); - } - }); - validateInput(); + addListeners(this); } - private void validateInput() { + @Override + public void validateInput() { if (getText().isBlank()) { isValid = false; - ValidatableConsoleWidget.setErrorBorder(this); + setErrorBorder(this); } else { isValid = true; - setNormalBorder(); + this.setBorder(normalBorder); } } - private void setNormalBorder() { - this.setBorder(normalBorder); - } - public ValidationInfo getValidationInfo() { if (!isValid) { return new ValidationInfo(errorMessage, this); diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java index 4ba757932..de9c24919 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -1,37 +1,29 @@ package com.redhat.devtools.lsp4ij.settings.ui; import com.intellij.openapi.ui.ValidationInfo; -import com.intellij.ui.DocumentAdapter; import com.intellij.ui.components.JBTextField; import com.redhat.devtools.lsp4ij.LanguageServerBundle; -import org.jetbrains.annotations.NotNull; import javax.swing.border.Border; -import javax.swing.event.DocumentEvent; -public class ServerNameWidget extends JBTextField { +public class ServerNameWidget extends JBTextField implements ValidatableConsoleWidget { private boolean isValid = true; private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.serverName.must.be.set"); - private final transient Border normalBorder; + private final transient Border originalBorder; public ServerNameWidget() { - this.normalBorder = this.getBorder(); - this.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(@NotNull final DocumentEvent e){ - validateInput(); - } - }); - validateInput(); + this.originalBorder = this.getBorder(); + addListeners(this); } + @Override public void validateInput() { if (getText().isBlank()) { isValid = false; - ValidatableConsoleWidget.setErrorBorder(this); + setErrorBorder(this); } else { isValid = true; - this.setBorder(normalBorder); + this.setBorder(originalBorder); } } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java index d633cf37c..d2bff6529 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -1,19 +1,57 @@ package com.redhat.devtools.lsp4ij.settings.ui; +import com.intellij.ui.DocumentAdapter; import com.intellij.ui.JBColor; +import com.intellij.ui.components.JBTextArea; +import com.intellij.ui.components.JBTextField; import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.event.DocumentEvent; import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; -public class ValidatableConsoleWidget { - private ValidatableConsoleWidget() { - // Prevent init - } - - public static void setErrorBorder(JComponent jComponent) { +/** + * A shared interface meant to simplify creating validatable components used in + * NewLanguageServerDialog and LanguageServerView (LSP console) + */ +public interface ValidatableConsoleWidget { + /** + * + * @param jComponent + */ + default void setErrorBorder(JComponent jComponent) { Color color = JBColor.red; color = color.darker(); jComponent.setBorder(JBUI.Borders.customLine(color, 1)); } + + default void addListeners(JComponent jComponent) { + jComponent.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + validateInput(); + super.focusGained(e); + } + }); + + if (jComponent instanceof JBTextField || jComponent instanceof JBTextArea) { + DocumentAdapter adapter = new DocumentAdapter() { + @Override + protected void textChanged(@NotNull DocumentEvent e) { + validateInput(); + } + }; + + if (jComponent instanceof JBTextField jbTextField) { + jbTextField.getDocument().addDocumentListener(adapter); + } else if (jComponent instanceof JBTextArea jbTextArea) { + jbTextArea.getDocument().addDocumentListener(adapter); + } + } + } + + void validateInput(); } \ No newline at end of file From d76179e44dbae0c51cf054e12b9a111d1e731a9e Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 17 Apr 2024 07:17:15 +0300 Subject: [PATCH 04/13] Add javadoc for ValidatableConsoleWidget --- .../settings/ui/ValidatableConsoleWidget.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java index d2bff6529..8b1394c2d 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -19,8 +19,8 @@ */ public interface ValidatableConsoleWidget { /** - * - * @param jComponent + * Set a common error border for the widget + * @param jComponent interface implementor (e.g. setErrorBorder(this);) */ default void setErrorBorder(JComponent jComponent) { Color color = JBColor.red; @@ -28,6 +28,11 @@ default void setErrorBorder(JComponent jComponent) { jComponent.setBorder(JBUI.Borders.customLine(color, 1)); } + /** + * Add listeners that handle input validation. The first instance of validation should run on focus + * and then on change + * @param jComponent interface implementor (e.g. addListeners(this);) + */ default void addListeners(JComponent jComponent) { jComponent.addFocusListener(new FocusAdapter() { @Override @@ -37,21 +42,21 @@ public void focusGained(FocusEvent e) { } }); - if (jComponent instanceof JBTextField || jComponent instanceof JBTextArea) { - DocumentAdapter adapter = new DocumentAdapter() { - @Override - protected void textChanged(@NotNull DocumentEvent e) { - validateInput(); - } - }; - - if (jComponent instanceof JBTextField jbTextField) { - jbTextField.getDocument().addDocumentListener(adapter); - } else if (jComponent instanceof JBTextArea jbTextArea) { - jbTextArea.getDocument().addDocumentListener(adapter); + DocumentAdapter adapter = new DocumentAdapter() { + @Override + protected void textChanged(@NotNull DocumentEvent e) { + validateInput(); } + }; + if (jComponent instanceof JBTextField jbTextField) { + jbTextField.getDocument().addDocumentListener(adapter); + } else if (jComponent instanceof JBTextArea jbTextArea) { + jbTextArea.getDocument().addDocumentListener(adapter); } } + /** + * Overridable method that implements the field validation + */ void validateInput(); } \ No newline at end of file From 36990bf0e0a3bd6012dd6629826ecb55161a6b42 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 17 Apr 2024 07:22:28 +0300 Subject: [PATCH 05/13] Don't enable presentation if language server view is not valid --- .../console/actions/ApplyLanguageServerSettingsAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java b/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java index 9330afe68..8a49ee38b 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java @@ -76,7 +76,7 @@ public void update(@NotNull AnActionEvent e) { } } - e.getPresentation().setEnabled(modified); + e.getPresentation().setEnabled(modified && languageServerView.isValid()); } @Override From 922296be6ee4c1b6c225966582ef270fc3b4cec4 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 17 Apr 2024 08:58:04 +0300 Subject: [PATCH 06/13] Remove unnecessary methods --- .../launching/ui/NewLanguageServerDialog.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index 3778b98ab..3fac089ad 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -166,8 +166,8 @@ public JComponent getPreferredFocusedComponent() { @Override protected @NotNull List doValidateAll() { List validations = new ArrayList<>(); - addValidationInfo(validateServerName(), validations); - addValidationInfo(validateCommand(), validations); + addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); + addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); return validations; } @@ -178,15 +178,6 @@ private void addValidationInfo(ValidationInfo validationInfo, List Date: Thu, 18 Apr 2024 06:53:48 +0300 Subject: [PATCH 07/13] Add license information, some docs and streamline validation interface --- .../launching/ui/NewLanguageServerDialog.java | 4 +-- .../lsp4ij/settings/LanguageServerView.java | 5 ++- .../lsp4ij/settings/ui/CommandLineWidget.java | 28 ++++++++------- .../lsp4ij/settings/ui/ServerNameWidget.java | 36 +++++++++++++------ .../settings/ui/ValidatableConsoleWidget.java | 26 +++++++++++++- 5 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index 3fac089ad..189a7d5d1 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -166,8 +166,8 @@ public JComponent getPreferredFocusedComponent() { @Override protected @NotNull List doValidateAll() { List validations = new ArrayList<>(); - addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); - addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); + addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); + addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); return validations; } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index 0475e2246..90e8a5b8d 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -10,6 +10,7 @@ * * Contributors: * Red Hat Inc. - initial API and implementation + * Mitja Leino - Implement DialogWrapper for validations *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings; @@ -95,7 +96,8 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini * @return */ public boolean isValid() { - return this.languageServerPanel.getCommandLine().getValidationInfo() == null; + return this.languageServerPanel.getCommandLine().isValid() + && this.languageServerPanel.getServerName().isValid(); } /** @@ -430,6 +432,7 @@ public void setInitializationOptionsContent(String initializationOptionsContent) @Override protected @Nullable ValidationInfo doValidate() { + // Server name is not editable for existing language server return this.languageServerPanel.getCommandLine().getValidationInfo(); } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index ff29e28b9..b97a0a85d 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -21,12 +21,12 @@ import javax.swing.border.Border; /** - * Command line widget used to fill the command to start a language server. + * Command line widget used to fill the command to start a language + * server when creating a new or modifying an existing LS configuration */ public class CommandLineWidget extends JBTextArea implements ValidatableConsoleWidget { - private boolean isValid = true; private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.commandLine.must.be.set"); - private final Border normalBorder; + private final transient Border normalBorder; public CommandLineWidget() { super(5, 0); @@ -40,19 +40,23 @@ public CommandLineWidget() { @Override public void validateInput() { - if (getText().isBlank()) { - isValid = false; - setErrorBorder(this); - } else { - isValid = true; + if (isValid()) { this.setBorder(normalBorder); + } else { + setErrorBorder(this); } } + @Override public ValidationInfo getValidationInfo() { - if (!isValid) { - return new ValidationInfo(errorMessage, this); + if (isValid()) { + return null; } - return null; + return new ValidationInfo(errorMessage, this); + } + + @Override + public boolean isValid() { + return getDocument() != null && !getText().isBlank(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java index de9c24919..b827d4a77 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat Inc. and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Mitja Leino - Initial API and implementation + *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; import com.intellij.openapi.ui.ValidationInfo; @@ -6,8 +17,10 @@ import javax.swing.border.Border; +/** + * Server name widget that contains the server name when creating a new LS configuration + */ public class ServerNameWidget extends JBTextField implements ValidatableConsoleWidget { - private boolean isValid = true; private final String errorMessage = LanguageServerBundle.message("new.language.server.dialog.validation.serverName.must.be.set"); private final transient Border originalBorder; @@ -18,19 +31,22 @@ public ServerNameWidget() { @Override public void validateInput() { - if (getText().isBlank()) { - isValid = false; - setErrorBorder(this); - } else { - isValid = true; + if (isValid()) { this.setBorder(originalBorder); + } else { + setErrorBorder(this); } } public ValidationInfo getValidationInfo() { - if (!isValid) { - return new ValidationInfo(errorMessage, this); + if (isValid()) { + return null; } - return null; + return new ValidationInfo(errorMessage, this); + } + + @Override + public boolean isValid() { + return getDocument() != null && !getText().isBlank(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java index 8b1394c2d..761d00444 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -1,5 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat Inc. and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Mitja Leino - Initial API and implementation + *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; +import com.intellij.openapi.ui.ValidationInfo; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.JBColor; import com.intellij.ui.components.JBTextArea; @@ -30,7 +42,7 @@ default void setErrorBorder(JComponent jComponent) { /** * Add listeners that handle input validation. The first instance of validation should run on focus - * and then on change + * and then on each change * @param jComponent interface implementor (e.g. addListeners(this);) */ default void addListeners(JComponent jComponent) { @@ -57,6 +69,18 @@ protected void textChanged(@NotNull DocumentEvent e) { /** * Overridable method that implements the field validation + * Handles updating the style of the component for error/valid */ void validateInput(); + + /** + * Overridable method that returns a ValidationInfo, is the component is not valid + * @return a ValidationInfo element if component validation fails, null if component is valid + */ + ValidationInfo getValidationInfo(); + + /** + * Overridable method that has to implement the validation check + */ + boolean isValid(); } \ No newline at end of file From b52251b05887eaddd759bc30f80475ca921d3e88 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Fri, 19 Apr 2024 06:06:54 +0300 Subject: [PATCH 08/13] Clean up --- .../actions/ApplyLanguageServerSettingsAction.java | 2 +- .../lsp4ij/settings/LanguageServerView.java | 14 +------------- .../lsp4ij/settings/ui/CommandLineWidget.java | 1 + 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java b/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java index 8a49ee38b..9330afe68 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/console/actions/ApplyLanguageServerSettingsAction.java @@ -76,7 +76,7 @@ public void update(@NotNull AnActionEvent e) { } } - e.getPresentation().setEnabled(modified && languageServerView.isValid()); + e.getPresentation().setEnabled(modified); } @Override diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index 90e8a5b8d..c694ffcb2 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -73,7 +73,6 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini @NotNull Project project ) { super(true); - super.setTitle("Doesn't show anywhere"); this.languageServerDefinition = languageServerDefinition; this.languageServerNameProvider = languageServerNameProvider; this.project = project; @@ -87,17 +86,6 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini JPanel wrapper = JBUI.Panels.simplePanel(settingsPanel); wrapper.setBorder(JBUI.Borders.emptyLeft(10)); this.myMainPanel = wrapper; - init(); - initValidation(); - } - - /** - * - * @return - */ - public boolean isValid() { - return this.languageServerPanel.getCommandLine().isValid() - && this.languageServerPanel.getServerName().isValid(); } /** @@ -432,7 +420,7 @@ public void setInitializationOptionsContent(String initializationOptionsContent) @Override protected @Nullable ValidationInfo doValidate() { - // Server name is not editable for existing language server + // Server name is not editable for existing language servers return this.languageServerPanel.getCommandLine().getValidationInfo(); } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index b97a0a85d..328ddb360 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -10,6 +10,7 @@ * * Contributors: * Red Hat Inc. - initial API and implementation + * Mitja Leino - Implement ValidatableConsoleWidget *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; From cd623f8bde3fa63b08486f95fd279e376b56b280 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Fri, 19 Apr 2024 06:12:55 +0300 Subject: [PATCH 09/13] Fix indent --- .../devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index 189a7d5d1..8c0df20aa 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -166,8 +166,8 @@ public JComponent getPreferredFocusedComponent() { @Override protected @NotNull List doValidateAll() { List validations = new ArrayList<>(); - addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); - addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); + addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); + addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); return validations; } From cf6779ff0a868d83bdc804e1d8b3b996641c8175 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Fri, 19 Apr 2024 06:14:33 +0300 Subject: [PATCH 10/13] Add missing overrider --- .../com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java index b827d4a77..3d9387f13 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -38,6 +38,7 @@ public void validateInput() { } } + @Override public ValidationInfo getValidationInfo() { if (isValid()) { return null; From 6c8f0c0faba2a00352c9520fc2efa0a5403b7e90 Mon Sep 17 00:00:00 2001 From: "mitja.leino" Date: Sun, 21 Apr 2024 20:53:10 +0300 Subject: [PATCH 11/13] Add ValidatableDialog class --- .../launching/ui/NewLanguageServerDialog.java | 19 ++------ .../lsp4ij/settings/LanguageServerView.java | 7 +-- .../settings/ui/LanguageServerPanel.java | 45 ++++++++++++++++++- .../lsp4ij/settings/ui/ValidatableDialog.java | 19 ++++++++ 4 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index 8c0df20aa..450c67aa3 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -12,7 +12,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.SimpleListCellRenderer; @@ -25,6 +24,7 @@ import com.redhat.devtools.lsp4ij.launching.templates.LanguageServerTemplateManager; import com.redhat.devtools.lsp4ij.server.definition.launching.UserDefinedLanguageServerDefinition; import com.redhat.devtools.lsp4ij.settings.ui.LanguageServerPanel; +import com.redhat.devtools.lsp4ij.settings.ui.ValidatableDialog; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,7 +40,7 @@ /** * New language server dialog. */ -public class NewLanguageServerDialog extends DialogWrapper { +public class NewLanguageServerDialog extends ValidatableDialog { private final ComboBox templateCombo = new ComboBox<>(new DefaultComboBoxModel<>(getLanguageServerTemplates())); private final Project project; @@ -70,7 +70,7 @@ public NewLanguageServerDialog(@NotNull Project project) { // Template combo createTemplateCombo(builder); // Create server name, command line, mappings, configuration UI - this.languageServerPanel = new LanguageServerPanel(builder, null, LanguageServerPanel.EditionMode.NEW_USER_DEFINED); + this.languageServerPanel = new LanguageServerPanel(builder, null, LanguageServerPanel.EditionMode.NEW_USER_DEFINED, this); // Add validation addValidator(this.languageServerPanel.getServerName()); @@ -165,20 +165,9 @@ public JComponent getPreferredFocusedComponent() { @Override protected @NotNull List doValidateAll() { - List validations = new ArrayList<>(); - addValidationInfo(this.languageServerPanel.getCommandLine().getValidationInfo(), validations); - addValidationInfo(this.languageServerPanel.getServerName().getValidationInfo(), validations); - return validations; + return languageServerPanel.doValidateAll(); } - private void addValidationInfo(ValidationInfo validationInfo, List validations) { - if (validationInfo == null) { - return; - } - validations.add((validationInfo)); - } - - @Override protected void doOKAction() { super.doOKAction(); diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index c694ffcb2..85214abc1 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -34,6 +34,7 @@ import com.redhat.devtools.lsp4ij.server.definition.launching.UserDefinedLanguageServerDefinition; import com.redhat.devtools.lsp4ij.settings.ui.LanguageServerPanel; import com.redhat.devtools.lsp4ij.settings.ui.ServerMappingsPanel; +import com.redhat.devtools.lsp4ij.settings.ui.ValidatableDialog; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,7 +53,7 @@ *
  • Suspend and wait for a debugger?
  • * */ -public class LanguageServerView extends DialogWrapper implements Disposable { +public class LanguageServerView extends ValidatableDialog implements Disposable { private final LanguageServerNameProvider languageServerNameProvider; @@ -72,7 +73,7 @@ public LanguageServerView(@NotNull LanguageServerDefinition languageServerDefini @Nullable LanguageServerNameProvider languageServerNameProvider, @NotNull Project project ) { - super(true); + super(project); this.languageServerDefinition = languageServerDefinition; this.languageServerNameProvider = languageServerNameProvider; this.project = project; @@ -288,7 +289,7 @@ private JPanel createSettings(JComponent description, boolean launchingServerDef this.languageServerPanel = new LanguageServerPanel(builder, description, launchingServerDefinition ? LanguageServerPanel.EditionMode.EDIT_USER_DEFINED : - LanguageServerPanel.EditionMode.EDIT_EXTENSION); + LanguageServerPanel.EditionMode.EDIT_EXTENSION, this); this.mappingPanel = languageServerPanel.getMappingsPanel(); return builder .addComponentFillVertically(new JPanel(), 50) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java index ace1bc153..5fd246f00 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java @@ -13,6 +13,7 @@ import com.intellij.execution.configuration.EnvironmentVariablesComponent; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.ValidationInfo; import com.intellij.ui.*; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBScrollPane; @@ -26,7 +27,11 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.text.JTextComponent; import java.awt.*; +import java.util.ArrayList; +import java.util.List; /** * Language server panel which show information about language server in several tabs: @@ -58,8 +63,10 @@ public enum EditionMode { private LanguageServerConfigurationWidget configurationWidget; private LanguageServerInitializationOptionsWidget initializationOptionsWidget; + private final ValidatableDialog dialogWrapper; - public LanguageServerPanel(FormBuilder builder, JComponent description, EditionMode mode) { + public LanguageServerPanel(FormBuilder builder, JComponent description, EditionMode mode, ValidatableDialog dialogWrapper) { + this.dialogWrapper = dialogWrapper; createUI(builder, description, mode); } @@ -77,6 +84,13 @@ private void createUI(FormBuilder builder, JComponent description, EditionMode m } // Debug tab addDebugTab(tabbedPane, mode); + + // Add validation + var serverName = getServerName(); + if (serverName != null) { + addValidator(serverName); + } + addValidator(getCommandLine()); } private void addServerTab(JBTabbedPane tabbedPane, JComponent description, EditionMode mode) { @@ -238,4 +252,33 @@ public ComboBox getErrorReportingKindCombo() { return errorReportingKindCombo; } + public @NotNull List doValidateAll() { + List validations = new ArrayList<>(); + var serverName = getServerName(); + if (serverName != null) { + addValidationInfo(serverName.getValidationInfo(), validations); + } + var commandLine = getCommandLine(); + if (commandLine != null) { + addValidationInfo(commandLine.getValidationInfo(), validations); + } + return validations; + } + + private void addValidationInfo(ValidationInfo validationInfo, List validations) { + if (validationInfo == null) { + return; + } + validations.add((validationInfo)); + } + + + private void addValidator(JTextComponent textComponent) { + textComponent.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(@NotNull DocumentEvent e) { + dialogWrapper.refreshValidation(); + } + }); + } } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java new file mode 100644 index 000000000..b38cfbf11 --- /dev/null +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java @@ -0,0 +1,19 @@ +package com.redhat.devtools.lsp4ij.settings.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; + +public abstract class ValidatableDialog extends DialogWrapper { + public ValidatableDialog(Project project) { + super(project); + } + + public void refreshValidation() { + super.initValidation(); + } + + @Override + protected boolean continuousValidation() { + return false; + } +} From 2de6a9f03382c6a50d5e2f9790796d11c30bda7d Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Mon, 22 Apr 2024 21:10:06 +0300 Subject: [PATCH 12/13] Simplify and unify validations --- .../lsp4ij/settings/LanguageServerView.java | 5 +- .../lsp4ij/settings/ui/CommandLineWidget.java | 25 +++------ .../settings/ui/LanguageServerPanel.java | 20 +++---- .../lsp4ij/settings/ui/ServerNameWidget.java | 20 +++---- .../settings/ui/ValidatableConsoleWidget.java | 52 +------------------ 5 files changed, 26 insertions(+), 96 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index 85214abc1..9082b2694 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -420,9 +420,8 @@ public void setInitializationOptionsContent(String initializationOptionsContent) } @Override - protected @Nullable ValidationInfo doValidate() { - // Server name is not editable for existing language servers - return this.languageServerPanel.getCommandLine().getValidationInfo(); + public @NotNull List doValidateAll() { + return languageServerPanel.doValidateAll(); } @Override diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index 328ddb360..82c22f42c 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -20,6 +20,7 @@ import com.redhat.devtools.lsp4ij.LanguageServerBundle; import javax.swing.border.Border; +import java.util.List; /** * Command line widget used to fill the command to start a language @@ -36,28 +37,18 @@ public CommandLineWidget() { super.setFont(JBFont.regular()); super.getEmptyText().setText(LanguageServerBundle.message("language.server.command.emptyText")); this.normalBorder = this.getBorder(); - addListeners(this); } @Override - public void validateInput() { - if (isValid()) { - this.setBorder(normalBorder); - } else { + public void validate(List validations) { + boolean valid = true; + if (getDocument() != null && getText().isBlank()) { setErrorBorder(this); + valid = false; + validations.add(new ValidationInfo(errorMessage, this)); } - } - - @Override - public ValidationInfo getValidationInfo() { - if (isValid()) { - return null; + if (valid) { + this.setBorder(normalBorder); } - return new ValidationInfo(errorMessage, this); - } - - @Override - public boolean isValid() { - return getDocument() != null && !getText().isBlank(); } } \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java index 5fd246f00..44e8b7ccb 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java @@ -254,25 +254,17 @@ public ComboBox getErrorReportingKindCombo() { public @NotNull List doValidateAll() { List validations = new ArrayList<>(); - var serverName = getServerName(); - if (serverName != null) { - addValidationInfo(serverName.getValidationInfo(), validations); + var serverNameWidget = getServerName(); + if (serverNameWidget != null) { + serverNameWidget.validate(validations); } - var commandLine = getCommandLine(); - if (commandLine != null) { - addValidationInfo(commandLine.getValidationInfo(), validations); + var commandLineWidget = getCommandLine(); + if (commandLineWidget != null) { + commandLineWidget.validate(validations); } return validations; } - private void addValidationInfo(ValidationInfo validationInfo, List validations) { - if (validationInfo == null) { - return; - } - validations.add((validationInfo)); - } - - private void addValidator(JTextComponent textComponent) { textComponent.getDocument().addDocumentListener(new DocumentAdapter() { @Override diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java index 3d9387f13..b9e9ecde5 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -16,6 +16,7 @@ import com.redhat.devtools.lsp4ij.LanguageServerBundle; import javax.swing.border.Border; +import java.util.List; /** * Server name widget that contains the server name when creating a new LS configuration @@ -26,24 +27,19 @@ public class ServerNameWidget extends JBTextField implements ValidatableConsoleW public ServerNameWidget() { this.originalBorder = this.getBorder(); - addListeners(this); } @Override - public void validateInput() { - if (isValid()) { - this.setBorder(originalBorder); - } else { + public void validate(List validations) { + boolean isValid = true; + if (getDocument() != null && getText().isBlank()) { setErrorBorder(this); + isValid = false; + validations.add(new ValidationInfo(errorMessage, this)); } - } - - @Override - public ValidationInfo getValidationInfo() { - if (isValid()) { - return null; + if (isValid) { + this.setBorder(originalBorder); } - return new ValidationInfo(errorMessage, this); } @Override diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java index 761d00444..e67031371 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -12,18 +12,12 @@ package com.redhat.devtools.lsp4ij.settings.ui; import com.intellij.openapi.ui.ValidationInfo; -import com.intellij.ui.DocumentAdapter; import com.intellij.ui.JBColor; -import com.intellij.ui.components.JBTextArea; -import com.intellij.ui.components.JBTextField; import com.intellij.util.ui.JBUI; -import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.event.DocumentEvent; +import java.util.List; import java.awt.*; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; /** * A shared interface meant to simplify creating validatable components used in @@ -40,47 +34,5 @@ default void setErrorBorder(JComponent jComponent) { jComponent.setBorder(JBUI.Borders.customLine(color, 1)); } - /** - * Add listeners that handle input validation. The first instance of validation should run on focus - * and then on each change - * @param jComponent interface implementor (e.g. addListeners(this);) - */ - default void addListeners(JComponent jComponent) { - jComponent.addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - validateInput(); - super.focusGained(e); - } - }); - - DocumentAdapter adapter = new DocumentAdapter() { - @Override - protected void textChanged(@NotNull DocumentEvent e) { - validateInput(); - } - }; - if (jComponent instanceof JBTextField jbTextField) { - jbTextField.getDocument().addDocumentListener(adapter); - } else if (jComponent instanceof JBTextArea jbTextArea) { - jbTextArea.getDocument().addDocumentListener(adapter); - } - } - - /** - * Overridable method that implements the field validation - * Handles updating the style of the component for error/valid - */ - void validateInput(); - - /** - * Overridable method that returns a ValidationInfo, is the component is not valid - * @return a ValidationInfo element if component validation fails, null if component is valid - */ - ValidationInfo getValidationInfo(); - - /** - * Overridable method that has to implement the validation check - */ - boolean isValid(); + void validate(List validations); } \ No newline at end of file From 80a1f959b977ada7cfc6077043b949ae50ebc6b4 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Wed, 24 Apr 2024 05:50:33 +0300 Subject: [PATCH 13/13] Clean up and add missing docs --- .../launching/ui/NewLanguageServerDialog.java | 1 + .../lsp4ij/settings/LanguageServerView.java | 3 +-- .../lsp4ij/settings/ui/CommandLineWidget.java | 14 +++++++++----- .../lsp4ij/settings/ui/LanguageServerPanel.java | 12 ++++++++---- .../lsp4ij/settings/ui/ServerNameWidget.java | 14 +++++++++----- .../settings/ui/ValidatableConsoleWidget.java | 5 +++++ .../lsp4ij/settings/ui/ValidatableDialog.java | 16 +++++++++++++++- 7 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java index 450c67aa3..efc43917d 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/launching/ui/NewLanguageServerDialog.java @@ -7,6 +7,7 @@ * * Contributors: * Red Hat, Inc. - initial API and implementation + * Mitja Leino - Extend ValidatableDialog for validations ******************************************************************************/ package com.redhat.devtools.lsp4ij.launching.ui; diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java index 9082b2694..024408b3f 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/LanguageServerView.java @@ -10,7 +10,7 @@ * * Contributors: * Red Hat Inc. - initial API and implementation - * Mitja Leino - Implement DialogWrapper for validations + * Mitja Leino - Extend ValidatableDialog for validations *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings; @@ -20,7 +20,6 @@ import com.intellij.openapi.fileTypes.FileNameMatcher; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.ui.FormBuilder; diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java index 82c22f42c..2a96caa44 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/CommandLineWidget.java @@ -20,6 +20,7 @@ import com.redhat.devtools.lsp4ij.LanguageServerBundle; import javax.swing.border.Border; +import java.util.ArrayList; import java.util.List; /** @@ -41,14 +42,17 @@ public CommandLineWidget() { @Override public void validate(List validations) { - boolean valid = true; + List widgetValidations = new ArrayList<>(); + if (getDocument() != null && getText().isBlank()) { - setErrorBorder(this); - valid = false; - validations.add(new ValidationInfo(errorMessage, this)); + widgetValidations.add(new ValidationInfo(errorMessage, this)); } - if (valid) { + + if (widgetValidations.isEmpty()) { this.setBorder(normalBorder); + } else { + validations.addAll(widgetValidations); + setErrorBorder(this); } } } \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java index 44e8b7ccb..24abe38aa 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/LanguageServerPanel.java @@ -7,6 +7,7 @@ * * Contributors: * Red Hat, Inc. - initial API and implementation + * Mitja Leino - Add DialogWrapper for validations ******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; @@ -86,11 +87,14 @@ private void createUI(FormBuilder builder, JComponent description, EditionMode m addDebugTab(tabbedPane, mode); // Add validation - var serverName = getServerName(); - if (serverName != null) { - addValidator(serverName); + var serverNameWidget = getServerName(); + if (serverNameWidget != null) { + addValidator(serverNameWidget); + } + var commandLineWidget = getCommandLine(); + if (commandLineWidget != null) { + addValidator(getCommandLine()); } - addValidator(getCommandLine()); } private void addServerTab(JBTabbedPane tabbedPane, JComponent description, EditionMode mode) { diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java index b9e9ecde5..6b2d3c089 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ServerNameWidget.java @@ -16,6 +16,7 @@ import com.redhat.devtools.lsp4ij.LanguageServerBundle; import javax.swing.border.Border; +import java.util.ArrayList; import java.util.List; /** @@ -31,14 +32,17 @@ public ServerNameWidget() { @Override public void validate(List validations) { - boolean isValid = true; + List widgetValidations = new ArrayList<>(); + if (getDocument() != null && getText().isBlank()) { - setErrorBorder(this); - isValid = false; - validations.add(new ValidationInfo(errorMessage, this)); + widgetValidations.add(new ValidationInfo(errorMessage, this)); } - if (isValid) { + + if (widgetValidations.isEmpty()) { this.setBorder(originalBorder); + } else { + validations.addAll(widgetValidations); + setErrorBorder(this); } } diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java index e67031371..ab815af39 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableConsoleWidget.java @@ -34,5 +34,10 @@ default void setErrorBorder(JComponent jComponent) { jComponent.setBorder(JBUI.Borders.customLine(color, 1)); } + /** + * Runs validations on the widget and handles border styling + * @param validations the dialog wrapper validation list, + * adds the validations to the list if there are any errors + */ void validate(List validations); } \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java index b38cfbf11..c9852f892 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/settings/ui/ValidatableDialog.java @@ -1,10 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat Inc. and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Mitja Leino - Initial API and implementation + *******************************************************************************/ package com.redhat.devtools.lsp4ij.settings.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +/** + * Shareable component for shared validations using DialogWrapper + */ public abstract class ValidatableDialog extends DialogWrapper { - public ValidatableDialog(Project project) { + protected ValidatableDialog(Project project) { super(project); }