Skip to content

Commit 895cf17

Browse files
add error border/popup to input component on realtime validation error.
1 parent 442f881 commit 895cf17

File tree

2 files changed

+61
-19
lines changed

2 files changed

+61
-19
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-lib/src/main/java/com/microsoft/azure/toolkit/intellij/common/AzureDialog.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,22 @@
44
*/
55
package com.microsoft.azure.toolkit.intellij.common;
66

7+
import com.intellij.openapi.Disposable;
78
import com.intellij.openapi.project.Project;
89
import com.intellij.openapi.ui.DialogWrapper;
910
import com.intellij.openapi.ui.ValidationInfo;
11+
import com.intellij.openapi.util.Disposer;
1012
import com.microsoft.azure.toolkit.lib.common.form.AzureForm;
1113
import com.microsoft.azure.toolkit.lib.common.form.AzureFormInput;
1214
import com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo;
1315
import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
1416
import lombok.extern.java.Log;
1517

16-
import javax.swing.*;
1718
import java.util.List;
1819
import java.util.Objects;
19-
import java.util.Optional;
2020
import java.util.stream.Collectors;
2121

2222
import static com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo.Type.SUCCESS;
23-
import static com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo.Type.WARNING;
2423

2524
@Log
2625
public abstract class AzureDialog<T> extends DialogWrapper {
@@ -36,6 +35,16 @@ public AzureDialog() {
3635
this(null);
3736
}
3837

38+
@Override
39+
protected void init() {
40+
super.init();
41+
for (final AzureFormInput<?> input : this.getForm().getInputs()) {
42+
if (input instanceof Disposable) {
43+
Disposer.register(this.getDisposable(), (Disposable) input);
44+
}
45+
}
46+
}
47+
3948
@Override
4049
protected void doOKAction() {
4150
try {
@@ -57,23 +66,13 @@ public void close() {
5766
@Override
5867
protected List<ValidationInfo> doValidateAll() {
5968
final List<AzureValidationInfo> infos = this.getForm().getAllValidationInfos(true);
60-
this.setOKActionEnabled(infos.stream().allMatch(AzureValidationInfo::isValid));
69+
// this.setOKActionEnabled(infos.stream().allMatch(AzureValidationInfo::isValid));
6170
return infos.stream()
6271
.filter(i -> i.getType() != SUCCESS)
63-
.map(AzureDialog::toIntellijValidationInfo)
72+
.map(AzureFormInputComponent::toIntellijValidationInfo)
6473
.collect(Collectors.toList());
6574
}
6675

67-
private static ValidationInfo toIntellijValidationInfo(final AzureValidationInfo info) {
68-
final AzureFormInput<?> input = info.getInput();
69-
final JComponent component = input instanceof AzureFormInputComponent ? ((AzureFormInputComponent<?>) input).getInputComponent() : null;
70-
final ValidationInfo v = new ValidationInfo(Optional.ofNullable(info.getMessage()).orElse("Unknown error"), component);
71-
if (info.getType() == WARNING) {
72-
v.asWarning();
73-
}
74-
return v;
75-
}
76-
7776
public abstract AzureForm<T> getForm();
7877

7978
protected abstract String getDialogTitle();

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-lib/src/main/java/com/microsoft/azure/toolkit/intellij/common/AzureFormInputComponent.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,29 @@
55

66
package com.microsoft.azure.toolkit.intellij.common;
77

8+
import com.intellij.openapi.Disposable;
9+
import com.intellij.openapi.ui.ComponentValidator;
10+
import com.intellij.openapi.ui.ValidationInfo;
811
import com.microsoft.azure.toolkit.lib.common.form.AzureFormInput;
912
import com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo;
13+
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
1014

1115
import javax.accessibility.AccessibleRelation;
1216
import javax.annotation.Nonnull;
17+
import javax.annotation.Nullable;
1318
import javax.swing.*;
19+
import java.util.Objects;
1420
import java.util.Optional;
1521

16-
public interface AzureFormInputComponent<T> extends AzureFormInput<T> {
22+
import static com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo.Type.PENDING;
23+
import static com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo.Type.SUCCESS;
24+
import static com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo.Type.WARNING;
25+
26+
public interface AzureFormInputComponent<T> extends AzureFormInput<T>, Disposable {
1727
default JComponent getInputComponent() {
1828
return (JComponent) this;
1929
}
2030

21-
/**
22-
* NOTE: don't override
23-
*/
2431
@Nonnull
2532
@Override
2633
default AzureValidationInfo validateInternal(T value) {
@@ -30,11 +37,47 @@ default AzureValidationInfo validateInternal(T value) {
3037
return AzureFormInput.super.validateInternal(value);
3138
}
3239

40+
@Override
41+
default void setValidationInfo(@Nullable AzureValidationInfo vi) {
42+
AzureFormInput.super.setValidationInfo(vi);
43+
final ValidationInfo info = Objects.nonNull(vi) && (vi.getType() == PENDING || vi.getType() == SUCCESS) ? null : toIntellijValidationInfo(vi);
44+
final String state = Objects.isNull(info) ? null : info.warning ? "warning" : "error";
45+
final JComponent input = this.getInputComponent();
46+
// see com.intellij.openapi.ui.ComponentValidator.updateInfo
47+
input.putClientProperty("JComponent.outline", state);
48+
input.revalidate();
49+
input.repaint();
50+
// see com.intellij.openapi.ui.DialogWrapper.setErrorInfoAll
51+
final ComponentValidator v = ComponentValidator.getInstance(input).orElseGet(() -> (new ComponentValidator(this)).installOn(input));
52+
if (v != null) {
53+
AzureTaskManager.getInstance().runLater(() -> v.updateInfo(info));
54+
}
55+
}
56+
3357
@Override
3458
default String getLabel() {
3559
final JLabel label = (JLabel) this.getInputComponent().getClientProperty(AccessibleRelation.LABELED_BY);
3660
return Optional.ofNullable(label).map(JLabel::getText)
3761
.map(t -> t.endsWith(":") ? t.substring(0, t.length() - 1) : t)
3862
.orElse(this.getClass().getSimpleName());
3963
}
64+
65+
@Nullable
66+
static ValidationInfo toIntellijValidationInfo(@Nullable final AzureValidationInfo info) {
67+
if (Objects.isNull(info)) {
68+
return null;
69+
}
70+
final AzureFormInput<?> input = info.getInput();
71+
final JComponent component = input instanceof AzureFormInputComponent ? ((AzureFormInputComponent<?>) input).getInputComponent() : null;
72+
final ValidationInfo v = new ValidationInfo(Optional.ofNullable(info.getMessage()).orElse("Unknown error"), component);
73+
if (info.getType() == WARNING) {
74+
v.asWarning();
75+
}
76+
return v;
77+
}
78+
79+
@Override
80+
default void dispose() {
81+
this.clearAll();
82+
}
4083
}

0 commit comments

Comments
 (0)