diff --git a/platform/icons/src/ide/errorPoint.png b/platform/icons/src/ide/errorPoint.png new file mode 100644 index 000000000000..2a08c2ff3763 Binary files /dev/null and b/platform/icons/src/ide/errorPoint.png differ diff --git a/platform/icons/src/ide/errorSign.png b/platform/icons/src/ide/errorSign.png new file mode 100644 index 000000000000..d4c199143d96 Binary files /dev/null and b/platform/icons/src/ide/errorSign.png differ diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 7c1ff707c62e..1a9a6810b74e 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -25,6 +25,8 @@ import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.StackingPopupDispatcher; import com.intellij.openapi.util.*; +import com.intellij.openapi.wm.IdeGlassPaneUtil; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.UIBundle; import com.intellij.util.Alarm; @@ -33,6 +35,7 @@ import com.intellij.util.ui.AwtVisitor; import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -193,11 +196,11 @@ public abstract class DialogWrapper { //validation private final Alarm myValidationAlarm = new Alarm(myDisposable); private int myValidationDelay = 300; - private static final String OLD_BORDER = "OLD_BORDER"; - private JComponent myLastErrorComponent = null; private boolean myDisposed = false; - private Boolean myLastPaintButtonBorder = null; private boolean myValidationStarted = false; + private Icon ERROR_POINT = IconLoader.getIcon("/ide/errorPoint.png"); + private Icon ERROR_SIGN = IconLoader.getIcon("/ide/errorSign.png"); + private final ErrorPainter myErrorPainter = new ErrorPainter(); /** * Allows to postpone first start of validation @@ -219,80 +222,30 @@ public abstract class DialogWrapper { return null; } - /** - * Controls components highlighting - * - * @return true for problem components highlighting. false otherwise. - */ - protected boolean isShowErrorBorder() { - return true; - } - - /** - * Specifies border color for error highlighting - * - * @return color for error highlighting - */ - protected Color getErrorColor() { - return Color.RED; - } - public void setValidationDelay(int delay) { myValidationDelay = delay; } - private void reportProblem(final String message, final JComponent comp) { + private void reportProblem(final ValidationInfo info) { + myErrorPainter.setValidationInfo(info); + if (! info.message.equals(myErrorText.myLabel.getText())) { SwingUtilities.invokeLater(new Runnable() { public void run() { - if (myDisposed) return; - if (isShowErrorBorder()) { - if (myLastErrorComponent != comp) { - if (myLastErrorComponent != null) { - myLastErrorComponent.setBorder((Border)myLastErrorComponent.getClientProperty(OLD_BORDER)); - if (myLastErrorComponent instanceof AbstractButton && myLastPaintButtonBorder != null) { - ((AbstractButton)myLastErrorComponent).setBorderPainted(myLastPaintButtonBorder); - } - } - myLastErrorComponent = comp; - if (comp != null) { - if (comp instanceof AbstractButton) { - myLastPaintButtonBorder = ((AbstractButton)comp).isBorderPainted(); - ((AbstractButton)comp).setBorderPainted(true); - } - final Object border = comp.getClientProperty(OLD_BORDER); - if (border == null) { - comp.putClientProperty(OLD_BORDER, comp.getBorder()); - } - comp.setBorder(BorderFactory.createLineBorder(getErrorColor(), 1)); - } - } - } - setErrorText(message); + setErrorText(info.message); + myPeer.getRootPane().getGlassPane().repaint(); getOKAction().setEnabled(false); } - }); } - + } private void clearProblems() { + myErrorPainter.setValidationInfo(null); SwingUtilities.invokeLater(new Runnable() { public void run() { - if (myDisposed) return; setErrorText(null); + myPeer.getRootPane().getGlassPane().repaint(); getOKAction().setEnabled(true); - //if (myLastPeerSize != null) { - // myPeer.setSize(myLastPeerSize.width, myLastPeerSize.height); - // myLastPeerSize = null; - //} - if (myLastErrorComponent != null) { - myLastErrorComponent.setBorder((Border)myLastErrorComponent.getClientProperty(OLD_BORDER)); - if (myLastPaintButtonBorder != null && myLastErrorComponent instanceof AbstractButton) { - ((AbstractButton)myLastErrorComponent).setBorderPainted(myLastPaintButtonBorder); - } - myLastErrorComponent = null; - myLastPaintButtonBorder = null; - } } }); } @@ -924,7 +877,9 @@ public abstract class DialogWrapper { final JComponent c = createCenterPanel(); if (c != null) { - centerSection.add(wrap(c, isCenterStrictedToPreferredSize()), BorderLayout.CENTER); + final JComponent wrap = wrap(c, isCenterStrictedToPreferredSize()); + centerSection.add(wrap, BorderLayout.CENTER); + IdeGlassPaneUtil.installPainter(wrap, myErrorPainter, myDisposable); } final JPanel southSection = new JPanel(new BorderLayout()); @@ -961,7 +916,7 @@ public abstract class DialogWrapper { if (result == null) { clearProblems(); } else { - reportProblem(result.message, result.component); + reportProblem(result); } if (!myDisposed) { @@ -971,17 +926,6 @@ public abstract class DialogWrapper { }, myValidationDelay, ModalityState.current()); } - public static final class ValidationInfo { - public final String message; - public final JComponent component; - - public ValidationInfo(String message, JComponent component) { - this.message = message; - this.component = component; - } - } - - private static JComponent wrap(final JComponent c, boolean strict) { if (!strict) return c; @@ -1521,4 +1465,64 @@ public abstract class DialogWrapper { String getDoNotShowMessage(); } + + private ErrorPaintingType getErrorPaintingType() { + return ErrorPaintingType.SIGN; + } + + private class ErrorPainter extends AbstractPainter { + private ValidationInfo myInfo; + + @Override + public void executePaint(Component component, Graphics2D g) { + if (myInfo != null && myInfo.component != null) { + final JComponent comp = myInfo.component; + final int w = comp.getWidth(); + final int h = comp.getHeight(); + Point p; + switch (getErrorPaintingType()) { + case DOT: + p = SwingUtilities.convertPoint(comp, 2, h/2 , component); + ERROR_POINT.paintIcon(component, g, p.x, p.y); + break; + case SIGN: + p = SwingUtilities.convertPoint(comp, w, 0, component); + ERROR_SIGN.paintIcon(component, g, p.x - 8, p.y - 8); + break; + case LINE: + p = SwingUtilities.convertPoint(comp, 0, h, component); + final GraphicsConfig config = new GraphicsConfig(g); + g.setColor(new Color(255, 0, 0 , 100)); + g.fillRoundRect(p.x, p.y-2, w, 4, 2, 2); + config.restore(); + break; + } + } + } + + @Override + public boolean needsRepaint() { + return true; + } + + public void setValidationInfo(ValidationInfo info) { + myInfo = info; + } + } + + private static enum ErrorPaintingType {DOT, SIGN, LINE} + + public static final class ValidationInfo { + public final String message; + public final JComponent component; + + public ValidationInfo(@NotNull String message, JComponent component) { + this.message = message; + this.component = component; + } + + public ValidationInfo(@NotNull String message) { + this(message, null); + } + } }